Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/cleanup

* git://git.kernel.org/pub/scm/linux/kernel/git/sam/cleanup:
  defconfig reduction
  kbuild: drop unifdef-y support
  archs: replace unifdef-y with header-y
  include: replace unifdef-y with header-y
diff --git a/Documentation/hwmon/emc2103 b/Documentation/hwmon/emc2103
new file mode 100644
index 0000000..a12b2c1
--- /dev/null
+++ b/Documentation/hwmon/emc2103
@@ -0,0 +1,33 @@
+Kernel driver emc2103
+======================
+
+Supported chips:
+  * SMSC EMC2103
+    Addresses scanned: I2C 0x2e
+    Prefix: 'emc2103'
+    Datasheet: Not public
+
+Authors:
+        Steve Glendinning <steve.glendinning@smsc.com>
+
+Description
+-----------
+
+The Standard Microsystems Corporation (SMSC) EMC2103 chips
+contain up to 4 temperature sensors and a single fan controller.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 1, the lowest
+representable value is 480 RPM.
+
+This driver supports RPM based control, to use this a fan target
+should be written to fan1_target and pwm1_enable should be set to 3.
+
+The 2103-2 and 2103-4 variants have a third temperature sensor, which can
+be connected to two anti-parallel diodes.  These values can be read
+as temp3 and temp4.  If only one diode is attached to this channel, temp4
+will show as "fault".  The module parameter "apd=0" can be used to suppress
+this 4th channel when anti-parallel diodes are not fitted.
diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245
index 86b5880..b478b08 100644
--- a/Documentation/hwmon/ltc4245
+++ b/Documentation/hwmon/ltc4245
@@ -72,9 +72,31 @@
 in7_min_alarm		3v  output undervoltage alarm
 in8_min_alarm		Vee (-12v) output undervoltage alarm
 
-in9_input		GPIO voltage data
+in9_input		GPIO voltage data (see note 1)
+in10_input		GPIO voltage data (see note 1)
+in11_input		GPIO voltage data (see note 1)
 
 power1_input		12v power usage (mW)
 power2_input		5v  power usage (mW)
 power3_input		3v  power usage (mW)
 power4_input		Vee (-12v) power usage (mW)
+
+
+Note 1
+------
+
+If you have NOT configured the driver to sample all GPIO pins as analog
+voltages, then the in10_input and in11_input sysfs attributes will not be
+created. The driver will sample the GPIO pin that is currently connected to the
+ADC as an analog voltage, and report the value in in9_input.
+
+If you have configured the driver to sample all GPIO pins as analog voltages,
+then they will be sampled in round-robin fashion. If userspace reads too
+slowly, -EAGAIN will be returned when you read the sysfs attribute containing
+the sensor reading.
+
+The LTC4245 chip can be configured to sample all GPIO pins with two methods:
+1) platform data -- see include/linux/i2c/ltc4245.h
+2) OF device tree -- add the "ltc4245,use-extra-gpios" property to each chip
+
+The default mode of operation is to sample a single GPIO pin.
diff --git a/Documentation/hwmon/pc87427 b/Documentation/hwmon/pc87427
index db5cc12..8fdd08c 100644
--- a/Documentation/hwmon/pc87427
+++ b/Documentation/hwmon/pc87427
@@ -18,10 +18,11 @@
 
 The National Semiconductor Super I/O chip includes complete hardware
 monitoring capabilities. It can monitor up to 18 voltages, 8 fans and
-6 temperature sensors. Only the fans are supported at the moment.
+6 temperature sensors. Only the fans and temperatures are supported at
+the moment, voltages aren't.
 
-This chip also has fan controlling features, which are not yet supported
-by this driver either.
+This chip also has fan controlling features (up to 4 PWM outputs),
+which are partly supported by this driver.
 
 The driver assumes that no more than one chip is present, which seems
 reasonable.
@@ -36,3 +37,23 @@
 An alarm is triggered if the rotation speed drops below a programmable
 limit. Another alarm is triggered if the speed is too low to be measured
 (including stalled or missing fan).
+
+
+Fan Speed Control
+-----------------
+
+Fan speed can be controlled by PWM outputs. There are 4 possible modes:
+always off, always on, manual and automatic. The latter isn't supported
+by the driver: you can only return to that mode if it was the original
+setting, and the configuration interface is missing.
+
+
+Temperature Monitoring
+----------------------
+
+The PC87427 relies on external sensors (following the SensorPath
+standard), so the resolution and range depend on the type of sensor
+connected. The integer part can be 8-bit or 9-bit, and can be signed or
+not. I couldn't find a way to figure out the external sensor data
+temperature format, so user-space adjustment (typically by a factor 2)
+may be required.
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index d4e2917..ff45d1f 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -107,10 +107,24 @@
 		Unit: millivolt
 		RW
 		
+in[0-*]_lcrit	Voltage critical min value.
+		Unit: millivolt
+		RW
+		If voltage drops to or below this limit, the system may
+		take drastic action such as power down or reset. At the very
+		least, it should report a fault.
+
 in[0-*]_max	Voltage max value.
 		Unit: millivolt
 		RW
 		
+in[0-*]_crit	Voltage critical max value.
+		Unit: millivolt
+		RW
+		If voltage reaches or exceeds this limit, the system may
+		take drastic action such as power down or reset. At the very
+		least, it should report a fault.
+
 in[0-*]_input	Voltage input value.
 		Unit: millivolt
 		RO
@@ -284,7 +298,7 @@
 		Unit: millidegree Celsius
 		RO
 
-temp[1-*]_crit	Temperature critical value, typically greater than
+temp[1-*]_crit	Temperature critical max value, typically greater than
 		corresponding temp_max values.
 		Unit: millidegree Celsius
 		RW
@@ -296,6 +310,11 @@
 		from the critical value.
 		RW
 
+temp[1-*]_lcrit	Temperature critical min value, typically lower than
+		corresponding temp_min values.
+		Unit: millidegree Celsius
+		RW
+
 temp[1-*]_offset
 		Temperature offset which is added to the temperature reading
 		by the chip.
@@ -344,9 +363,6 @@
 * Currents *
 ************
 
-Note that no known chip provides current measurements as of writing,
-so this part is theoretical, so to say.
-
 curr[1-*]_max	Current max value
 		Unit: milliampere
 		RW
@@ -471,6 +487,7 @@
 implementation.
 
 in[0-*]_alarm
+curr[1-*]_alarm
 fan[1-*]_alarm
 temp[1-*]_alarm
 		Channel alarm
@@ -482,6 +499,8 @@
 
 in[0-*]_min_alarm
 in[0-*]_max_alarm
+curr[1-*]_min_alarm
+curr[1-*]_max_alarm
 fan[1-*]_min_alarm
 fan[1-*]_max_alarm
 temp[1-*]_min_alarm
@@ -497,7 +516,6 @@
 supports it. When this boolean has value 1, the measurement for that
 channel should not be trusted.
 
-in[0-*]_fault
 fan[1-*]_fault
 temp[1-*]_fault
 		Input fault condition
@@ -513,6 +531,7 @@
 		RW
 
 in[0-*]_beep
+curr[1-*]_beep
 fan[1-*]_beep
 temp[1-*]_beep
 		Channel beep
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index b7e42ec..13d5561 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -20,6 +20,10 @@
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: not available
+  * Winbond W83667HG-B
+    Prefix: 'w83667hg'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
         Jean Delvare <khali@linux-fr.org>
@@ -32,8 +36,8 @@
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P and W83667HG super I/O chips. We will refer to them
-collectively as Winbond chips.
+W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips.
+We will refer to them collectively as Winbond chips.
 
 The chips implement three temperature sensors, five fan rotation
 speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
@@ -68,14 +72,15 @@
 temp1 -> pwm1
 temp2 -> pwm2
 temp3 -> pwm3
-prog  -> pwm4 (not on 667HG; the programmable setting is not supported by
-	       the driver)
+prog  -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
+	       supported by the driver)
 
 /sys files
 ----------
 
 name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
-       it is set to "w83627ehf" and for the W83627DHG it is set to "w83627dhg"
+       it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
+       and for the W83667HG it is set to "w83667hg".
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 873b680..4956686 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -88,8 +88,8 @@
 	RAM	RAM disk support is enabled.
 	S390	S390 architecture is enabled.
 	SCSI	Appropriate SCSI support is enabled.
-			A lot of drivers has their options described inside of
-			Documentation/scsi/.
+			A lot of drivers have their options described inside
+			the Documentation/scsi/ sub-directory.
 	SECURITY Different security models are enabled.
 	SELINUX SELinux support is enabled.
 	APPARMOR AppArmor support is enabled.
@@ -284,27 +284,12 @@
 	add_efi_memmap	[EFI; X86] Include EFI memory map in
 			kernel's map of available physical RAM.
 
-	advansys=	[HW,SCSI]
-			See header of drivers/scsi/advansys.c.
-
 	agp=		[AGP]
 			{ off | try_unsupported }
 			off: disable AGP support
 			try_unsupported: try to drive unsupported chipsets
 				(may crash computer or cause data corruption)
 
-	aha152x=	[HW,SCSI]
-			See Documentation/scsi/aha152x.txt.
-
-	aha1542=	[HW,SCSI]
-			Format: <portbase>[,<buson>,<busoff>[,<dmaspeed>]]
-
-	aic7xxx=	[HW,SCSI]
-			See Documentation/scsi/aic7xxx.txt.
-
-	aic79xx=	[HW,SCSI]
-			See Documentation/scsi/aic79xx.txt.
-
 	ALSA		[HW,ALSA]
 			See Documentation/sound/alsa/alsa-parameters.txt
 
@@ -368,8 +353,6 @@
 
 	atarimouse=	[HW,MOUSE] Atari Mouse
 
-	atascsi=	[HW,SCSI] Atari SCSI
-
 	atkbd.extra=	[HW] Enable extra LEDs and keys on IBM RapidAccess,
 			EzKey and similar keyboards
 
@@ -419,10 +402,6 @@
 	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
 	bttv.tuner=	and Documentation/video4linux/bttv/CARDLIST
 
-	BusLogic=	[HW,SCSI]
-			See drivers/scsi/BusLogic.c, comment before function
-			BusLogic_ParseDriverOptions().
-
 	c101=		[NET] Moxa C101 synchronous serial card
 
 	cachesize=	[BUGS=X86-32] Override level 2 CPU cache size detection.
@@ -671,8 +650,6 @@
 
 	dscc4.setup=	[NET]
 
-	dtc3181e=	[HW,SCSI]
-
 	dynamic_printk	Enables pr_debug()/dev_dbg() calls if
 			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
 			These can also be switched on/off via
@@ -713,8 +690,6 @@
 			This is desgined to be used in conjunction with
 			the boot argument: earlyprintk=vga
 
-	eata=		[HW,SCSI]
-
 	edd=		[EDD]
 			Format: {"off" | "on" | "skip[mbr]"}
 
@@ -770,12 +745,6 @@
 			Format: <interval>,<probability>,<space>,<times>
 			See also /Documentation/fault-injection/.
 
-	fd_mcs=		[HW,SCSI]
-			See header of drivers/scsi/fd_mcs.c.
-
-	fdomain=	[HW,SCSI]
-			See header of drivers/scsi/fdomain.c.
-
 	floppy=		[HW]
 			See Documentation/blockdev/floppy.txt.
 
@@ -835,14 +804,9 @@
 			When zero, profiling data is discarded and associated
 			debugfs files are removed at module unload time.
 
-	gdth=		[HW,SCSI]
-			See header of drivers/scsi/gdth.c.
-
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
-	gvp11=		[HW,SCSI]
-
 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
 			are distributed across NUMA nodes.  Defaults on
 			for 64bit NUMA, off otherwise.
@@ -931,9 +895,6 @@
 	i8k.restricted	[HW] Allow controlling fans only if SYS_ADMIN
 			capability is set.
 
-	ibmmcascsi=	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter
-			See Documentation/mca.txt.
-
 	icn=		[HW,ISDN]
 			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
 
@@ -983,9 +944,6 @@
 			programs exec'd, files mmap'd for exec, and all files
 			opened for read by uid=0.
 
-	in2000=		[HW,SCSI]
-			See header of drivers/scsi/in2000.c.
-
 	init=		[KNL]
 			Format: <full_path>
 			Run specified binary instead of /sbin/init as init
@@ -1063,9 +1021,6 @@
 			See comment before ip2_setup() in
 			drivers/char/ip2/ip2base.c.
 
-	ips=		[HW,SCSI] Adaptec / IBM ServeRAID controller
-			See header of drivers/scsi/ips.c.
-
 	irqfixup	[HW]
 			When an interrupt is not handled search all handlers
 			for it. Intended to get systems with badly broken
@@ -1341,9 +1296,6 @@
 	ltpc=		[NET]
 			Format: <io>,<irq>,<dma>
 
-	mac5380=	[HW,SCSI] Format:
-			<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
-
 	machvec=	[IA64] Force the use of a particular machine-vector
 			(machvec) in a generic kernel.
 			Example: machvec=hpzx1_swiotlb
@@ -1365,13 +1317,6 @@
 			be mounted
 			Format: <1-256>
 
-	max_luns=	[SCSI] Maximum number of LUNs to probe.
-			Should be between 1 and 2^32-1.
-
-	max_report_luns=
-			[SCSI] Maximum number of LUNs received.
-			Should be between 1 and 16384.
-
 	mcatest=	[IA-64]
 
 	mce		[X86-32] Machine Check Exception
@@ -1568,19 +1513,6 @@
 
 	n2=		[NET] SDL Inc. RISCom/N2 synchronous serial card
 
-	NCR_D700=	[HW,SCSI]
-			See header of drivers/scsi/NCR_D700.c.
-
-	ncr5380=	[HW,SCSI]
-
-	ncr53c400=	[HW,SCSI]
-
-	ncr53c400a=	[HW,SCSI]
-
-	ncr53c406a=	[HW,SCSI]
-
-	ncr53c8xx=	[HW,SCSI]
-
 	netdev=		[NET] Network devices parameters
 			Format: <irq>,<io>,<mem_start>,<mem_end>,<name>
 			Note that mem_start is often overloaded to mean
@@ -1859,10 +1791,6 @@
 	OSS		[HW,OSS]
 			See Documentation/sound/oss/oss-parameters.txt
 
-	osst=		[HW,SCSI] SCSI Tape Driver
-			Format: <buffer_size>,<write_threshold>
-			See also Documentation/scsi/st.txt.
-
 	panic=		[KNL] Kernel behaviour on panic
 			Format: <timeout>
 
@@ -1895,9 +1823,6 @@
 			Currently this function knows 686a and 8231 chips.
 			Format: [spp|ps2|epp|ecp|ecpepp]
 
-	pas16=		[HW,SCSI]
-			See header of drivers/scsi/pas16.c.
-
 	pause_on_oops=
 			Halt all CPUs after the first oops has been printed for
 			the specified number of seconds.  This is to be used if
@@ -2264,30 +2189,6 @@
 
 	sched_debug	[KNL] Enables verbose scheduler debug messages.
 
-	scsi_debug_*=	[SCSI]
-			See drivers/scsi/scsi_debug.c.
-
-	scsi_default_dev_flags=
-			[SCSI] SCSI default device flags
-			Format: <integer>
-
-	scsi_dev_flags=	[SCSI] Black/white list entry for vendor and model
-			Format: <vendor>:<model>:<flags>
-			(flags are integer value)
-
-	scsi_logging_level=	[SCSI] a bit mask of logging levels
-			See drivers/scsi/scsi_logging.h for bits.  Also
-			settable via sysctl at dev.scsi.logging_level
-			(/proc/sys/dev/scsi/logging_level).
-			There is also a nice 'scsi_logging_level' script in the
-			S390-tools package, available for download at
-			http://www-128.ibm.com/developerworks/linux/linux390/s390-tools-1.5.4.html
-
-	scsi_mod.scan=	[SCSI] sync (default) scans SCSI busses as they are
-			discovered.  async scans them in kernel threads,
-			allowing boot to proceed.  none ignores them, expecting
-			user space to do the scan.
-
 	security=	[SECURITY] Choose a security module to enable at boot.
 			If this boot parameter is not specified, only the first
 			security module asking for security registration will be
@@ -2321,9 +2222,6 @@
 			The parameter means the number of CPUs to show,
 			for example 1 means boot CPU only.
 
-	sim710=		[SCSI,HW]
-			See header of drivers/scsi/sim710.c.
-
 	simeth=		[IA-64]
 	simscsi=
 
@@ -2395,9 +2293,6 @@
 	spia_pedr=
 	spia_peddr=
 
-	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
-			See Documentation/scsi/st.txt.
-
 	stacktrace	[FTRACE]
 			Enabled the stack tracer on boot up.
 
@@ -2455,18 +2350,12 @@
 
 	switches=	[HW,M68k]
 
-	sym53c416=	[HW,SCSI]
-			See header of drivers/scsi/sym53c416.c.
-
 	sysrq_always_enabled
 			[KNL]
 			Ignore sysrq setting - this boot parameter will
 			neutralize any effect of /proc/sys/kernel/sysrq.
 			Useful for debugging.
 
-	t128=		[HW,SCSI]
-			See header of drivers/scsi/t128.c.
-
 	tdfx=		[HW,DRM]
 
 	test_suspend=	[SUSPEND]
@@ -2503,10 +2392,6 @@
 			<deci-seconds>: poll all this frequency
 			0: no polling (default)
 
-	tmscsim=	[HW,SCSI]
-			See comment before function dc390_setup() in
-			drivers/scsi/tmscsim.c.
-
 	topology=	[S390]
 			Format: {off | on}
 			Specify if the kernel should make use of the cpu
@@ -2547,9 +2432,6 @@
 			<port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
 			See also Documentation/input/joystick-parport.txt
 
-	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
-			See header of drivers/scsi/u14-34f.c.
-
 	uhash_entries=	[KNL,NET]
 			Set number of hash buckets for UDP/UDP-Lite connections
 
@@ -2715,12 +2597,6 @@
 			overridden by individual drivers. 0 will hide
 			cursors, 1 will display them.
 
-	wd33c93=	[HW,SCSI]
-			See header of drivers/scsi/wd33c93.c.
-
-	wd7000=		[HW,SCSI]
-			See header of drivers/scsi/wd7000.c.
-
 	watchdog timers	[HW,WDT] For information on watchdog timers,
 			see Documentation/watchdog/watchdog-parameters.txt
 			or other driver-specific files in the
diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt
new file mode 100644
index 0000000..21e5798
--- /dev/null
+++ b/Documentation/scsi/scsi-parameters.txt
@@ -0,0 +1,139 @@
+                          SCSI Kernel Parameters
+                          ~~~~~~~~~~~~~~~~~~~~~~
+
+See Documentation/kernel-parameters.txt for general information on
+specifying module parameters.
+
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+
+	advansys=	[HW,SCSI]
+			See header of drivers/scsi/advansys.c.
+
+	aha152x=	[HW,SCSI]
+			See Documentation/scsi/aha152x.txt.
+
+	aha1542=	[HW,SCSI]
+			Format: <portbase>[,<buson>,<busoff>[,<dmaspeed>]]
+
+	aic7xxx=	[HW,SCSI]
+			See Documentation/scsi/aic7xxx.txt.
+
+	aic79xx=	[HW,SCSI]
+			See Documentation/scsi/aic79xx.txt.
+
+	atascsi=	[HW,SCSI] Atari SCSI
+
+	BusLogic=	[HW,SCSI]
+			See drivers/scsi/BusLogic.c, comment before function
+			BusLogic_ParseDriverOptions().
+
+	dtc3181e=	[HW,SCSI]
+
+	eata=		[HW,SCSI]
+
+	fd_mcs=		[HW,SCSI]
+			See header of drivers/scsi/fd_mcs.c.
+
+	fdomain=	[HW,SCSI]
+			See header of drivers/scsi/fdomain.c.
+
+	gdth=		[HW,SCSI]
+			See header of drivers/scsi/gdth.c.
+
+	gvp11=		[HW,SCSI]
+
+	ibmmcascsi=	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter
+			See Documentation/mca.txt.
+
+	in2000=		[HW,SCSI]
+			See header of drivers/scsi/in2000.c.
+
+	ips=		[HW,SCSI] Adaptec / IBM ServeRAID controller
+			See header of drivers/scsi/ips.c.
+
+	mac5380=	[HW,SCSI] Format:
+			<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
+
+	max_luns=	[SCSI] Maximum number of LUNs to probe.
+			Should be between 1 and 2^32-1.
+
+	max_report_luns=
+			[SCSI] Maximum number of LUNs received.
+			Should be between 1 and 16384.
+
+	NCR_D700=	[HW,SCSI]
+			See header of drivers/scsi/NCR_D700.c.
+
+	ncr5380=	[HW,SCSI]
+
+	ncr53c400=	[HW,SCSI]
+
+	ncr53c400a=	[HW,SCSI]
+
+	ncr53c406a=	[HW,SCSI]
+
+	ncr53c8xx=	[HW,SCSI]
+
+	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
+
+	osst=		[HW,SCSI] SCSI Tape Driver
+			Format: <buffer_size>,<write_threshold>
+			See also Documentation/scsi/st.txt.
+
+	pas16=		[HW,SCSI]
+			See header of drivers/scsi/pas16.c.
+
+	scsi_debug_*=	[SCSI]
+			See drivers/scsi/scsi_debug.c.
+
+	scsi_default_dev_flags=
+			[SCSI] SCSI default device flags
+			Format: <integer>
+
+	scsi_dev_flags=	[SCSI] Black/white list entry for vendor and model
+			Format: <vendor>:<model>:<flags>
+			(flags are integer value)
+
+	scsi_logging_level=	[SCSI] a bit mask of logging levels
+			See drivers/scsi/scsi_logging.h for bits.  Also
+			settable via sysctl at dev.scsi.logging_level
+			(/proc/sys/dev/scsi/logging_level).
+			There is also a nice 'scsi_logging_level' script in the
+			S390-tools package, available for download at
+			http://www-128.ibm.com/developerworks/linux/linux390/s390-tools-1.5.4.html
+
+	scsi_mod.scan=	[SCSI] sync (default) scans SCSI busses as they are
+			discovered.  async scans them in kernel threads,
+			allowing boot to proceed.  none ignores them, expecting
+			user space to do the scan.
+
+	sim710=		[SCSI,HW]
+			See header of drivers/scsi/sim710.c.
+
+	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
+			See Documentation/scsi/st.txt.
+
+	sym53c416=	[HW,SCSI]
+			See header of drivers/scsi/sym53c416.c.
+
+	t128=		[HW,SCSI]
+			See header of drivers/scsi/t128.c.
+
+	tmscsim=	[HW,SCSI]
+			See comment before function dc390_setup() in
+			drivers/scsi/tmscsim.c.
+
+	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
+			See header of drivers/scsi/u14-34f.c.
+
+	wd33c93=	[HW,SCSI]
+			See header of drivers/scsi/wd33c93.c.
+
+	wd7000=		[HW,SCSI]
+			See header of drivers/scsi/wd7000.c.
diff --git a/MAINTAINERS b/MAINTAINERS
index 39d8c5c..99b6f82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4402,6 +4402,13 @@
 S:	Maintained
 F:	drivers/char/pc8736x_gpio.c
 
+PC87427 HARDWARE MONITORING DRIVER
+M:	Jean Delvare <khali@linux-fr.org>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/pc87427
+F:	drivers/hwmon/pc87427.c
+
 PCA9532 LED DRIVER
 M:	Riku Voipio <riku.voipio@iki.fi>
 S:	Maintained
@@ -5279,6 +5286,13 @@
 F:	Documentation/hwmon/smm665
 F:	drivers/hwmon/smm665.c
 
+SMSC EMC2103 HARDWARE MONITOR DRIVER
+M:	Steve Glendinning <steve.glendinning@smsc.com>
+L:	lm-sensors@lm-sensors.org
+S:	Supported
+F:	Documentation/hwmon/emc2103
+F:	drivers/hwmon/emc2103.c
+
 SMSC47B397 HARDWARE MONITOR DRIVER
 M:	"Mark M. Hoffman" <mhoffman@lightlink.com>
 L:	lm-sensors@lm-sensors.org
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f3adf18..0fba829 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -465,6 +465,7 @@
 
 config SENSORS_JC42
 	tristate "JEDEC JC42.4 compliant temperature sensors"
+	depends on I2C
 	help
 	  If you say yes here you get support for Jedec JC42.4 compliant
 	  temperature sensors. Support will include, but not be limited to,
@@ -711,7 +712,8 @@
 	  functions of the National Semiconductor PC87427 Super-I/O chip.
 	  The chip has two distinct logical devices, one for fan speed
 	  monitoring and control, and one for voltage and temperature
-	  monitoring. Only fan speed monitoring is supported right now.
+	  monitoring. Fan speed monitoring and control are supported, as
+	  well as temperature monitoring. Voltages aren't supported yet.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called pc87427.
@@ -804,6 +806,16 @@
 	  Threshold values can be configured using sysfs.
 	  Data from the different diodes are accessible via sysfs.
 
+config SENSORS_EMC2103
+	tristate "SMSC EMC2103"
+	depends on I2C
+	help
+	  If you say yes here you get support for the temperature
+	  and fan sensors of the SMSC EMC2103 chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called emc2103.
+
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
 	help
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 13d913e..e3c2484 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -43,6 +43,7 @@
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
+obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 3b973f3..89b4f3b 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -1150,9 +1150,6 @@
 {
 	struct i2c_adapter *adapter = client->adapter;
 	int company, verstep, chip_index;
-	struct device *dev;
-
-	dev = &client->dev;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -1169,13 +1166,11 @@
 
 		if (company == asc7621_chips[chip_index].company_id &&
 		    verstep == asc7621_chips[chip_index].verstep_id) {
-			strlcpy(client->name, asc7621_chips[chip_index].name,
-				I2C_NAME_SIZE);
 			strlcpy(info->type, asc7621_chips[chip_index].name,
 				I2C_NAME_SIZE);
 
-			dev_info(&adapter->dev, "Matched %s\n",
-				 asc7621_chips[chip_index].name);
+			dev_info(&adapter->dev, "Matched %s at 0x%02x\n",
+				 asc7621_chips[chip_index].name, client->addr);
 			return 0;
 		}
 	}
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index 0e4b564..5b58b20 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -89,6 +89,35 @@
 	return count;
 }
 
+static ssize_t store_bit(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct thermal_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
+	unsigned long val;
+	int retval;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	mutex_lock(&data->mutex);
+	retval = i2c_smbus_read_byte_data(client, sda->nr);
+	if (retval < 0)
+		goto fail;
+
+	retval &= ~sda->index;
+	if (val)
+		retval |= sda->index;
+
+	retval = i2c_smbus_write_byte_data(client, sda->index, retval);
+	if (retval == 0)
+		retval = count;
+fail:
+	mutex_unlock(&data->mutex);
+	return retval;
+}
+
 static ssize_t show_hyst(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
@@ -200,6 +229,9 @@
 static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,
 	show_hyst, store_hyst, 0x1A);
 
+static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR,
+	show_bit, store_bit, 0x03, 0x40);
+
 static struct attribute *mid_att_thermal[] = {
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -225,6 +257,7 @@
 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_power_state.dev_attr.attr,
 	NULL
 };
 
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
new file mode 100644
index 0000000..af914ad
--- /dev/null
+++ b/drivers/hwmon/emc2103.c
@@ -0,0 +1,740 @@
+/*
+    emc2103.c - Support for SMSC EMC2103
+    Copyright (c) 2010 SMSC
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END };
+
+static const u8 REG_TEMP[4] = { 0x00, 0x02, 0x04, 0x06 };
+static const u8 REG_TEMP_MIN[4] = { 0x3c, 0x38, 0x39, 0x3a };
+static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 };
+
+#define REG_CONF1		0x20
+#define REG_TEMP_MAX_ALARM	0x24
+#define REG_TEMP_MIN_ALARM	0x25
+#define REG_FAN_CONF1		0x42
+#define REG_FAN_TARGET_LO	0x4c
+#define REG_FAN_TARGET_HI	0x4d
+#define REG_FAN_TACH_HI		0x4e
+#define REG_FAN_TACH_LO		0x4f
+#define REG_PRODUCT_ID		0xfd
+#define REG_MFG_ID		0xfe
+
+/* equation 4 from datasheet: rpm = (3932160 * multipler) / count */
+#define FAN_RPM_FACTOR		3932160
+
+/* 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes
+ * in anti-parallel mode, and in this configuration both can be read
+ * independently (so we have 4 temperature inputs).  The device can't
+ * detect if it's connected in this mode, so we have to manually enable
+ * it.  Default is to leave the device in the state it's already in (-1).
+ * This parameter allows APD mode to be optionally forced on or off */
+static int apd = -1;
+module_param(apd, bool, 0);
+MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode");
+
+struct temperature {
+	s8	degrees;
+	u8	fraction;	/* 0-7 multiples of 0.125 */
+};
+
+struct emc2103_data {
+	struct device		*hwmon_dev;
+	struct mutex		update_lock;
+	bool			valid;		/* registers are valid */
+	bool			fan_rpm_control;
+	int			temp_count;	/* num of temp sensors */
+	unsigned long		last_updated;	/* in jiffies */
+	struct temperature	temp[4];	/* internal + 3 external */
+	s8			temp_min[4];	/* no fractional part */
+	s8			temp_max[4];    /* no fractional part */
+	u8			temp_min_alarm;
+	u8			temp_max_alarm;
+	u8			fan_multiplier;
+	u16			fan_tach;
+	u16			fan_target;
+};
+
+static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output)
+{
+	int status = i2c_smbus_read_byte_data(client, i2c_reg);
+	if (status < 0) {
+		dev_warn(&client->dev, "reg 0x%02x, err %d\n",
+			i2c_reg, status);
+	} else {
+		*output = status;
+	}
+	return status;
+}
+
+static void read_temp_from_i2c(struct i2c_client *client, u8 i2c_reg,
+			       struct temperature *temp)
+{
+	u8 degrees, fractional;
+
+	if (read_u8_from_i2c(client, i2c_reg, &degrees) < 0)
+		return;
+
+	if (read_u8_from_i2c(client, i2c_reg + 1, &fractional) < 0)
+		return;
+
+	temp->degrees = degrees;
+	temp->fraction = (fractional & 0xe0) >> 5;
+}
+
+static void read_fan_from_i2c(struct i2c_client *client, u16 *output,
+			      u8 hi_addr, u8 lo_addr)
+{
+	u8 high_byte, lo_byte;
+
+	if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0)
+		return;
+
+	if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0)
+		return;
+
+	*output = ((u16)high_byte << 5) | (lo_byte >> 3);
+}
+
+static void write_fan_target_to_i2c(struct i2c_client *client, u16 new_target)
+{
+	u8 high_byte = (new_target & 0x1fe0) >> 5;
+	u8 low_byte = (new_target & 0x001f) << 3;
+	i2c_smbus_write_byte_data(client, REG_FAN_TARGET_LO, low_byte);
+	i2c_smbus_write_byte_data(client, REG_FAN_TARGET_HI, high_byte);
+}
+
+static void read_fan_config_from_i2c(struct i2c_client *client)
+
+{
+	struct emc2103_data *data = i2c_get_clientdata(client);
+	u8 conf1;
+
+	if (read_u8_from_i2c(client, REG_FAN_CONF1, &conf1) < 0)
+		return;
+
+	data->fan_multiplier = 1 << ((conf1 & 0x60) >> 5);
+	data->fan_rpm_control = (conf1 & 0x80) != 0;
+}
+
+static struct emc2103_data *emc2103_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct emc2103_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		int i;
+
+		for (i = 0; i < data->temp_count; i++) {
+			read_temp_from_i2c(client, REG_TEMP[i], &data->temp[i]);
+			read_u8_from_i2c(client, REG_TEMP_MIN[i],
+				&data->temp_min[i]);
+			read_u8_from_i2c(client, REG_TEMP_MAX[i],
+				&data->temp_max[i]);
+		}
+
+		read_u8_from_i2c(client, REG_TEMP_MIN_ALARM,
+			&data->temp_min_alarm);
+		read_u8_from_i2c(client, REG_TEMP_MAX_ALARM,
+			&data->temp_max_alarm);
+
+		read_fan_from_i2c(client, &data->fan_tach,
+			REG_FAN_TACH_HI, REG_FAN_TACH_LO);
+		read_fan_from_i2c(client, &data->fan_target,
+			REG_FAN_TARGET_HI, REG_FAN_TARGET_LO);
+		read_fan_config_from_i2c(client);
+
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int millidegrees = data->temp[nr].degrees * 1000
+		+ data->temp[nr].fraction * 125;
+	return sprintf(buf, "%d\n", millidegrees);
+}
+
+static ssize_t
+show_temp_min(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int millidegrees = data->temp_min[nr] * 1000;
+	return sprintf(buf, "%d\n", millidegrees);
+}
+
+static ssize_t
+show_temp_max(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int millidegrees = data->temp_max[nr] * 1000;
+	return sprintf(buf, "%d\n", millidegrees);
+}
+
+static ssize_t
+show_temp_fault(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	bool fault = (data->temp[nr].degrees == -128);
+	return sprintf(buf, "%d\n", fault ? 1 : 0);
+}
+
+static ssize_t
+show_temp_min_alarm(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	bool alarm = data->temp_min_alarm & (1 << nr);
+	return sprintf(buf, "%d\n", alarm ? 1 : 0);
+}
+
+static ssize_t
+show_temp_max_alarm(struct device *dev, struct device_attribute *da, char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct emc2103_data *data = emc2103_update_device(dev);
+	bool alarm = data->temp_max_alarm & (1 << nr);
+	return sprintf(buf, "%d\n", alarm ? 1 : 0);
+}
+
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *da,
+			    const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct emc2103_data *data = i2c_get_clientdata(client);
+	long val;
+
+	int result = strict_strtol(buf, 10, &val);
+	if (result < 0)
+		return -EINVAL;
+
+	val = DIV_ROUND_CLOSEST(val, 1000);
+	if ((val < -63) || (val > 127))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->temp_min[nr] = val;
+	i2c_smbus_write_byte_data(client, REG_TEMP_MIN[nr], val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *da,
+			    const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct emc2103_data *data = i2c_get_clientdata(client);
+	long val;
+
+	int result = strict_strtol(buf, 10, &val);
+	if (result < 0)
+		return -EINVAL;
+
+	val = DIV_ROUND_CLOSEST(val, 1000);
+	if ((val < -63) || (val > 127))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->temp_max[nr] = val;
+	i2c_smbus_write_byte_data(client, REG_TEMP_MAX[nr], val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int rpm = 0;
+	if (data->fan_tach != 0)
+		rpm = (FAN_RPM_FACTOR * data->fan_multiplier) / data->fan_tach;
+	return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int fan_div = 8 / data->fan_multiplier;
+	return sprintf(buf, "%d\n", fan_div);
+}
+
+/* Note: we also update the fan target here, because its value is
+   determined in part by the fan clock divider.  This follows the principle
+   of least surprise; the user doesn't expect the fan target to change just
+   because the divider changed. */
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	int new_range_bits, old_div = 8 / data->fan_multiplier;
+	long new_div;
+
+	int status = strict_strtol(buf, 10, &new_div);
+	if (status < 0)
+		return -EINVAL;
+
+	if (new_div == old_div) /* No change */
+		return count;
+
+	switch (new_div) {
+	case 1:
+		new_range_bits = 3;
+		break;
+	case 2:
+		new_range_bits = 2;
+		break;
+	case 4:
+		new_range_bits = 1;
+		break;
+	case 8:
+		new_range_bits = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+
+	status = i2c_smbus_read_byte_data(client, REG_FAN_CONF1);
+	if (status < 0) {
+		dev_dbg(&client->dev, "reg 0x%02x, err %d\n",
+			REG_FAN_CONF1, status);
+		mutex_unlock(&data->update_lock);
+		return -EIO;
+	}
+	status &= 0x9F;
+	status |= (new_range_bits << 5);
+	i2c_smbus_write_byte_data(client, REG_FAN_CONF1, status);
+
+	data->fan_multiplier = 8 / new_div;
+
+	/* update fan target if high byte is not disabled */
+	if ((data->fan_target & 0x1fe0) != 0x1fe0) {
+		u16 new_target = (data->fan_target * old_div) / new_div;
+		data->fan_target = min(new_target, (u16)0x1fff);
+		write_fan_target_to_i2c(client, data->fan_target);
+	}
+
+	/* invalidate data to force re-read from hardware */
+	data->valid = false;
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_fan_target(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	int rpm = 0;
+
+	/* high byte of 0xff indicates disabled so return 0 */
+	if ((data->fan_target != 0) && ((data->fan_target & 0x1fe0) != 0x1fe0))
+		rpm = (FAN_RPM_FACTOR * data->fan_multiplier)
+			/ data->fan_target;
+
+	return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t set_fan_target(struct device *dev, struct device_attribute *da,
+			      const char *buf, size_t count)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	long rpm_target;
+
+	int result = strict_strtol(buf, 10, &rpm_target);
+	if (result < 0)
+		return -EINVAL;
+
+	/* Datasheet states 16384 as maximum RPM target (table 3.2) */
+	if ((rpm_target < 0) || (rpm_target > 16384))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	if (rpm_target == 0)
+		data->fan_target = 0x1fff;
+	else
+		data->fan_target = SENSORS_LIMIT(
+			(FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target,
+			0, 0x1fff);
+
+	write_fan_target_to_i2c(client, data->fan_target);
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_fan_fault(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	bool fault = ((data->fan_tach & 0x1fe0) == 0x1fe0);
+	return sprintf(buf, "%d\n", fault ? 1 : 0);
+}
+
+static ssize_t
+show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct emc2103_data *data = emc2103_update_device(dev);
+	return sprintf(buf, "%d\n", data->fan_rpm_control ? 3 : 0);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da,
+			      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct emc2103_data *data = i2c_get_clientdata(client);
+	long new_value;
+	u8 conf_reg;
+
+	int result = strict_strtol(buf, 10, &new_value);
+	if (result < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	switch (new_value) {
+	case 0:
+		data->fan_rpm_control = false;
+		break;
+	case 3:
+		data->fan_rpm_control = true;
+		break;
+	default:
+		mutex_unlock(&data->update_lock);
+		return -EINVAL;
+	}
+
+	read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg);
+
+	if (data->fan_rpm_control)
+		conf_reg |= 0x80;
+	else
+		conf_reg &= ~0x80;
+
+	i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg);
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp_min,
+	set_temp_min, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max,
+	set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm,
+	NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm,
+	NULL, 0);
+
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, show_temp_min,
+	set_temp_min, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
+	set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm,
+	NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm,
+	NULL, 1);
+
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, show_temp_min,
+	set_temp_min, 2);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
+	set_temp_max, 2);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm,
+	NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm,
+	NULL, 2);
+
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR, show_temp_min,
+	set_temp_min, 3);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max,
+	set_temp_max, 3);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_temp_min_alarm,
+	NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_temp_max_alarm,
+	NULL, 3);
+
+static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL);
+static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div, set_fan_div);
+static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_fan_target,
+	set_fan_target);
+static DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL);
+
+static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
+	set_pwm_enable);
+
+/* sensors present on all models */
+static struct attribute *emc2103_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan1_target.attr,
+	&dev_attr_fan1_fault.attr,
+	&dev_attr_pwm1_enable.attr,
+	NULL
+};
+
+/* extra temperature sensors only present on 2103-2 and 2103-4 */
+static struct attribute *emc2103_attributes_temp3[] = {
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+	NULL
+};
+
+/* extra temperature sensors only present on 2103-2 and 2103-4 in APD mode */
+static struct attribute *emc2103_attributes_temp4[] = {
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_min.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group emc2103_group = {
+	.attrs = emc2103_attributes,
+};
+
+static const struct attribute_group emc2103_temp3_group = {
+	.attrs = emc2103_attributes_temp3,
+};
+
+static const struct attribute_group emc2103_temp4_group = {
+	.attrs = emc2103_attributes_temp4,
+};
+
+static int
+emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct emc2103_data *data;
+	int status;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */
+	status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID);
+	if (status == 0x24) {
+		/* 2103-1 only has 1 external diode */
+		data->temp_count = 2;
+	} else {
+		/* 2103-2 and 2103-4 have 3 or 4 external diodes */
+		status = i2c_smbus_read_byte_data(client, REG_CONF1);
+		if (status < 0) {
+			dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1,
+				status);
+			goto exit_free;
+		}
+
+		/* detect current state of hardware */
+		data->temp_count = (status & 0x01) ? 4 : 3;
+
+		/* force APD state if module parameter is set */
+		if (apd == 0) {
+			/* force APD mode off */
+			data->temp_count = 3;
+			status &= ~(0x01);
+			i2c_smbus_write_byte_data(client, REG_CONF1, status);
+		} else if (apd == 1) {
+			/* force APD mode on */
+			data->temp_count = 4;
+			status |= 0x01;
+			i2c_smbus_write_byte_data(client, REG_CONF1, status);
+		}
+	}
+
+	/* Register sysfs hooks */
+	status = sysfs_create_group(&client->dev.kobj, &emc2103_group);
+	if (status)
+		goto exit_free;
+
+	if (data->temp_count >= 3) {
+		status = sysfs_create_group(&client->dev.kobj,
+			&emc2103_temp3_group);
+		if (status)
+			goto exit_remove;
+	}
+
+	if (data->temp_count == 4) {
+		status = sysfs_create_group(&client->dev.kobj,
+			&emc2103_temp4_group);
+		if (status)
+			goto exit_remove_temp3;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		status = PTR_ERR(data->hwmon_dev);
+		goto exit_remove_temp4;
+	}
+
+	dev_info(&client->dev, "%s: sensor '%s'\n",
+		 dev_name(data->hwmon_dev), client->name);
+
+	return 0;
+
+exit_remove_temp4:
+	if (data->temp_count == 4)
+		sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
+exit_remove_temp3:
+	if (data->temp_count >= 3)
+		sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
+exit_free:
+	kfree(data);
+	return status;
+}
+
+static int emc2103_remove(struct i2c_client *client)
+{
+	struct emc2103_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	if (data->temp_count == 4)
+		sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
+
+	if (data->temp_count >= 3)
+		sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
+
+	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
+
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id emc2103_ids[] = {
+	{ "emc2103", 0, },
+	{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, emc2103_ids);
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int
+emc2103_detect(struct i2c_client *new_client, struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = new_client->adapter;
+	int manufacturer, product;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	manufacturer = i2c_smbus_read_byte_data(new_client, REG_MFG_ID);
+	if (manufacturer != 0x5D)
+		return -ENODEV;
+
+	product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID);
+	if ((product != 0x24) && (product != 0x26))
+		return -ENODEV;
+
+	strlcpy(info->type, "emc2103", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static struct i2c_driver emc2103_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "emc2103",
+	},
+	.probe		= emc2103_probe,
+	.remove		= emc2103_remove,
+	.id_table	= emc2103_ids,
+	.detect		= emc2103_detect,
+	.address_list	= normal_i2c,
+};
+
+static int __init sensors_emc2103_init(void)
+{
+	return i2c_add_driver(&emc2103_driver);
+}
+
+static void __exit sensors_emc2103_exit(void)
+{
+	i2c_del_driver(&emc2103_driver);
+}
+
+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
+MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_emc2103_init);
+module_exit(sensors_emc2103_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 25763d2..f770129 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -259,6 +259,7 @@
 	u8 revision;
 	u8 vid_value;
 	u8 beep_pin;
+	u8 internal;	/* Internal sensors can be labeled */
 	/* Features skipped based on config or DMI */
 	u8 skip_vid;
 	u8 skip_fan;
@@ -1194,6 +1195,22 @@
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
+static ssize_t show_label(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	static const char *labels[] = {
+		"+5V",
+		"5VSB",
+		"Vbat",
+	};
+	int nr = to_sensor_dev_attr(attr)->index;
+
+	return sprintf(buf, "%s\n", labels[nr]);
+}
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
+
 static ssize_t show_name(struct device *dev, struct device_attribute
 			 *devattr, char *buf)
 {
@@ -1434,6 +1451,17 @@
 	.attrs = it87_attributes_vid,
 };
 
+static struct attribute *it87_attributes_label[] = {
+	&sensor_dev_attr_in3_label.dev_attr.attr,
+	&sensor_dev_attr_in7_label.dev_attr.attr,
+	&sensor_dev_attr_in8_label.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group it87_group_label = {
+	.attrs = it87_attributes_vid,
+};
+
 /* SuperIO detection - will change isa_address if a chip is found */
 static int __init it87_find(unsigned short *address,
 	struct it87_sio_data *sio_data)
@@ -1487,6 +1515,9 @@
 	pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
 		chip_type, *address, sio_data->revision);
 
+	/* in8 (Vbat) is always internal */
+	sio_data->internal = (1 << 2);
+
 	/* Read GPIO config and VID value from LDN 7 (GPIO) */
 	if (sio_data->type == it87) {
 		/* The IT8705F doesn't have VID pins at all */
@@ -1540,9 +1571,9 @@
 			pr_notice("it87: Routing internal VCCH to in7\n");
 		}
 		if (reg & (1 << 0))
-			pr_info("it87: in3 is VCC (+5V)\n");
+			sio_data->internal |= (1 << 0);
 		if (reg & (1 << 1))
-			pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
+			sio_data->internal |= (1 << 1);
 
 		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	}
@@ -1600,6 +1631,7 @@
 	}
 	if (!sio_data->skip_vid)
 		sysfs_remove_group(&dev->kobj, &it87_group_vid);
+	sysfs_remove_group(&dev->kobj, &it87_group_label);
 }
 
 static int __devinit it87_probe(struct platform_device *pdev)
@@ -1725,6 +1757,16 @@
 			goto ERROR4;
 	}
 
+	/* Export labels for internal sensors */
+	for (i = 0; i < 3; i++) {
+		if (!(sio_data->internal & (1 << i)))
+			continue;
+		err = sysfs_create_file(&dev->kobj,
+					it87_attributes_label[i]);
+		if (err)
+			goto ERROR4;
+	}
+
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 8bdf80d..b9bb3e0 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -252,12 +252,13 @@
 				   &sensor_dev_attr_temp3_input.dev_attr);
 		if (err)
 			goto exit_remove;
-		if (data->sensorsp & SEL_PLACE)
+		if (data->sensorsp & SEL_PLACE) {
 			err = device_create_file(&pdev->dev,
 					   &sensor_dev_attr_temp4_input.
 					   dev_attr);
 			if (err)
 				goto exit_remove;
+		}
 	}
 
 	err = device_create_file(&pdev->dev, &dev_attr_name);
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 393f354..ab5b87a 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -280,10 +280,49 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int lm75_suspend(struct device *dev)
+{
+	int status;
+	struct i2c_client *client = to_i2c_client(dev);
+	status = lm75_read_value(client, LM75_REG_CONF);
+	if (status < 0) {
+		dev_dbg(&client->dev, "Can't read config? %d\n", status);
+		return status;
+	}
+	status = status | LM75_SHUTDOWN;
+	lm75_write_value(client, LM75_REG_CONF, status);
+	return 0;
+}
+
+static int lm75_resume(struct device *dev)
+{
+	int status;
+	struct i2c_client *client = to_i2c_client(dev);
+	status = lm75_read_value(client, LM75_REG_CONF);
+	if (status < 0) {
+		dev_dbg(&client->dev, "Can't read config? %d\n", status);
+		return status;
+	}
+	status = status & ~LM75_SHUTDOWN;
+	lm75_write_value(client, LM75_REG_CONF, status);
+	return 0;
+}
+
+static const struct dev_pm_ops lm75_dev_pm_ops = {
+	.suspend	= lm75_suspend,
+	.resume		= lm75_resume,
+};
+#define LM75_DEV_PM_OPS (&lm75_dev_pm_ops)
+#else
+#define LM75_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
 static struct i2c_driver lm75_driver = {
 	.class		= I2C_CLASS_HWMON,
 	.driver = {
 		.name	= "lm75",
+		.pm	= LM75_DEV_PM_OPS,
 	},
 	.probe		= lm75_probe,
 	.remove		= lm75_remove,
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h
index 7c93454..e547a3e 100644
--- a/drivers/hwmon/lm75.h
+++ b/drivers/hwmon/lm75.h
@@ -30,6 +30,7 @@
 /* straight from the datasheet */
 #define LM75_TEMP_MIN (-55000)
 #define LM75_TEMP_MAX 125000
+#define LM75_SHUTDOWN 0x01
 
 /* TEMP: 0.001C/bit (-55C to +125C)
    REG: (0.5C/bit, two's complement) << 7 */
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index 21d201b..6593083 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/i2c/ltc4245.h>
 
 /* Here are names of the chip's registers (a.k.a. commands) */
 enum ltc4245_cmd {
@@ -60,8 +61,72 @@
 
 	/* Voltage registers */
 	u8 vregs[0x0d];
+
+	/* GPIO ADC registers */
+	bool use_extra_gpios;
+	int gpios[3];
 };
 
+/*
+ * Update the readings from the GPIO pins. If the driver has been configured to
+ * sample all GPIO's as analog voltages, a round-robin sampling method is used.
+ * Otherwise, only the configured GPIO pin is sampled.
+ *
+ * LOCKING: must hold data->update_lock
+ */
+static void ltc4245_update_gpios(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ltc4245_data *data = i2c_get_clientdata(client);
+	u8 gpio_curr, gpio_next, gpio_reg;
+	int i;
+
+	/* no extra gpio support, we're basically done */
+	if (!data->use_extra_gpios) {
+		data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10];
+		return;
+	}
+
+	/*
+	 * If the last reading was too long ago, then we mark all old GPIO
+	 * readings as stale by setting them to -EAGAIN
+	 */
+	if (time_after(jiffies, data->last_updated + 5 * HZ)) {
+		dev_dbg(&client->dev, "Marking GPIOs invalid\n");
+		for (i = 0; i < ARRAY_SIZE(data->gpios); i++)
+			data->gpios[i] = -EAGAIN;
+	}
+
+	/*
+	 * Get the current GPIO pin
+	 *
+	 * The datasheet calls these GPIO[1-3], but we'll calculate the zero
+	 * based array index instead, and call them GPIO[0-2]. This is much
+	 * easier to think about.
+	 */
+	gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6;
+	if (gpio_curr > 0)
+		gpio_curr -= 1;
+
+	/* Read the GPIO voltage from the GPIOADC register */
+	data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10];
+
+	/* Find the next GPIO pin to read */
+	gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios);
+
+	/*
+	 * Calculate the correct setting for the GPIO register so it will
+	 * sample the next GPIO pin
+	 */
+	gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6);
+
+	/* Update the GPIO register */
+	i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg);
+
+	/* Update saved data */
+	data->cregs[LTC4245_GPIO] = gpio_reg;
+}
+
 static struct ltc4245_data *ltc4245_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -93,6 +158,9 @@
 				data->vregs[i] = val;
 		}
 
+		/* Update GPIO readings */
+		ltc4245_update_gpios(dev);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -233,6 +301,22 @@
 	return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
 }
 
+static ssize_t ltc4245_show_gpio(struct device *dev,
+				 struct device_attribute *da,
+				 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ltc4245_data *data = ltc4245_update_device(dev);
+	int val = data->gpios[attr->index];
+
+	/* handle stale GPIO's */
+	if (val < 0)
+		return val;
+
+	/* Convert to millivolts and print */
+	return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
+}
+
 /* These macros are used below in constructing device attribute objects
  * for use with sysfs_create_group() to make a sysfs device file
  * for each register.
@@ -254,6 +338,10 @@
 	static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
 	ltc4245_show_alarm, NULL, (mask), reg)
 
+#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \
+	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+	ltc4245_show_gpio, NULL, gpio_num)
+
 /* Construct a sensor_device_attribute structure for each register */
 
 /* Input voltages */
@@ -293,7 +381,9 @@
 LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
 
 /* GPIO voltages */
-LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC);
+LTC4245_GPIO_VOLTAGE(in9_input,			0);
+LTC4245_GPIO_VOLTAGE(in10_input,		1);
+LTC4245_GPIO_VOLTAGE(in11_input,		2);
 
 /* Power Consumption (virtual) */
 LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
@@ -304,7 +394,7 @@
 /* Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
  */
-static struct attribute *ltc4245_attributes[] = {
+static struct attribute *ltc4245_std_attributes[] = {
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
 	&sensor_dev_attr_in3_input.dev_attr.attr,
@@ -345,10 +435,77 @@
 	NULL,
 };
 
-static const struct attribute_group ltc4245_group = {
-	.attrs = ltc4245_attributes,
+static struct attribute *ltc4245_gpio_attributes[] = {
+	&sensor_dev_attr_in10_input.dev_attr.attr,
+	&sensor_dev_attr_in11_input.dev_attr.attr,
+	NULL,
 };
 
+static const struct attribute_group ltc4245_std_group = {
+	.attrs = ltc4245_std_attributes,
+};
+
+static const struct attribute_group ltc4245_gpio_group = {
+	.attrs = ltc4245_gpio_attributes,
+};
+
+static int ltc4245_sysfs_create_groups(struct i2c_client *client)
+{
+	struct ltc4245_data *data = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
+	int ret;
+
+	/* register the standard sysfs attributes */
+	ret = sysfs_create_group(&dev->kobj, &ltc4245_std_group);
+	if (ret) {
+		dev_err(dev, "unable to register standard attributes\n");
+		return ret;
+	}
+
+	/* if we're using the extra gpio support, register it's attributes */
+	if (data->use_extra_gpios) {
+		ret = sysfs_create_group(&dev->kobj, &ltc4245_gpio_group);
+		if (ret) {
+			dev_err(dev, "unable to register gpio attributes\n");
+			sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void ltc4245_sysfs_remove_groups(struct i2c_client *client)
+{
+	struct ltc4245_data *data = i2c_get_clientdata(client);
+	struct device *dev = &client->dev;
+
+	if (data->use_extra_gpios)
+		sysfs_remove_group(&dev->kobj, &ltc4245_gpio_group);
+
+	sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
+}
+
+static bool ltc4245_use_extra_gpios(struct i2c_client *client)
+{
+	struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev);
+#ifdef CONFIG_OF
+	struct device_node *np = client->dev.of_node;
+#endif
+
+	/* prefer platform data */
+	if (pdata)
+		return pdata->use_extra_gpios;
+
+#ifdef CONFIG_OF
+	/* fallback on OF */
+	if (of_find_property(np, "ltc4245,use-extra-gpios", NULL))
+		return true;
+#endif
+
+	return false;
+}
+
 static int ltc4245_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -367,15 +524,16 @@
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
+	data->use_extra_gpios = ltc4245_use_extra_gpios(client);
 
 	/* Initialize the LTC4245 chip */
 	i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
 	i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
 
 	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &ltc4245_group);
+	ret = ltc4245_sysfs_create_groups(client);
 	if (ret)
-		goto out_sysfs_create_group;
+		goto out_sysfs_create_groups;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -386,8 +544,8 @@
 	return 0;
 
 out_hwmon_device_register:
-	sysfs_remove_group(&client->dev.kobj, &ltc4245_group);
-out_sysfs_create_group:
+	ltc4245_sysfs_remove_groups(client);
+out_sysfs_create_groups:
 	kfree(data);
 out_kzalloc:
 	return ret;
@@ -398,8 +556,7 @@
 	struct ltc4245_data *data = i2c_get_clientdata(client);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ltc4245_group);
-
+	ltc4245_sysfs_remove_groups(client);
 	kfree(data);
 
 	return 0;
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 4a64b85..68e69a4 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1610,11 +1610,8 @@
 
 static int __init pc87360_device_add(unsigned short address)
 {
-	struct resource res = {
-		.name	= "pc87360",
-		.flags	= IORESOURCE_IO,
-	};
-	int err, i;
+	struct resource res[3];
+	int err, i, res_count;
 
 	pdev = platform_device_alloc("pc87360", address);
 	if (!pdev) {
@@ -1623,22 +1620,28 @@
 		goto exit;
 	}
 
+	memset(res, 0, 3 * sizeof(struct resource));
+	res_count = 0;
 	for (i = 0; i < 3; i++) {
 		if (!extra_isa[i])
 			continue;
-		res.start = extra_isa[i];
-		res.end = extra_isa[i] + PC87360_EXTENT - 1;
+		res[res_count].start = extra_isa[i];
+		res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1;
+		res[res_count].name = "pc87360",
+		res[res_count].flags = IORESOURCE_IO,
 
-		err = acpi_check_resource_conflict(&res);
+		err = acpi_check_resource_conflict(&res[res_count]);
 		if (err)
 			goto exit_device_put;
 
-		err = platform_device_add_resources(pdev, &res, 1);
-		if (err) {
-			printk(KERN_ERR "pc87360: Device resource[%d] "
-			       "addition failed (%d)\n", i, err);
-			goto exit_device_put;
-		}
+		res_count++;
+	}
+
+	err = platform_device_add_resources(pdev, res, res_count);
+	if (err) {
+		printk(KERN_ERR "pc87360: Device resources addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 3170b26..9ec4daa 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -1,7 +1,7 @@
 /*
  *  pc87427.c - hardware monitoring driver for the
  *              National Semiconductor PC87427 Super-I/O chip
- *  Copyright (C) 2006 Jean Delvare <khali@linux-fr.org>
+ *  Copyright (C) 2006, 2008, 2010  Jean Delvare <khali@linux-fr.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -15,10 +15,11 @@
  *  Supports the following chips:
  *
  *  Chip        #vin    #fan    #pwm    #temp   devid
- *  PC87427     -       8       -       -       0xF2
+ *  PC87427     -       8       4       6       0xF2
  *
  *  This driver assumes that no more than one chip is present.
- *  Only fan inputs are supported so far, although the chip can do much more.
+ *  Only fans are fully supported so far. Temperatures are in read-only
+ *  mode, and voltages aren't supported at all.
  */
 
 #include <linux/module.h>
@@ -57,6 +58,25 @@
 	u16 fan[8];			/* register values */
 	u16 fan_min[8];			/* register values */
 	u8 fan_status[8];		/* register values */
+
+	u8 pwm_enabled;			/* bit vector */
+	u8 pwm_auto_ok;			/* bit vector */
+	u8 pwm_enable[4];		/* register values */
+	u8 pwm[4];			/* register values */
+
+	u8 temp_enabled;		/* bit vector */
+	s16 temp[6];			/* register values */
+	s8 temp_min[6];			/* register values */
+	s8 temp_max[6];			/* register values */
+	s8 temp_crit[6];		/* register values */
+	u8 temp_status[6];		/* register values */
+	u8 temp_type[6];		/* register values */
+};
+
+struct pc87427_sio_data {
+	unsigned short address[2];
+	u8 has_fanin;
+	u8 has_fanout;
 };
 
 /*
@@ -65,6 +85,13 @@
 
 #define SIOREG_LDSEL	0x07	/* Logical device select */
 #define SIOREG_DEVID	0x20	/* Device ID */
+#define SIOREG_CF2	0x22	/* Configuration 2 */
+#define SIOREG_CF3	0x23	/* Configuration 3 */
+#define SIOREG_CF4	0x24	/* Configuration 4 */
+#define SIOREG_CF5	0x25	/* Configuration 5 */
+#define SIOREG_CFB	0x2B	/* Configuration B */
+#define SIOREG_CFC	0x2C	/* Configuration C */
+#define SIOREG_CFD	0x2D	/* Configuration D */
 #define SIOREG_ACT	0x30	/* Device activation */
 #define SIOREG_MAP	0x50	/* I/O or memory mapping */
 #define SIOREG_IOBASE	0x60	/* I/O base address */
@@ -102,6 +129,8 @@
 #define BANK_FM(nr)		(nr)
 #define BANK_FT(nr)		(0x08 + (nr))
 #define BANK_FC(nr)		(0x10 + (nr) * 2)
+#define BANK_TM(nr)		(nr)
+#define BANK_VM(nr)		(0x08 + (nr))
 
 /*
  * I/O access functions
@@ -179,6 +208,127 @@
 }
 
 /*
+ * PWM registers and conversions
+ */
+
+#define PC87427_REG_PWM_ENABLE		0x10
+#define PC87427_REG_PWM_DUTY		0x12
+
+#define PWM_ENABLE_MODE_MASK		(7 << 4)
+#define PWM_ENABLE_CTLEN		(1 << 0)
+
+#define PWM_MODE_MANUAL			(0 << 4)
+#define PWM_MODE_AUTO			(1 << 4)
+#define PWM_MODE_OFF			(2 << 4)
+#define PWM_MODE_ON			(7 << 4)
+
+/* Dedicated function to read all registers related to a given PWM output.
+   This saves us quite a few locks and bank selections.
+   Must be called with data->lock held.
+   nr is from 0 to 3 */
+static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr)
+{
+	int iobase = data->address[LD_FAN];
+
+	outb(BANK_FC(nr), iobase + PC87427_REG_BANK);
+	data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE);
+	data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY);
+}
+
+static inline int pwm_enable_from_reg(u8 reg)
+{
+	switch (reg & PWM_ENABLE_MODE_MASK) {
+	case PWM_MODE_ON:
+		return 0;
+	case PWM_MODE_MANUAL:
+	case PWM_MODE_OFF:
+		return 1;
+	case PWM_MODE_AUTO:
+		return 2;
+	default:
+		return -EPROTO;
+	}
+}
+
+static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval)
+{
+	switch (val) {
+	default:
+		return PWM_MODE_ON;
+	case 1:
+		return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF;
+	case 2:
+		return PWM_MODE_AUTO;
+	}
+}
+
+/*
+ * Temperature registers and conversions
+ */
+
+#define PC87427_REG_TEMP_STATUS		0x10
+#define PC87427_REG_TEMP		0x14
+#define PC87427_REG_TEMP_MAX		0x18
+#define PC87427_REG_TEMP_MIN		0x19
+#define PC87427_REG_TEMP_CRIT		0x1a
+#define PC87427_REG_TEMP_TYPE		0x1d
+
+#define TEMP_STATUS_CHANEN		(1 << 0)
+#define TEMP_STATUS_LOWFLG		(1 << 1)
+#define TEMP_STATUS_HIGHFLG		(1 << 2)
+#define TEMP_STATUS_CRITFLG		(1 << 3)
+#define TEMP_STATUS_SENSERR		(1 << 5)
+#define TEMP_TYPE_MASK			(3 << 5)
+
+#define TEMP_TYPE_THERMISTOR		(1 << 5)
+#define TEMP_TYPE_REMOTE_DIODE		(2 << 5)
+#define TEMP_TYPE_LOCAL_DIODE		(3 << 5)
+
+/* Dedicated function to read all registers related to a given temperature
+   input. This saves us quite a few locks and bank selections.
+   Must be called with data->lock held.
+   nr is from 0 to 5 */
+static void pc87427_readall_temp(struct pc87427_data *data, u8 nr)
+{
+	int iobase = data->address[LD_TEMP];
+
+	outb(BANK_TM(nr), iobase + PC87427_REG_BANK);
+	data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP));
+	data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX);
+	data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN);
+	data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT);
+	data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE);
+	data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS);
+	/* Clear fan alarm bits */
+	outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS);
+}
+
+static inline unsigned int temp_type_from_reg(u8 reg)
+{
+	switch (reg & TEMP_TYPE_MASK) {
+	case TEMP_TYPE_THERMISTOR:
+		return 4;
+	case TEMP_TYPE_REMOTE_DIODE:
+	case TEMP_TYPE_LOCAL_DIODE:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
+/* We assume 8-bit thermal sensors; 9-bit thermal sensors are possible
+   too, but I have no idea how to figure out when they are used. */
+static inline long temp_from_reg(s16 reg)
+{
+	return reg * 1000 / 256;
+}
+
+static inline long temp_from_reg8(s8 reg)
+{
+	return reg * 1000;
+}
+
+/*
  * Data interface
  */
 
@@ -198,6 +348,21 @@
 			continue;
 		pc87427_readall_fan(data, i);
 	}
+
+	/* PWM outputs */
+	for (i = 0; i < 4; i++) {
+		if (!(data->pwm_enabled & (1 << i)))
+			continue;
+		pc87427_readall_pwm(data, i);
+	}
+
+	/* Temperature channels */
+	for (i = 0; i < 6; i++) {
+		if (!(data->temp_enabled & (1 << i)))
+			continue;
+		pc87427_readall_temp(data, i);
+	}
+
 	data->last_updated = jiffies;
 
 done:
@@ -208,9 +373,8 @@
 static ssize_t show_fan_input(struct device *dev, struct device_attribute
 			      *devattr, char *buf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87427_data *data = pc87427_update_device(dev);
-	int nr = attr->index;
+	int nr = to_sensor_dev_attr(devattr)->index;
 
 	return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
 }
@@ -218,9 +382,8 @@
 static ssize_t show_fan_min(struct device *dev, struct device_attribute
 			    *devattr, char *buf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87427_data *data = pc87427_update_device(dev);
-	int nr = attr->index;
+	int nr = to_sensor_dev_attr(devattr)->index;
 
 	return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
 }
@@ -228,9 +391,8 @@
 static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
 			      *devattr, char *buf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87427_data *data = pc87427_update_device(dev);
-	int nr = attr->index;
+	int nr = to_sensor_dev_attr(devattr)->index;
 
 	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
 				       & FAN_STATUS_LOSPD));
@@ -239,9 +401,8 @@
 static ssize_t show_fan_fault(struct device *dev, struct device_attribute
 			      *devattr, char *buf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87427_data *data = pc87427_update_device(dev);
-	int nr = attr->index;
+	int nr = to_sensor_dev_attr(devattr)->index;
 
 	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
 				       & FAN_STATUS_STALL));
@@ -251,11 +412,13 @@
 			   *devattr, const char *buf, size_t count)
 {
 	struct pc87427_data *data = dev_get_drvdata(dev);
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int nr = to_sensor_dev_attr(devattr)->index;
+	unsigned long val;
 	int iobase = data->address[LD_FAN];
 
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
 	mutex_lock(&data->lock);
 	outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
 	/* The low speed limit registers are read-only while monitoring
@@ -377,6 +540,390 @@
 	{ .attrs = pc87427_attributes_fan[7] },
 };
 
+/* Must be called with data->lock held and pc87427_readall_pwm() freshly
+   called */
+static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode)
+{
+	int iobase = data->address[LD_FAN];
+	data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK;
+	data->pwm_enable[nr] |= mode;
+	outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE);
+}
+
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+	int pwm_enable;
+
+	pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]);
+	if (pwm_enable < 0)
+		return pwm_enable;
+	return sprintf(buf, "%d\n", pwm_enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+			      *devattr, const char *buf, size_t count)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) < 0 || val > 2)
+		return -EINVAL;
+	/* Can't go to automatic mode if it isn't configured */
+	if (val == 2 && !(data->pwm_auto_ok & (1 << nr)))
+		return -EINVAL;
+
+	mutex_lock(&data->lock);
+	pc87427_readall_pwm(data, nr);
+	update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr]));
+	mutex_unlock(&data->lock);
+
+	return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%d\n", (int)data->pwm[nr]);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute
+		       *devattr, const char *buf, size_t count)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+	unsigned long val;
+	int iobase = data->address[LD_FAN];
+	u8 mode;
+
+	if (strict_strtoul(buf, 10, &val) < 0 || val > 0xff)
+		return -EINVAL;
+
+	mutex_lock(&data->lock);
+	pc87427_readall_pwm(data, nr);
+	mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK;
+	if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) {
+		dev_notice(dev, "Can't set PWM%d duty cycle while not in "
+			   "manual mode\n", nr + 1);
+		mutex_unlock(&data->lock);
+		return -EPERM;
+	}
+
+	/* We may have to change the mode */
+	if (mode == PWM_MODE_MANUAL && val == 0) {
+		/* Transition from Manual to Off */
+		update_pwm_enable(data, nr, PWM_MODE_OFF);
+		mode = PWM_MODE_OFF;
+		dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
+			"manual", "off");
+	} else if (mode == PWM_MODE_OFF && val != 0) {
+		/* Transition from Off to Manual */
+		update_pwm_enable(data, nr, PWM_MODE_MANUAL);
+		mode = PWM_MODE_MANUAL;
+		dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1,
+			"off", "manual");
+	}
+
+	data->pwm[nr] = val;
+	if (mode == PWM_MODE_MANUAL)
+		outb(val, iobase + PC87427_REG_PWM_DUTY);
+	mutex_unlock(&data->lock);
+
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+			  show_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+			  show_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
+			  show_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
+			  show_pwm_enable, set_pwm_enable, 3);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3);
+
+static struct attribute *pc87427_attributes_pwm[4][3] = {
+	{
+		&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm1.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm2.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm3.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_pwm4_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm4.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group pc87427_group_pwm[4] = {
+	{ .attrs = pc87427_attributes_pwm[0] },
+	{ .attrs = pc87427_attributes_pwm[1] },
+	{ .attrs = pc87427_attributes_pwm[2] },
+	{ .attrs = pc87427_attributes_pwm[3] },
+};
+
+static ssize_t show_temp_input(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr]));
+}
+
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr]));
+}
+
+static ssize_t show_temp_type(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr]));
+}
+
+static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute
+				   *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%d\n", !!(data->temp_status[nr]
+				       & TEMP_STATUS_LOWFLG));
+}
+
+static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute
+				   *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%d\n", !!(data->temp_status[nr]
+				       & TEMP_STATUS_HIGHFLG));
+}
+
+static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute
+				   *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%d\n", !!(data->temp_status[nr]
+				       & TEMP_STATUS_CRITFLG));
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+			       *devattr, char *buf)
+{
+	struct pc87427_data *data = pc87427_update_device(dev);
+	int nr = to_sensor_dev_attr(devattr)->index;
+
+	return sprintf(buf, "%d\n", !!(data->temp_status[nr]
+				       & TEMP_STATUS_SENSERR));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO,
+			  show_temp_min_alarm, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO,
+			  show_temp_max_alarm, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO,
+			  show_temp_crit_alarm, NULL, 5);
+
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
+
+static struct attribute *pc87427_attributes_temp[6][10] = {
+	{
+		&sensor_dev_attr_temp1_input.dev_attr.attr,
+		&sensor_dev_attr_temp1_min.dev_attr.attr,
+		&sensor_dev_attr_temp1_max.dev_attr.attr,
+		&sensor_dev_attr_temp1_crit.dev_attr.attr,
+		&sensor_dev_attr_temp1_type.dev_attr.attr,
+		&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp1_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp2_input.dev_attr.attr,
+		&sensor_dev_attr_temp2_min.dev_attr.attr,
+		&sensor_dev_attr_temp2_max.dev_attr.attr,
+		&sensor_dev_attr_temp2_crit.dev_attr.attr,
+		&sensor_dev_attr_temp2_type.dev_attr.attr,
+		&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp2_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp3_input.dev_attr.attr,
+		&sensor_dev_attr_temp3_min.dev_attr.attr,
+		&sensor_dev_attr_temp3_max.dev_attr.attr,
+		&sensor_dev_attr_temp3_crit.dev_attr.attr,
+		&sensor_dev_attr_temp3_type.dev_attr.attr,
+		&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp3_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp4_input.dev_attr.attr,
+		&sensor_dev_attr_temp4_min.dev_attr.attr,
+		&sensor_dev_attr_temp4_max.dev_attr.attr,
+		&sensor_dev_attr_temp4_crit.dev_attr.attr,
+		&sensor_dev_attr_temp4_type.dev_attr.attr,
+		&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp4_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp5_input.dev_attr.attr,
+		&sensor_dev_attr_temp5_min.dev_attr.attr,
+		&sensor_dev_attr_temp5_max.dev_attr.attr,
+		&sensor_dev_attr_temp5_crit.dev_attr.attr,
+		&sensor_dev_attr_temp5_type.dev_attr.attr,
+		&sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp5_fault.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp6_input.dev_attr.attr,
+		&sensor_dev_attr_temp6_min.dev_attr.attr,
+		&sensor_dev_attr_temp6_max.dev_attr.attr,
+		&sensor_dev_attr_temp6_crit.dev_attr.attr,
+		&sensor_dev_attr_temp6_type.dev_attr.attr,
+		&sensor_dev_attr_temp6_min_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
+		&sensor_dev_attr_temp6_fault.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group pc87427_group_temp[6] = {
+	{ .attrs = pc87427_attributes_temp[0] },
+	{ .attrs = pc87427_attributes_temp[1] },
+	{ .attrs = pc87427_attributes_temp[2] },
+	{ .attrs = pc87427_attributes_temp[3] },
+	{ .attrs = pc87427_attributes_temp[4] },
+	{ .attrs = pc87427_attributes_temp[5] },
+};
+
 static ssize_t show_name(struct device *dev, struct device_attribute
 			 *devattr, char *buf)
 {
@@ -391,8 +938,49 @@
  * Device detection, attach and detach
  */
 
+static void pc87427_release_regions(struct platform_device *pdev, int count)
+{
+	struct resource *res;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, i);
+		release_region(res->start, resource_size(res));
+	}
+}
+
+static int __devinit pc87427_request_regions(struct platform_device *pdev,
+					     int count)
+{
+	struct resource *res;
+	int i, err = 0;
+
+	for (i = 0; i < count; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, i);
+		if (!res) {
+			err = -ENOENT;
+			dev_err(&pdev->dev, "Missing resource #%d\n", i);
+			break;
+		}
+		if (!request_region(res->start, resource_size(res), DRVNAME)) {
+			err = -EBUSY;
+			dev_err(&pdev->dev,
+				"Failed to request region 0x%lx-0x%lx\n",
+				(unsigned long)res->start,
+				(unsigned long)res->end);
+			break;
+		}
+	}
+
+	if (err && i)
+		pc87427_release_regions(pdev, i);
+
+	return err;
+}
+
 static void __devinit pc87427_init_device(struct device *dev)
 {
+	struct pc87427_sio_data *sio_data = dev->platform_data;
 	struct pc87427_data *data = dev_get_drvdata(dev);
 	int i;
 	u8 reg;
@@ -400,10 +988,12 @@
 	/* The FMC module should be ready */
 	reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
 	if (!(reg & 0x80))
-		dev_warn(dev, "FMC module not ready!\n");
+		dev_warn(dev, "%s module not ready!\n", "FMC");
 
 	/* Check which fans are enabled */
 	for (i = 0; i < 8; i++) {
+		if (!(sio_data->has_fanin & (1 << i)))	/* Not wired */
+			continue;
 		reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
 					 PC87427_REG_FAN_STATUS);
 		if (reg & FAN_STATUS_MONEN)
@@ -411,37 +1001,93 @@
 	}
 
 	if (!data->fan_enabled) {
-		dev_dbg(dev, "Enabling all fan inputs\n");
-		for (i = 0; i < 8; i++)
+		dev_dbg(dev, "Enabling monitoring of all fans\n");
+		for (i = 0; i < 8; i++) {
+			if (!(sio_data->has_fanin & (1 << i)))	/* Not wired */
+				continue;
 			pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
 					    PC87427_REG_FAN_STATUS,
 					    FAN_STATUS_MONEN);
-		data->fan_enabled = 0xff;
+		}
+		data->fan_enabled = sio_data->has_fanin;
+	}
+
+	/* Check which PWM outputs are enabled */
+	for (i = 0; i < 4; i++) {
+		if (!(sio_data->has_fanout & (1 << i)))	/* Not wired */
+			continue;
+		reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i),
+					 PC87427_REG_PWM_ENABLE);
+		if (reg & PWM_ENABLE_CTLEN)
+			data->pwm_enabled |= (1 << i);
+
+		/* We don't expose an interface to reconfigure the automatic
+		   fan control mode, so only allow to return to this mode if
+		   it was originally set. */
+		if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) {
+			dev_dbg(dev, "PWM%d is in automatic control mode\n",
+				i + 1);
+			data->pwm_auto_ok |= (1 << i);
+		}
+	}
+
+	/* The HMC module should be ready */
+	reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK);
+	if (!(reg & 0x80))
+		dev_warn(dev, "%s module not ready!\n", "HMC");
+
+	/* Check which temperature channels are enabled */
+	for (i = 0; i < 6; i++) {
+		reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i),
+					 PC87427_REG_TEMP_STATUS);
+		if (reg & TEMP_STATUS_CHANEN)
+			data->temp_enabled |= (1 << i);
+	}
+}
+
+static void pc87427_remove_files(struct device *dev)
+{
+	struct pc87427_data *data = dev_get_drvdata(dev);
+	int i;
+
+	device_remove_file(dev, &dev_attr_name);
+	for (i = 0; i < 8; i++) {
+		if (!(data->fan_enabled & (1 << i)))
+			continue;
+		sysfs_remove_group(&dev->kobj, &pc87427_group_fan[i]);
+	}
+	for (i = 0; i < 4; i++) {
+		if (!(data->pwm_enabled & (1 << i)))
+			continue;
+		sysfs_remove_group(&dev->kobj, &pc87427_group_pwm[i]);
+	}
+	for (i = 0; i < 6; i++) {
+		if (!(data->temp_enabled & (1 << i)))
+			continue;
+		sysfs_remove_group(&dev->kobj, &pc87427_group_temp[i]);
 	}
 }
 
 static int __devinit pc87427_probe(struct platform_device *pdev)
 {
+	struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
 	struct pc87427_data *data;
-	struct resource *res;
-	int i, err;
+	int i, err, res_count;
 
-	if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		printk(KERN_ERR DRVNAME ": Out of memory\n");
 		goto exit;
 	}
 
-	/* This will need to be revisited when we add support for
-	   temperature and voltage monitoring. */
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, resource_size(res), DRVNAME)) {
-		err = -EBUSY;
-		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
-			(unsigned long)res->start, (unsigned long)res->end);
+	data->address[0] = sio_data->address[0];
+	data->address[1] = sio_data->address[1];
+	res_count = (data->address[0] != 0) + (data->address[1] != 0);
+
+	err = pc87427_request_regions(pdev, res_count);
+	if (err)
 		goto exit_kfree;
-	}
-	data->address[0] = res->start;
 
 	mutex_init(&data->lock);
 	data->name = "pc87427";
@@ -449,13 +1095,31 @@
 	pc87427_init_device(&pdev->dev);
 
 	/* Register sysfs hooks */
-	if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
 		goto exit_release_region;
 	for (i = 0; i < 8; i++) {
 		if (!(data->fan_enabled & (1 << i)))
 			continue;
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &pc87427_group_fan[i])))
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &pc87427_group_fan[i]);
+		if (err)
+			goto exit_remove_files;
+	}
+	for (i = 0; i < 4; i++) {
+		if (!(data->pwm_enabled & (1 << i)))
+			continue;
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &pc87427_group_pwm[i]);
+		if (err)
+			goto exit_remove_files;
+	}
+	for (i = 0; i < 6; i++) {
+		if (!(data->temp_enabled & (1 << i)))
+			continue;
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &pc87427_group_temp[i]);
+		if (err)
 			goto exit_remove_files;
 	}
 
@@ -469,13 +1133,9 @@
 	return 0;
 
 exit_remove_files:
-	for (i = 0; i < 8; i++) {
-		if (!(data->fan_enabled & (1 << i)))
-			continue;
-		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
-	}
+	pc87427_remove_files(&pdev->dev);
 exit_release_region:
-	release_region(res->start, resource_size(res));
+	pc87427_release_regions(pdev, res_count);
 exit_kfree:
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
@@ -486,21 +1146,16 @@
 static int __devexit pc87427_remove(struct platform_device *pdev)
 {
 	struct pc87427_data *data = platform_get_drvdata(pdev);
-	struct resource *res;
-	int i;
+	int res_count;
+
+	res_count = (data->address[0] != 0) + (data->address[1] != 0);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-	for (i = 0; i < 8; i++) {
-		if (!(data->fan_enabled & (1 << i)))
-			continue;
-		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
-	}
+	pc87427_remove_files(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, resource_size(res));
+	pc87427_release_regions(pdev, res_count);
 
 	return 0;
 }
@@ -515,34 +1170,50 @@
 	.remove		= __devexit_p(pc87427_remove),
 };
 
-static int __init pc87427_device_add(unsigned short address)
+static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
 {
-	struct resource res = {
-		.start	= address,
-		.end	= address + REGION_LENGTH - 1,
-		.name	= logdev_str[0],
-		.flags	= IORESOURCE_IO,
+	struct resource res[2] = {
+		{ .flags	= IORESOURCE_IO },
+		{ .flags	= IORESOURCE_IO },
 	};
-	int err;
+	int err, i, res_count;
 
-	err = acpi_check_resource_conflict(&res);
-	if (err)
-		goto exit;
+	res_count = 0;
+	for (i = 0; i < 2; i++) {
+		if (!sio_data->address[i])
+			continue;
+		res[res_count].start = sio_data->address[i];
+		res[res_count].end = sio_data->address[i] + REGION_LENGTH - 1;
+		res[res_count].name = logdev_str[i];
 
-	pdev = platform_device_alloc(DRVNAME, address);
+		err = acpi_check_resource_conflict(&res[res_count]);
+		if (err)
+			goto exit;
+
+		res_count++;
+	}
+
+	pdev = platform_device_alloc(DRVNAME, res[0].start);
 	if (!pdev) {
 		err = -ENOMEM;
 		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
 		goto exit;
 	}
 
-	err = platform_device_add_resources(pdev, &res, 1);
+	err = platform_device_add_resources(pdev, res, res_count);
 	if (err) {
 		printk(KERN_ERR DRVNAME ": Device resource addition failed "
 		       "(%d)\n", err);
 		goto exit_device_put;
 	}
 
+	err = platform_device_add_data(pdev, sio_data,
+				       sizeof(struct pc87427_sio_data));
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		goto exit_device_put;
+	}
+
 	err = platform_device_add(pdev);
 	if (err) {
 		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
@@ -558,9 +1229,10 @@
 	return err;
 }
 
-static int __init pc87427_find(int sioaddr, unsigned short *address)
+static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data)
 {
 	u16 val;
+	u8 cfg, cfg_b;
 	int i, err = 0;
 
 	/* Identify device */
@@ -571,7 +1243,7 @@
 	}
 
 	for (i = 0; i < 2; i++) {
-		address[i] = 0;
+		sio_data->address[i] = 0;
 		/* Select logical device */
 		superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
 
@@ -596,9 +1268,58 @@
 			       "for logical device 0x%02x\n", logdev[i]);
 			continue;
 		}
-		address[i] = val;
+		sio_data->address[i] = val;
 	}
 
+	/* No point in loading the driver if everything is disabled */
+	if (!sio_data->address[0] && !sio_data->address[1]) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/* Check which fan inputs are wired */
+	sio_data->has_fanin = (1 << 2) | (1 << 3);	/* FANIN2, FANIN3 */
+
+	cfg = superio_inb(sioaddr, SIOREG_CF2);
+	if (!(cfg & (1 << 3)))
+		sio_data->has_fanin |= (1 << 0);	/* FANIN0 */
+	if (!(cfg & (1 << 2)))
+		sio_data->has_fanin |= (1 << 4);	/* FANIN4 */
+
+	cfg = superio_inb(sioaddr, SIOREG_CFD);
+	if (!(cfg & (1 << 0)))
+		sio_data->has_fanin |= (1 << 1);	/* FANIN1 */
+
+	cfg = superio_inb(sioaddr, SIOREG_CF4);
+	if (!(cfg & (1 << 0)))
+		sio_data->has_fanin |= (1 << 7);	/* FANIN7 */
+	cfg_b = superio_inb(sioaddr, SIOREG_CFB);
+	if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3)))
+		sio_data->has_fanin |= (1 << 5);	/* FANIN5 */
+	cfg = superio_inb(sioaddr, SIOREG_CF3);
+	if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5)))
+		sio_data->has_fanin |= (1 << 6);	/* FANIN6 */
+
+	/* Check which fan outputs are wired */
+	sio_data->has_fanout = (1 << 0);		/* FANOUT0 */
+	if (cfg_b & (1 << 0))
+		sio_data->has_fanout |= (1 << 3);	/* FANOUT3 */
+
+	cfg = superio_inb(sioaddr, SIOREG_CFC);
+	if (!(cfg & (1 << 4))) {
+		if (cfg_b & (1 << 1))
+			sio_data->has_fanout |= (1 << 1); /* FANOUT1 */
+		if (cfg_b & (1 << 2))
+			sio_data->has_fanout |= (1 << 2); /* FANOUT2 */
+	}
+
+	/* FANOUT1 and FANOUT2 can each be routed to 2 different pins */
+	cfg = superio_inb(sioaddr, SIOREG_CF5);
+	if (cfg & (1 << 6))
+		sio_data->has_fanout |= (1 << 1);	/* FANOUT1 */
+	if (cfg & (1 << 5))
+		sio_data->has_fanout |= (1 << 2);	/* FANOUT2 */
+
 exit:
 	superio_exit(sioaddr);
 	return err;
@@ -607,15 +1328,10 @@
 static int __init pc87427_init(void)
 {
 	int err;
-	unsigned short address[2];
+	struct pc87427_sio_data sio_data;
 
-	if (pc87427_find(0x2e, address)
-	 && pc87427_find(0x4e, address))
-		return -ENODEV;
-
-	/* For now the driver only handles fans so we only care about the
-	   first address. */
-	if (!address[0])
+	if (pc87427_find(0x2e, &sio_data)
+	 && pc87427_find(0x4e, &sio_data))
 		return -ENODEV;
 
 	err = platform_driver_register(&pc87427_driver);
@@ -623,7 +1339,7 @@
 		goto exit;
 
 	/* Sets global pdev as a side effect */
-	err = pc87427_device_add(address[0]);
+	err = pc87427_device_add(&sio_data);
 	if (err)
 		goto exit_driver;
 
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 7442cf7..ffb793a 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -39,7 +39,7 @@
 
 #define DRVNAME	"via_cputemp"
 
-enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW;
+enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME };
 
 /*
  * Functions declaration
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 0dcaba9..e96e69d 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -39,6 +39,7 @@
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
     w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
+    w83667hg-b   9      5       3       3      0xb350 0xc1    0x5ca3
 */
 
 #include <linux/module.h>
@@ -55,7 +56,7 @@
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg };
+enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b };
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
 static const char * w83627ehf_device_names[] = {
@@ -63,6 +64,7 @@
 	"w83627dhg",
 	"w83627dhg",
 	"w83667hg",
+	"w83667hg",
 };
 
 static unsigned short force_id;
@@ -91,6 +93,7 @@
 #define SIO_W83627DHG_ID	0xa020
 #define SIO_W83627DHG_P_ID	0xb070
 #define SIO_W83667HG_ID 	0xa510
+#define SIO_W83667HG_B_ID	0xb350
 #define SIO_ID_MASK		0xFFF0
 
 static inline void
@@ -201,8 +204,14 @@
 static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
 static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
 static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
-static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0xff, 0x67, 0xff, 0x69 };
-static const u8 W83627EHF_REG_FAN_STEP_OUTPUT[] = { 0xff, 0x68, 0xff, 0x6a };
+
+static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
+						= { 0xff, 0x67, 0xff, 0x69 };
+static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
+						= { 0xff, 0x68, 0xff, 0x6a };
+
+static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
+static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c };
 
 /*
  * Conversions
@@ -277,6 +286,11 @@
 	struct device *hwmon_dev;
 	struct mutex lock;
 
+	const u8 *REG_FAN_START_OUTPUT;
+	const u8 *REG_FAN_STOP_OUTPUT;
+	const u8 *REG_FAN_MAX_OUTPUT;
+	const u8 *REG_FAN_STEP_OUTPUT;
+
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -524,7 +538,10 @@
 			}
 		}
 
-		for (i = 0; i < 4; i++) {
+		for (i = 0; i < data->pwm_num; i++) {
+			if (!(data->has_fan & (1 << i)))
+				continue;
+
 			/* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
 			if (i != 1) {
 				pwmcfg = w83627ehf_read_value(data,
@@ -546,6 +563,17 @@
 						W83627EHF_REG_FAN_STOP_OUTPUT[i]);
 			data->fan_stop_time[i] = w83627ehf_read_value(data,
 						W83627EHF_REG_FAN_STOP_TIME[i]);
+
+			if (data->REG_FAN_MAX_OUTPUT[i] != 0xff)
+				data->fan_max_output[i] =
+				  w83627ehf_read_value(data,
+					       data->REG_FAN_MAX_OUTPUT[i]);
+
+			if (data->REG_FAN_STEP_OUTPUT[i] != 0xff)
+				data->fan_step_output[i] =
+				  w83627ehf_read_value(data,
+					       data->REG_FAN_STEP_OUTPUT[i]);
+
 			data->target_temp[i] =
 				w83627ehf_read_value(data,
 					W83627EHF_REG_TARGET[i]) &
@@ -1126,7 +1154,7 @@
 	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
-	w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
+	w83627ehf_write_value(data, data->REG_##REG[nr], val); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -1206,12 +1234,26 @@
 		    store_fan_stop_output, 1),
 	SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
 		    store_fan_stop_output, 2),
+};
 
-	/* pwm1 and pwm3 don't support max and step settings */
+
+/*
+ * pwm1 and pwm3 don't support max and step settings on all chips.
+ * Need to check support while generating/removing attribute files.
+ */
+static struct sensor_device_attribute sda_sf3_max_step_arrays[] = {
+	SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
+		    store_fan_max_output, 0),
+	SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
+		    store_fan_step_output, 0),
 	SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
 		    store_fan_max_output, 1),
 	SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
 		    store_fan_step_output, 1),
+	SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
+		    store_fan_max_output, 2),
+	SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
+		    store_fan_step_output, 2),
 };
 
 static ssize_t
@@ -1235,6 +1277,12 @@
 
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
 		device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
+		struct sensor_device_attribute *attr =
+		  &sda_sf3_max_step_arrays[i];
+		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
+			device_remove_file(dev, &attr->dev_attr);
+	}
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
 		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
 	for (i = 0; i < data->in_num; i++) {
@@ -1343,22 +1391,37 @@
 	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
 	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
 	/* 667HG has 3 pwms */
-	data->pwm_num = (sio_data->kind == w83667hg) ? 3 : 4;
+	data->pwm_num = (sio_data->kind == w83667hg
+			 || sio_data->kind == w83667hg_b) ? 3 : 4;
 
 	/* Check temp3 configuration bit for 667HG */
-	if (sio_data->kind == w83667hg) {
+	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
 		data->temp3_disable = w83627ehf_read_value(data,
 					W83627EHF_REG_TEMP_CONFIG[1]) & 0x01;
 		data->in6_skip = !data->temp3_disable;
 	}
 
+	data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
+	data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
+	if (sio_data->kind == w83667hg_b) {
+		data->REG_FAN_MAX_OUTPUT =
+		  W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B;
+		data->REG_FAN_STEP_OUTPUT =
+		  W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B;
+	} else {
+		data->REG_FAN_MAX_OUTPUT =
+		  W83627EHF_REG_FAN_MAX_OUTPUT_COMMON;
+		data->REG_FAN_STEP_OUTPUT =
+		  W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
+	}
+
 	/* Initialize the chip */
 	w83627ehf_init_device(data);
 
 	data->vrm = vid_which_vrm();
 	superio_enter(sio_data->sioreg);
 	/* Read VID value */
-	if (sio_data->kind == w83667hg) {
+	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
 		/* W83667HG has different pins for VID input and output, so
 		we can get the VID input values directly at logical device D
 		0xe3. */
@@ -1409,7 +1472,7 @@
 	}
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
-	if (sio_data->kind == w83667hg) {
+	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
 		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
 		fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
 	} else {
@@ -1440,6 +1503,15 @@
 			&sda_sf3_arrays[i].dev_attr)))
 			goto exit_remove;
 
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
+		struct sensor_device_attribute *attr =
+		  &sda_sf3_max_step_arrays[i];
+		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
+			err = device_create_file(dev, &attr->dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
 	/* if fan4 is enabled create the sf3 files for it */
 	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
 		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
@@ -1556,6 +1628,7 @@
 	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
 	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
 	static const char __initdata sio_name_W83667HG[] = "W83667HG";
+	static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
 
 	u16 val;
 	const char *sio_name;
@@ -1588,6 +1661,10 @@
 		sio_data->kind = w83667hg;
 		sio_name = sio_name_W83667HG;
 		break;
+	case SIO_W83667HG_B_ID:
+		sio_data->kind = w83667hg_b;
+		sio_name = sio_name_W83667HG_B;
+		break;
 	default:
 		if (val != 0xffff)
 			pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index c425681..6837a8e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -626,6 +626,7 @@
  *	mpt_register - Register protocol-specific main callback handler.
  *	@cbfunc: callback function pointer
  *	@dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
+ *	@func_name: call function's name
  *
  *	This routine is called by a protocol-specific driver (SCSI host,
  *	LAN, SCSI target) to register its reply callback routine.  Each
@@ -6559,7 +6560,7 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
+/*
  *	Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
  */
 static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan);
@@ -8003,6 +8004,7 @@
  *	mpt_sas_log_info - Log information returned from SAS IOC.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@log_info: U32 LogInfo reply word from the IOC
+ *	@cb_idx: callback function's handle
  *
  *	Refer to lsi/mpi_log_sas.h.
  **/
diff --git a/fs/dcache.c b/fs/dcache.c
index 166d35d..4d13bf5 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1976,7 +1976,7 @@
  * __d_path - return the path of a dentry
  * @path: the dentry/vfsmount to report
  * @root: root vfsmnt/dentry (may be modified by this function)
- * @buffer: buffer to return value in
+ * @buf: buffer to return value in
  * @buflen: buffer length
  *
  * Convert a dentry into an ASCII path name.
diff --git a/include/linux/i2c/ltc4245.h b/include/linux/i2c/ltc4245.h
new file mode 100644
index 0000000..56bda4b
--- /dev/null
+++ b/include/linux/i2c/ltc4245.h
@@ -0,0 +1,21 @@
+/*
+ * Platform Data for LTC4245 hardware monitor chip
+ *
+ * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef LINUX_LTC4245_H
+#define LINUX_LTC4245_H
+
+#include <linux/types.h>
+
+struct ltc4245_platform_data {
+	bool use_extra_gpios;
+};
+
+#endif /* LINUX_LTC4245_H */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 20890d8..7262aac 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -397,7 +397,7 @@
 	return x + 1;	/* Ensure that we never return 0 */
 }
 
-/**
+/*
  * global_dirty_limits - background-writeback and dirty-throttling thresholds
  *
  * Calculate the dirty thresholds based on sysctl parameters
@@ -440,7 +440,7 @@
 	*pdirty = dirty;
 }
 
-/**
+/*
  * bdi_dirty_limit - @bdi's share of dirty throttling threshold
  *
  * Allocate high/low dirty limits to fast/slow devices, in order to prevent