瀏覽代碼

Merge tag 'mfd-3.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6

Pull MFD changes from Samuel Ortiz:
 "MFD bits for the 3.7 merge window.

  As usual we have a few new drivers:

   - TI LP8788
   - TI OMAP USB TLL
   - Maxim MAX8907
   - SMSC ECE1099
   - Dialog Semiconductor DA9055
   - A simpler syscon driver that allow us to get rid of the anatop one.

  Drivers are also gradually getting Device Tree and IRQ domain support.

  The following drivers got DT support:
   - palmas, 88pm860x, tc3589x and twl4030-audio

  And those ones now use the IRQ domain APIs:
   - 88pm860x, tc3589x, db8500_prcmu

  Also some other interesting changes:
   - Intel's ICH LPC now supports Lynx Point
   - TI's twl4030-audio added a GPO child
   - tps6527 enabled its backlight subdevice
   - The twl6030 pwm driver moved to the new PWM subsystem

  And finally a bunch of cleanup and casual fixes for mc13xxx, 88pm860x,
  palmas, ab8500, wm8994, wm5110, max8907 and the tps65xxx family."

Fix up various annoying conflicts: the DT and IRQ domain support came in
twice and was already in 3.6. And then it was apparently rebased.

Guys, DON'T REBASE!

* tag 'mfd-3.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (89 commits)
  ARM: dts: Enable 88pm860x pmic
  mfd: 88pm860x: Move gpadc init into touch
  mfd: 88pm860x: Device tree support
  mfd: 88pm860x: Use irqdomain
  mfd: smsc: Add support for smsc gpio io/keypad driver
  backlight: tps65217_bl: Add missing platform_set_drvdata in tps65217_bl_probe
  mfd: DA9055 core driver
  mfd: tps65910: Add alarm interrupt of TPS65910 RTC to mfd device list
  mfd: wm5110: Add register patches for revision B
  mfd: wm5110: Disable control interface error report for WM5110 rev B
  mfd: max8907: Remove regulator-compatible from DT docs
  backlight: Add TPS65217 WLED driver
  mfd: Add backlight as subdevice to the tps65217
  mfd: Provide the PRCMU with its own IRQ domain
  mfd: Fix max8907 sparse warning
  mfd: Add lp8788 mfd driver
  mfd: dbx500: Provide a more accurate smp_twd clock
  mfd: rc5t583: Fix warning messages
  regulator: palmas: Add DT support
  mfd: palmas: Change regulator defns to better suite DT
  ...
Linus Torvalds 13 年之前
父節點
當前提交
578f1ef91a
共有 100 個文件被更改,包括 7865 次插入1815 次删除
  1. 85 0
      Documentation/devicetree/bindings/mfd/88pm860x.txt
  2. 20 0
      Documentation/devicetree/bindings/mfd/syscon.txt
  3. 4 0
      Documentation/devicetree/bindings/mfd/tps65910.txt
  4. 46 0
      Documentation/devicetree/bindings/mfd/twl4030-audio.txt
  5. 6 3
      Documentation/devicetree/bindings/mfd/twl6040.txt
  6. 30 0
      Documentation/devicetree/bindings/regulator/88pm860x.txt
  7. 69 0
      Documentation/devicetree/bindings/regulator/max8907.txt
  8. 6 0
      Documentation/devicetree/bindings/regulator/tps6586x.txt
  9. 15 0
      Documentation/devicetree/bindings/video/backlight/88pm860x.txt
  10. 56 0
      Documentation/smsc_ece1099.txt
  11. 7 2
      arch/arm/boot/dts/imx6q.dtsi
  12. 137 0
      arch/arm/boot/dts/pxa910-dkb.dts
  13. 4 0
      arch/arm/boot/dts/pxa910.dtsi
  14. 1 1
      arch/arm/mach-imx/Kconfig
  15. 18 29
      arch/arm/mach-imx/mach-imx6q.c
  16. 22 9
      arch/arm/mach-omap2/usb-host.c
  17. 1 1
      arch/arm/mach-u300/i2c.c
  18. 7 0
      arch/arm/plat-omap/include/plat/usb.h
  19. 7 0
      drivers/gpio/Kconfig
  20. 1 0
      drivers/gpio/Makefile
  21. 69 10
      drivers/gpio/gpio-ich.c
  22. 137 0
      drivers/gpio/gpio-twl6040.c
  23. 16 2
      drivers/input/misc/twl4030-vibra.c
  24. 111 16
      drivers/input/touchscreen/88pm860x-ts.c
  25. 98 107
      drivers/leds/leds-88pm860x.c
  26. 567 238
      drivers/mfd/88pm860x-core.c
  27. 12 162
      drivers/mfd/88pm860x-i2c.c
  28. 58 17
      drivers/mfd/Kconfig
  29. 9 3
      drivers/mfd/Makefile
  30. 1 0
      drivers/mfd/ab3100-core.c
  31. 19 18
      drivers/mfd/ab8500-core.c
  32. 0 124
      drivers/mfd/anatop-mfd.c
  33. 45 11
      drivers/mfd/arizona-irq.c
  34. 423 0
      drivers/mfd/da9055-core.c
  35. 93 0
      drivers/mfd/da9055-i2c.c
  36. 35 12
      drivers/mfd/db8500-prcmu.c
  37. 198 0
      drivers/mfd/lp8788-irq.c
  38. 245 0
      drivers/mfd/lp8788.c
  39. 41 2
      drivers/mfd/lpc_ich.c
  40. 351 0
      drivers/mfd/max8907.c
  41. 334 93
      drivers/mfd/max8925-core.c
  42. 0 1
      drivers/mfd/mc13xxx-core.c
  43. 15 223
      drivers/mfd/omap-usb-host.c
  44. 471 0
      drivers/mfd/omap-usb-tll.c
  45. 77 72
      drivers/mfd/palmas.c
  46. 1 1
      drivers/mfd/rc5t583-irq.c
  47. 1 1
      drivers/mfd/rc5t583.c
  48. 113 0
      drivers/mfd/smsc-ece1099.c
  49. 176 0
      drivers/mfd/syscon.c
  50. 85 27
      drivers/mfd/tc3589x.c
  51. 1 1
      drivers/mfd/tps65090.c
  52. 3 0
      drivers/mfd/tps65217.c
  53. 19 0
      drivers/mfd/tps6586x.c
  54. 32 0
      drivers/mfd/tps65910.c
  55. 64 92
      drivers/mfd/twl-core.c
  56. 70 35
      drivers/mfd/twl4030-audio.c
  57. 16 1
      drivers/mfd/twl6040-core.c
  58. 95 1
      drivers/mfd/wm5110-tables.c
  59. 20 46
      drivers/mfd/wm831x-core.c
  60. 1 1
      drivers/mfd/wm8994-core.c
  61. 1 1
      drivers/mfd/wm8994-regmap.c
  62. 9 0
      drivers/pwm/Kconfig
  63. 1 0
      drivers/pwm/Makefile
  64. 69 50
      drivers/pwm/pwm-twl6030.c
  65. 120 16
      drivers/regulator/88pm8607.c
  66. 1 1
      drivers/regulator/Kconfig
  67. 1 0
      drivers/regulator/ab3100.c
  68. 21 10
      drivers/regulator/anatop-regulator.c
  69. 17 18
      drivers/regulator/max8925-regulator.c
  70. 119 8
      drivers/regulator/palmas-regulator.c
  71. 6 6
      drivers/regulator/wm831x-dcdc.c
  72. 2 2
      drivers/regulator/wm831x-isink.c
  73. 6 6
      drivers/regulator/wm831x-ldo.c
  74. 34 9
      drivers/rtc/rtc-88pm860x.c
  75. 79 67
      drivers/video/backlight/88pm860x_bl.c
  76. 7 0
      drivers/video/backlight/Kconfig
  77. 1 0
      drivers/video/backlight/Makefile
  78. 41 38
      drivers/video/backlight/max8925_bl.c
  79. 342 0
      drivers/video/backlight/tps65217_bl.c
  80. 1 0
      drivers/watchdog/iTCO_wdt.c
  81. 1 0
      include/linux/i2c/twl.h
  82. 2 1
      include/linux/ioport.h
  83. 19 29
      include/linux/mfd/88pm860x.h
  84. 129 0
      include/linux/mfd/ab3100.h
  85. 1 116
      include/linux/mfd/abx500.h
  86. 0 2
      include/linux/mfd/abx500/ab8500.h
  87. 0 40
      include/linux/mfd/anatop.h
  88. 94 0
      include/linux/mfd/da9055/core.h
  89. 32 0
      include/linux/mfd/da9055/pdata.h
  90. 699 0
      include/linux/mfd/da9055/reg.h
  91. 52 0
      include/linux/mfd/lp8788-isink.h
  92. 364 0
      include/linux/mfd/lp8788.h
  93. 1 0
      include/linux/mfd/lpc_ich.h
  94. 252 0
      include/linux/mfd/max8907.h
  95. 23 3
      include/linux/mfd/max8925.h
  96. 202 30
      include/linux/mfd/palmas.h
  97. 109 0
      include/linux/mfd/smsc.h
  98. 23 0
      include/linux/mfd/syscon.h
  99. 319 0
      include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
  100. 1 0
      include/linux/mfd/tc3589x.h

+ 85 - 0
Documentation/devicetree/bindings/mfd/88pm860x.txt

@@ -0,0 +1,85 @@
+* Marvell 88PM860x Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm860x"
+- reg : the I2C slave address for the 88pm860x chip
+- interrupts : IRQ line for the 88pm860x chip
+- interrupt-controller: describes the 88pm860x as an interrupt controller (has its own domain)
+- #interrupt-cells : should be 1.
+		- The cell is the 88pm860x local IRQ number
+
+Optional parent device properties:
+- marvell,88pm860x-irq-read-clr: inicates whether interrupt status is cleared by read
+- marvell,88pm860x-slave-addr: 88pm860x are two chips solution. <reg> stores the I2C address
+				of one chip, and this property stores the I2C address of
+				another chip.
+
+88pm860x consists of a large and varied group of sub-devices:
+
+Device			 Supply Names	 Description
+------			 ------------	 -----------
+88pm860x-onkey		:		: On key
+88pm860x-rtc		:		: RTC
+88pm8607		:		: Regulators
+88pm860x-backlight	:		: Backlight
+88pm860x-led		:		: Led
+88pm860x-touch		:		: Touchscreen
+
+Example:
+
+	pmic: 88pm860x@34 {
+		compatible = "marvell,88pm860x";
+		reg = <0x34>;
+		interrupts = <4>;
+		interrupt-parent = <&intc>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		marvell,88pm860x-irq-read-clr;
+		marvell,88pm860x-slave-addr = <0x11>;
+
+		regulators {
+			BUCK1 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO1 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+		rtc {
+			marvell,88pm860x-vrtc = <1>;
+		};
+		touch {
+			marvell,88pm860x-gpadc-prebias = <1>;
+			marvell,88pm860x-gpadc-slot-cycle = <1>;
+			marvell,88pm860x-tsi-prebias = <6>;
+			marvell,88pm860x-pen-prebias = <16>;
+			marvell,88pm860x-pen-prechg = <2>;
+			marvell,88pm860x-resistor-X = <300>;
+		};
+		backlights {
+			backlight-0 {
+				marvell,88pm860x-iset = <4>;
+				marvell,88pm860x-pwm = <3>;
+			};
+			backlight-2 {
+			};
+		};
+		leds {
+			led0-red {
+				marvell,88pm860x-iset = <12>;
+			};
+			led0-green {
+				marvell,88pm860x-iset = <12>;
+			};
+			led0-blue {
+				marvell,88pm860x-iset = <12>;
+			};
+		};
+	};

+ 20 - 0
Documentation/devicetree/bindings/mfd/syscon.txt

@@ -0,0 +1,20 @@
+* System Controller Registers R/W driver
+
+System controller node represents a register region containing a set
+of miscellaneous registers. The registers are not cohesive enough to
+represent as any specific type of device. The typical use-case is for
+some other node's driver, or platform-specific code, to acquire a
+reference to the syscon node (e.g. by phandle, node path, or search
+using a specific compatible value), interrogate the node (or associated
+OS driver) to determine the location of the registers, and access the
+registers directly.
+
+Required properties:
+- compatible: Should contain "syscon".
+- reg: the register region can be accessed from syscon
+
+Examples:
+gpr: iomuxc-gpr@020e0000 {
+	compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+	reg = <0x020e0000 0x38>;
+};

+ 4 - 0
Documentation/devicetree/bindings/mfd/tps65910.txt

@@ -59,6 +59,8 @@ Optional properties:
   in TPS6591X datasheet)
   in TPS6591X datasheet)
 - ti,en-gpio-sleep: enable sleep control for gpios
 - ti,en-gpio-sleep: enable sleep control for gpios
   There should be 9 entries here, one for each gpio.
   There should be 9 entries here, one for each gpio.
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
 
 
 Regulator Optional properties:
 Regulator Optional properties:
 - ti,regulator-ext-sleep-control: enable external sleep
 - ti,regulator-ext-sleep-control: enable external sleep
@@ -79,6 +81,8 @@ Example:
 		#interrupt-cells = <2>;
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		interrupt-controller;
 
 
+		ti,system-power-controller;
+
 		ti,vmbch-threshold = 0;
 		ti,vmbch-threshold = 0;
 		ti,vmbch2-threshold = 0;
 		ti,vmbch2-threshold = 0;
 		ti,en-ck32k-xtal;
 		ti,en-ck32k-xtal;

+ 46 - 0
Documentation/devicetree/bindings/mfd/twl4030-audio.txt

@@ -0,0 +1,46 @@
+Texas Instruments TWL family (twl4030) audio module
+
+The audio module inside the TWL family consist of an audio codec and a vibra
+driver.
+
+Required properties:
+- compatible : must be "ti,twl4030-audio"
+
+Optional properties, nodes:
+
+Audio functionality:
+- codec { }: Need to be present if the audio functionality is used. Within this
+	     section the following options can be used:
+- ti,digimic_delay: Delay need after enabling the digimic to reduce artifacts
+		    from the start of the recorded sample (in ms)
+-ti,ramp_delay_value: HS ramp delay configuration to reduce pop noise
+-ti,hs_extmute: Use external mute for HS pop reduction
+-ti,hs_extmute_gpio: Use external GPIO to control the external mute
+-ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the
+		      valid values.
+
+Vibra functionality
+- ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if
+		   missing or it is 0, the vibra functionality is disabled.
+
+Example:
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+
+			ti,enable-vibra = <1>;
+
+			codec {
+				ti,ramp_delay_value = <3>;
+			};
+
+		};
+	};
+};

+ 6 - 3
Documentation/devicetree/bindings/mfd/twl6040.txt

@@ -1,7 +1,7 @@
 Texas Instruments TWL6040 family
 Texas Instruments TWL6040 family
 
 
-The TWL6040s are 8-channel high quality low-power audio codecs providing audio
-and vibra functionality on OMAP4+ platforms.
+The TWL6040s are 8-channel high quality low-power audio codecs providing audio,
+vibra and GPO functionality on OMAP4+ platforms.
 They are connected ot the host processor via i2c for commands, McPDM for audio
 They are connected ot the host processor via i2c for commands, McPDM for audio
 data and commands.
 data and commands.
 
 
@@ -10,6 +10,8 @@ Required properties:
 - reg: must be 0x4b for i2c address
 - reg: must be 0x4b for i2c address
 - interrupts: twl6040 has one interrupt line connecteded to the main SoC
 - interrupts: twl6040 has one interrupt line connecteded to the main SoC
 - interrupt-parent: The parent interrupt controller
 - interrupt-parent: The parent interrupt controller
+- gpio-controller:
+- #gpio-cells = <1>: twl6040 provides GPO lines.
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 
 
 - vio-supply: Regulator for the twl6040 VIO supply
 - vio-supply: Regulator for the twl6040 VIO supply
@@ -37,7 +39,6 @@ Example:
 &i2c1 {
 &i2c1 {
 	twl6040: twl@4b {
 	twl6040: twl@4b {
 		compatible = "ti,twl6040";
 		compatible = "ti,twl6040";
-		reg = <0x4b>;
 
 
 		interrupts = <0 119 4>;
 		interrupts = <0 119 4>;
 		interrupt-parent = <&gic>;
 		interrupt-parent = <&gic>;
@@ -60,3 +61,5 @@ Example:
 		};
 		};
 	};
 	};
 };
 };
+
+/include/ "twl6040.dtsi"

+ 30 - 0
Documentation/devicetree/bindings/regulator/88pm860x.txt

@@ -0,0 +1,30 @@
+Marvell 88PM860x regulator
+
+Required properties:
+- compatible: "marvell,88pm860x"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the regulator-compatible
+  property, with valid values listed below.
+
+Example:
+
+	pmic: 88pm860x@34 {
+		compatible = "marvell,88pm860x";
+		reg = <0x34>;
+
+		regulators {
+			BUCK1 {
+			        regulator-min-microvolt = <1000000>;
+			        regulator-max-microvolt = <1500000>;
+			        regulator-boot-on;
+			        regulator-always-on;
+			};
+			BUCK3 {
+			        regulator-min-microvolt = <1000000>;
+			        regulator-max-microvolt = <3000000>;
+			        regulator-boot-on;
+			        regulator-always-on;
+			};
+		};
+	};

+ 69 - 0
Documentation/devicetree/bindings/regulator/max8907.txt

@@ -0,0 +1,69 @@
+MAX8907 regulator
+
+Required properties:
+- compatible: "maxim,max8907"
+- reg: I2C slave address
+- interrupts: The interrupt output of the controller
+- mbatt-supply: The input supply for MBATT, BBAT, SDBY, VRTC.
+- in-v1-supply: The input supply for SD1.
+- in-v2-supply: The input supply for SD2.
+- in-v3-supply: The input supply for SD3.
+- in1-supply: The input supply for LDO1.
+...
+- in20-supply: The input supply for LDO20.
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+Optional properties:
+- maxim,system-power-controller: Boolean property indicating that the PMIC
+  controls the overall system power.
+
+The valid names for regulators are:
+
+  sd1, sd2, sd3, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8, ldo9, ldo10,
+  ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19, ldo20, out5v,
+  out33v, bbat, sdby, vrtc.
+
+Example:
+
+		max8907@3c {
+			compatible = "maxim,max8907";
+			reg = <0x3c>;
+			interrupts = <0 86 0x4>;
+
+			maxim,system-power-controller;
+
+			mbatt-supply = <&some_reg>;
+			in-v1-supply = <&mbatt_reg>;
+			...
+			in1-supply = <&mbatt_reg>;
+			...
+
+			regulators {
+				mbatt_reg: mbatt {
+					regulator-name = "vbat_pmu";
+					regulator-min-microvolt = <5000000>;
+					regulator-max-microvolt = <5000000>;
+					regulator-always-on;
+				};
+
+				sd1 {
+					regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sd2 {
+					regulator-name = "nvvdd_sv2,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+...
+			};
+		};
+	};

+ 6 - 0
Documentation/devicetree/bindings/regulator/tps6586x.txt

@@ -22,6 +22,10 @@ Required properties:
 - vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
 - vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
 - vinldo9-supply: The input supply for the LDO9
 - vinldo9-supply: The input supply for the LDO9
 
 
+Optional properties:
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
+
 Each regulator is defined using the standard binding for regulators.
 Each regulator is defined using the standard binding for regulators.
 
 
 Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver
 Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver
@@ -37,6 +41,8 @@ Example:
 		#gpio-cells = <2>;
 		#gpio-cells = <2>;
 		gpio-controller;
 		gpio-controller;
 
 
+		ti,system-power-controller;
+
 		sys-supply = <&some_reg>;
 		sys-supply = <&some_reg>;
 		vin-sm0-supply = <&some_reg>;
 		vin-sm0-supply = <&some_reg>;
 		vin-sm1-supply = <&some_reg>;
 		vin-sm1-supply = <&some_reg>;

+ 15 - 0
Documentation/devicetree/bindings/video/backlight/88pm860x.txt

@@ -0,0 +1,15 @@
+88pm860x-backlight bindings
+
+Optional properties:
+  - marvell,88pm860x-iset: Current supplies on backlight device.
+  - marvell,88pm860x-pwm: PWM frequency on backlight device.
+
+Example:
+
+	backlights {
+		backlight-0 {
+			marvell,88pm860x-iset = <4>;
+			marvell,88pm860x-pwm = <3>;
+		};
+		backlight-2 {
+		};

+ 56 - 0
Documentation/smsc_ece1099.txt

@@ -0,0 +1,56 @@
+What is smsc-ece1099?
+----------------------
+
+The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
+or GPIO Expansion device. The device supports a keyboard
+scan matrix of 23x8. The device is connected to a Master
+via the SMSC BC-Link interface or via the SMBus.
+Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
+are multiplexed with GPIOs.
+
+Interrupt generation
+--------------------
+
+Interrupts can be generated by an edge detection on a GPIO
+pin or an edge detection on one of the bus interface pins.
+Interrupts can also be detected on the keyboard scan interface.
+The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
+any bit in one of the Interrupt Status registers is 1 and
+the corresponding Interrupt Mask bit is also 1.
+
+In order for software to determine which device is the source
+of an interrupt, it should first read the Group Interrupt Status Register
+to determine which Status register group is a source for the interrupt.
+Software should read both the Status register and the associated Mask register,
+then AND the two values together. Bits that are 1 in the result of the AND
+are active interrupts. Software clears an interrupt by writing a 1 to the
+corresponding bit in the Status register.
+
+Communication Protocol
+----------------------
+
+- SMbus slave Interface
+	The host processor communicates with the ECE1099 device
+	through a series of read/write registers via the SMBus
+	interface. SMBus is a serial communication protocol between
+	a computer host and its peripheral devices. The SMBus data
+	rate is 10KHz minimum to 400 KHz maximum
+
+- Slave Bus Interface
+	The ECE1099 device SMBus implementation is a subset of the
+	SMBus interface to the host. The device is a slave-only SMBus device.
+	The implementation in the device is a subset of SMBus since it
+	only supports four protocols.
+
+	The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
+	only valid SMBus protocols for the device.
+
+- BC-LinkTM Interface
+	The BC-Link is a proprietary bus that allows communication
+	between a Master device and a Companion device. The Master
+	device uses this serial bus to read and write registers
+	located on the Companion device. The bus comprises three signals,
+	BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
+	clock, BC_CLK, and the Companion device is the source for an
+	independent asynchronous interrupt signal, BC_INT#. The ECE1099
+	supports BC-Link speeds up to 24MHz.

+ 7 - 2
arch/arm/boot/dts/imx6q.dtsi

@@ -400,8 +400,8 @@
 				#clock-cells = <1>;
 				#clock-cells = <1>;
 			};
 			};
 
 
-			anatop@020c8000 {
-				compatible = "fsl,imx6q-anatop";
+			anatop: anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
 				reg = <0x020c8000 0x1000>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 
 
@@ -531,6 +531,11 @@
 				interrupts = <0 89 0x04 0 90 0x04>;
 				interrupts = <0 89 0x04 0 90 0x04>;
 			};
 			};
 
 
+			gpr: iomuxc-gpr@020e0000 {
+				compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+				reg = <0x020e0000 0x38>;
+			};
+
 			iomuxc@020e0000 {
 			iomuxc@020e0000 {
 				compatible = "fsl,imx6q-iomuxc";
 				compatible = "fsl,imx6q-iomuxc";
 				reg = <0x020e0000 0x4000>;
 				reg = <0x020e0000 0x4000>;

+ 137 - 0
arch/arm/boot/dts/pxa910-dkb.dts

@@ -29,6 +29,143 @@
 			};
 			};
 			twsi1: i2c@d4011000 {
 			twsi1: i2c@d4011000 {
 				status = "okay";
 				status = "okay";
+
+				pmic: 88pm860x@34 {
+					compatible = "marvell,88pm860x";
+					reg = <0x34>;
+					interrupts = <4>;
+					interrupt-parent = <&intc>;
+					interrupt-controller;
+					#interrupt-cells = <1>;
+
+					marvell,88pm860x-irq-read-clr;
+					marvell,88pm860x-slave-addr = <0x11>;
+
+					regulators {
+						BUCK1 {
+							regulator-min-microvolt = <1000000>;
+							regulator-max-microvolt = <1500000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						BUCK2 {
+							regulator-min-microvolt = <1000000>;
+							regulator-max-microvolt = <1500000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						BUCK3 {
+							regulator-min-microvolt = <1000000>;
+							regulator-max-microvolt = <3000000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO1 {
+							regulator-min-microvolt = <1200000>;
+							regulator-max-microvolt = <2800000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO2 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO3 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO4 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-always-on;
+						};
+						LDO5 {
+							regulator-min-microvolt = <2900000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO6 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO7 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <2900000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO8 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <2900000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO9 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO10 {
+							regulator-min-microvolt = <1200000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-boot-on;
+							regulator-always-on;
+						};
+						LDO12 {
+							regulator-min-microvolt = <1200000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-always-on;
+						};
+						LDO13 {
+							regulator-min-microvolt = <1200000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-always-on;
+						};
+						LDO14 {
+							regulator-min-microvolt = <1800000>;
+							regulator-max-microvolt = <3300000>;
+							regulator-always-on;
+						};
+					};
+					rtc {
+						marvell,88pm860x-vrtc = <1>;
+					};
+					touch {
+						marvell,88pm860x-gpadc-prebias = <1>;
+						marvell,88pm860x-gpadc-slot-cycle = <1>;
+						marvell,88pm860x-tsi-prebias = <6>;
+						marvell,88pm860x-pen-prebias = <16>;
+						marvell,88pm860x-pen-prechg = <2>;
+						marvell,88pm860x-resistor-X = <300>;
+					};
+					backlights {
+						backlight-0 {
+							marvell,88pm860x-iset = <4>;
+							marvell,88pm860x-pwm = <3>;
+						};
+						backlight-2 {
+						};
+					};
+					leds {
+						led0-red {
+							marvell,88pm860x-iset = <12>;
+						};
+						led0-green {
+							marvell,88pm860x-iset = <12>;
+						};
+						led0-blue {
+							marvell,88pm860x-iset = <12>;
+						};
+					};
+				};
 			};
 			};
 			rtc: rtc@d4010000 {
 			rtc: rtc@d4010000 {
 				status = "okay";
 				status = "okay";

+ 4 - 0
arch/arm/boot/dts/pxa910.dtsi

@@ -120,6 +120,8 @@
 
 
 			twsi1: i2c@d4011000 {
 			twsi1: i2c@d4011000 {
 				compatible = "mrvl,mmp-twsi";
 				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0xd4011000 0x1000>;
 				reg = <0xd4011000 0x1000>;
 				interrupts = <7>;
 				interrupts = <7>;
 				mrvl,i2c-fast-mode;
 				mrvl,i2c-fast-mode;
@@ -128,6 +130,8 @@
 
 
 			twsi2: i2c@d4037000 {
 			twsi2: i2c@d4037000 {
 				compatible = "mrvl,mmp-twsi";
 				compatible = "mrvl,mmp-twsi";
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0xd4037000 0x1000>;
 				reg = <0xd4037000 0x1000>;
 				interrupts = <54>;
 				interrupts = <54>;
 				status = "disabled";
 				status = "disabled";

+ 1 - 1
arch/arm/mach-imx/Kconfig

@@ -758,7 +758,7 @@ config SOC_IMX6Q
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_SRC
 	select HAVE_IMX_SRC
 	select HAVE_SMP
 	select HAVE_SMP
-	select MFD_ANATOP
+	select MFD_SYSCON
 	select PINCTRL
 	select PINCTRL
 	select PINCTRL_IMX6Q
 	select PINCTRL_IMX6Q
 
 

+ 18 - 29
arch/arm/mach-imx/mach-imx6q.c

@@ -23,8 +23,9 @@
 #include <linux/of_irq.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
 #include <linux/phy.h>
+#include <linux/regmap.h>
 #include <linux/micrel_phy.h>
 #include <linux/micrel_phy.h>
-#include <linux/mfd/anatop.h>
+#include <linux/mfd/syscon.h>
 #include <asm/cpuidle.h>
 #include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -118,20 +119,7 @@ static void __init imx6q_sabrelite_init(void)
 
 
 static void __init imx6q_usb_init(void)
 static void __init imx6q_usb_init(void)
 {
 {
-	struct device_node *np;
-	struct platform_device *pdev = NULL;
-	struct anatop *adata = NULL;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-	if (np)
-		pdev = of_find_device_by_node(np);
-	if (pdev)
-		adata = platform_get_drvdata(pdev);
-	if (!adata) {
-		if (np)
-			of_node_put(np);
-		return;
-	}
+	struct regmap *anatop;
 
 
 #define HW_ANADIG_USB1_CHRG_DETECT		0x000001b0
 #define HW_ANADIG_USB1_CHRG_DETECT		0x000001b0
 #define HW_ANADIG_USB2_CHRG_DETECT		0x00000210
 #define HW_ANADIG_USB2_CHRG_DETECT		0x00000210
@@ -139,20 +127,21 @@ static void __init imx6q_usb_init(void)
 #define BM_ANADIG_USB_CHRG_DETECT_EN_B		0x00100000
 #define BM_ANADIG_USB_CHRG_DETECT_EN_B		0x00100000
 #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B	0x00080000
 #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B	0x00080000
 
 
-	/*
-	 * The external charger detector needs to be disabled,
-	 * or the signal at DP will be poor
-	 */
-	anatop_write_reg(adata, HW_ANADIG_USB1_CHRG_DETECT,
-			BM_ANADIG_USB_CHRG_DETECT_EN_B
-			| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-			~0);
-	anatop_write_reg(adata, HW_ANADIG_USB2_CHRG_DETECT,
-			BM_ANADIG_USB_CHRG_DETECT_EN_B |
-			BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-			~0);
-
-	of_node_put(np);
+	anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
+	if (!IS_ERR(anatop)) {
+		/*
+		 * The external charger detector needs to be disabled,
+		 * or the signal at DP will be poor
+		 */
+		regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT,
+				BM_ANADIG_USB_CHRG_DETECT_EN_B
+				| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+		regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT,
+				BM_ANADIG_USB_CHRG_DETECT_EN_B |
+				BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+	} else {
+		pr_warn("failed to find fsl,imx6q-anatop regmap\n");
+	}
 }
 }
 
 
 static void __init imx6q_init_machine(void)
 static void __init imx6q_init_machine(void)

+ 22 - 9
arch/arm/mach-omap2/usb-host.c

@@ -33,10 +33,12 @@
 #ifdef CONFIG_MFD_OMAP_USB_HOST
 #ifdef CONFIG_MFD_OMAP_USB_HOST
 
 
 #define OMAP_USBHS_DEVICE	"usbhs_omap"
 #define OMAP_USBHS_DEVICE	"usbhs_omap"
+#define OMAP_USBTLL_DEVICE	"usbhs_tll"
 #define	USBHS_UHH_HWMODNAME	"usb_host_hs"
 #define	USBHS_UHH_HWMODNAME	"usb_host_hs"
 #define USBHS_TLL_HWMODNAME	"usb_tll_hs"
 #define USBHS_TLL_HWMODNAME	"usb_tll_hs"
 
 
 static struct usbhs_omap_platform_data		usbhs_data;
 static struct usbhs_omap_platform_data		usbhs_data;
+static struct usbtll_omap_platform_data		usbtll_data;
 static struct ehci_hcd_omap_platform_data	ehci_data;
 static struct ehci_hcd_omap_platform_data	ehci_data;
 static struct ohci_hcd_omap_platform_data	ohci_data;
 static struct ohci_hcd_omap_platform_data	ohci_data;
 
 
@@ -485,13 +487,14 @@ void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 
 
 void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 {
 {
-	struct omap_hwmod	*oh[2];
+	struct omap_hwmod	*uhh_hwm, *tll_hwm;
 	struct platform_device	*pdev;
 	struct platform_device	*pdev;
 	int			bus_id = -1;
 	int			bus_id = -1;
 	int			i;
 	int			i;
 
 
 	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
 	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
 		usbhs_data.port_mode[i] = pdata->port_mode[i];
 		usbhs_data.port_mode[i] = pdata->port_mode[i];
+		usbtll_data.port_mode[i] = pdata->port_mode[i];
 		ohci_data.port_mode[i] = pdata->port_mode[i];
 		ohci_data.port_mode[i] = pdata->port_mode[i];
 		ehci_data.port_mode[i] = pdata->port_mode[i];
 		ehci_data.port_mode[i] = pdata->port_mode[i];
 		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
 		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
@@ -510,25 +513,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 		setup_4430ohci_io_mux(pdata->port_mode);
 		setup_4430ohci_io_mux(pdata->port_mode);
 	}
 	}
 
 
-	oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
-	if (!oh[0]) {
+	uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
+	if (!uhh_hwm) {
 		pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
 		pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
 		return;
 		return;
 	}
 	}
 
 
-	oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
-	if (!oh[1]) {
+	tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
+	if (!tll_hwm) {
 		pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
 		pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
 		return;
 		return;
 	}
 	}
 
 
-	pdev = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2,
-				(void *)&usbhs_data, sizeof(usbhs_data),
+	pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
+				&usbtll_data, sizeof(usbtll_data),
 				omap_uhhtll_latency,
 				omap_uhhtll_latency,
 				ARRAY_SIZE(omap_uhhtll_latency), false);
 				ARRAY_SIZE(omap_uhhtll_latency), false);
 	if (IS_ERR(pdev)) {
 	if (IS_ERR(pdev)) {
-		pr_err("Could not build hwmod devices %s,%s\n",
-			USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
+		pr_err("Could not build hwmod device %s\n",
+		       USBHS_TLL_HWMODNAME);
+		return;
+	}
+
+	pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
+				&usbhs_data, sizeof(usbhs_data),
+				omap_uhhtll_latency,
+				ARRAY_SIZE(omap_uhhtll_latency), false);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build hwmod devices %s\n",
+		       USBHS_UHH_HWMODNAME);
 		return;
 		return;
 	}
 	}
 }
 }

+ 1 - 1
arch/arm/mach-u300/i2c.c

@@ -9,7 +9,7 @@
  */
  */
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
-#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/machine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/bus.h>
 #include <mach/irqs.h>
 #include <mach/irqs.h>

+ 7 - 0
arch/arm/plat-omap/include/plat/usb.h

@@ -4,6 +4,7 @@
 #define	__ASM_ARCH_OMAP_USB_H
 #define	__ASM_ARCH_OMAP_USB_H
 
 
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <linux/usb/musb.h>
 #include <linux/usb/musb.h>
 
 
 #define OMAP3_HS_USB_PORTS	3
 #define OMAP3_HS_USB_PORTS	3
@@ -63,6 +64,10 @@ struct usbhs_omap_platform_data {
 	struct ehci_hcd_omap_platform_data	*ehci_data;
 	struct ehci_hcd_omap_platform_data	*ehci_data;
 	struct ohci_hcd_omap_platform_data	*ohci_data;
 	struct ohci_hcd_omap_platform_data	*ohci_data;
 };
 };
+
+struct usbtll_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+};
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 struct omap_musb_board_data {
 struct omap_musb_board_data {
@@ -81,6 +86,8 @@ enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
 
 extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
 extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
 
 
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);

+ 7 - 0
drivers/gpio/Kconfig

@@ -409,6 +409,13 @@ config GPIO_TWL4030
 	  Say yes here to access the GPIO signals of various multi-function
 	  Say yes here to access the GPIO signals of various multi-function
 	  power management chips from Texas Instruments.
 	  power management chips from Texas Instruments.
 
 
+config GPIO_TWL6040
+	tristate "TWL6040 GPO"
+	depends on TWL6040_CORE
+	help
+	  Say yes here to access the GPO signals of twl6040
+	  audio chip from Texas Instruments.
+
 config GPIO_WM831X
 config GPIO_WM831X
 	tristate "WM831x GPIOs"
 	tristate "WM831x GPIOs"
 	depends on MFD_WM831X
 	depends on MFD_WM831X

+ 1 - 0
drivers/gpio/Makefile

@@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
+obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
 obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
 obj-$(CONFIG_GPIO_VT8500)	+= gpio-vt8500.o
 obj-$(CONFIG_GPIO_VT8500)	+= gpio-vt8500.o

+ 69 - 10
drivers/gpio/gpio-ich.c

@@ -49,6 +49,10 @@ static const u8 ichx_regs[3][3] = {
 	{0x0c, 0x38, 0x48},	/* LVL[1-3] offsets */
 	{0x0c, 0x38, 0x48},	/* LVL[1-3] offsets */
 };
 };
 
 
+static const u8 ichx_reglen[3] = {
+	0x30, 0x10, 0x10,
+};
+
 #define ICHX_WRITE(val, reg, base_res)	outl(val, (reg) + (base_res)->start)
 #define ICHX_WRITE(val, reg, base_res)	outl(val, (reg) + (base_res)->start)
 #define ICHX_READ(reg, base_res)	inl((reg) + (base_res)->start)
 #define ICHX_READ(reg, base_res)	inl((reg) + (base_res)->start)
 
 
@@ -75,6 +79,7 @@ static struct {
 	struct resource *pm_base;	/* Power Mangagment IO base */
 	struct resource *pm_base;	/* Power Mangagment IO base */
 	struct ichx_desc *desc;	/* Pointer to chipset-specific description */
 	struct ichx_desc *desc;	/* Pointer to chipset-specific description */
 	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */
 	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */
+	u8 use_gpio;		/* Which GPIO groups are usable */
 } ichx_priv;
 } ichx_priv;
 
 
 static int modparam_gpiobase = -1;	/* dynamic */
 static int modparam_gpiobase = -1;	/* dynamic */
@@ -123,8 +128,16 @@ static int ichx_read_bit(int reg, unsigned nr)
 	return data & (1 << bit) ? 1 : 0;
 	return data & (1 << bit) ? 1 : 0;
 }
 }
 
 
+static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
+{
+	return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO;
+}
+
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
 {
+	if (!ichx_gpio_check_available(gpio, nr))
+		return -ENXIO;
+
 	/*
 	/*
 	 * Try setting pin as an input and verify it worked since many pins
 	 * Try setting pin as an input and verify it worked since many pins
 	 * are output-only.
 	 * are output-only.
@@ -138,6 +151,9 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 					int val)
 					int val)
 {
 {
+	if (!ichx_gpio_check_available(gpio, nr))
+		return -ENXIO;
+
 	/* Set GPIO output value. */
 	/* Set GPIO output value. */
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 
 
@@ -153,6 +169,9 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 
 
 static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
 static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
 {
 {
+	if (!ichx_gpio_check_available(chip, nr))
+		return -ENXIO;
+
 	return ichx_read_bit(GPIO_LVL, nr);
 	return ichx_read_bit(GPIO_LVL, nr);
 }
 }
 
 
@@ -161,6 +180,9 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
 	unsigned long flags;
 	unsigned long flags;
 	u32 data;
 	u32 data;
 
 
+	if (!ichx_gpio_check_available(chip, nr))
+		return -ENXIO;
+
 	/*
 	/*
 	 * GPI 0 - 15 need to be read from the power management registers on
 	 * GPI 0 - 15 need to be read from the power management registers on
 	 * a ICH6/3100 bridge.
 	 * a ICH6/3100 bridge.
@@ -291,6 +313,46 @@ static struct ichx_desc intel5_desc = {
 	.ngpio = 76,
 	.ngpio = 76,
 };
 };
 
 
+static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+						const char *name, u8 use_gpio)
+{
+	int i;
+
+	if (!res_base || !res_base->start || !res_base->end)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		if (!request_region(res_base->start + ichx_regs[0][i],
+				    ichx_reglen[i], name))
+			goto request_err;
+	}
+	return 0;
+
+request_err:
+	/* Clean up: release already requested regions, if any */
+	for (i--; i >= 0; i--) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		release_region(res_base->start + ichx_regs[0][i],
+			       ichx_reglen[i]);
+	}
+	return -EBUSY;
+}
+
+static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		release_region(res_base->start + ichx_regs[0][i],
+			       ichx_reglen[i]);
+	}
+}
+
 static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 {
 {
 	struct resource *res_base, *res_pm;
 	struct resource *res_base, *res_pm;
@@ -329,12 +391,11 @@ static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
 	res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
-	if (!res_base || !res_base->start || !res_base->end)
-		return -ENODEV;
-
-	if (!request_region(res_base->start, resource_size(res_base),
-				pdev->name))
-		return -EBUSY;
+	ichx_priv.use_gpio = ich_info->use_gpio;
+	err = ichx_gpio_request_regions(res_base, pdev->name,
+					ichx_priv.use_gpio);
+	if (err)
+		return err;
 
 
 	ichx_priv.gpio_base = res_base;
 	ichx_priv.gpio_base = res_base;
 
 
@@ -374,8 +435,7 @@ init:
 	return 0;
 	return 0;
 
 
 add_err:
 add_err:
-	release_region(ichx_priv.gpio_base->start,
-			resource_size(ichx_priv.gpio_base));
+	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
 	if (ichx_priv.pm_base)
 	if (ichx_priv.pm_base)
 		release_region(ichx_priv.pm_base->start,
 		release_region(ichx_priv.pm_base->start,
 				resource_size(ichx_priv.pm_base));
 				resource_size(ichx_priv.pm_base));
@@ -393,8 +453,7 @@ static int __devexit ichx_gpio_remove(struct platform_device *pdev)
 		return err;
 		return err;
 	}
 	}
 
 
-	release_region(ichx_priv.gpio_base->start,
-				resource_size(ichx_priv.gpio_base));
+	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
 	if (ichx_priv.pm_base)
 	if (ichx_priv.pm_base)
 		release_region(ichx_priv.pm_base->start,
 		release_region(ichx_priv.pm_base->start,
 				resource_size(ichx_priv.pm_base));
 				resource_size(ichx_priv.pm_base));

+ 137 - 0
drivers/gpio/gpio-twl6040.c

@@ -0,0 +1,137 @@
+/*
+ * Access to GPOs on TWL6040 chip
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Authors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <linux/mfd/twl6040.h>
+
+static struct gpio_chip twl6040gpo_chip;
+
+static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+	int ret = 0;
+
+	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+	if (ret < 0)
+		return ret;
+
+	return (ret >> offset) & 1;
+}
+
+static int twl6040gpo_direction_out(struct gpio_chip *chip, unsigned offset,
+				    int value)
+{
+	/* This only drives GPOs, and can't change direction */
+	return 0;
+}
+
+static void twl6040gpo_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+	int ret;
+	u8 gpoctl;
+
+	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+	if (ret < 0)
+		return;
+
+	if (value)
+		gpoctl = ret | (1 << offset);
+	else
+		gpoctl = ret & ~(1 << offset);
+
+	twl6040_reg_write(twl6040, TWL6040_REG_GPOCTL, gpoctl);
+}
+
+static struct gpio_chip twl6040gpo_chip = {
+	.label			= "twl6040",
+	.owner			= THIS_MODULE,
+	.get			= twl6040gpo_get,
+	.direction_output	= twl6040gpo_direction_out,
+	.set			= twl6040gpo_set,
+	.can_sleep		= 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+{
+	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
+	struct device *twl6040_core_dev = pdev->dev.parent;
+	struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
+	int ret;
+
+	if (pdata)
+		twl6040gpo_chip.base = pdata->gpio_base;
+	else
+		twl6040gpo_chip.base = -1;
+
+	if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
+		twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */
+	else
+		twl6040gpo_chip.ngpio = 1; /* twl6041 have 1 GPO */
+
+	twl6040gpo_chip.dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+	twl6040gpo_chip.of_node = twl6040_core_dev->of_node;
+#endif
+
+	ret = gpiochip_add(&twl6040gpo_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
+		twl6040gpo_chip.ngpio = 0;
+	}
+
+	return ret;
+}
+
+static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+{
+	return gpiochip_remove(&twl6040gpo_chip);
+}
+
+/* Note:  this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl6040-gpo");
+
+static struct platform_driver gpo_twl6040_driver = {
+	.driver = {
+		.name	= "twl6040-gpo",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= gpo_twl6040_probe,
+	.remove		= gpo_twl6040_remove,
+};
+
+module_platform_driver(gpo_twl6040_driver);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPO interface for TWL6040");
+MODULE_LICENSE("GPL");

+ 16 - 2
drivers/input/misc/twl4030-vibra.c

@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/twl4030-audio.h>
 #include <linux/mfd/twl4030-audio.h>
@@ -194,13 +195,26 @@ static int twl4030_vibra_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 			 twl4030_vibra_suspend, twl4030_vibra_resume);
 			 twl4030_vibra_suspend, twl4030_vibra_resume);
 
 
+static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
+			      struct device_node *node)
+{
+	if (pdata && pdata->coexist)
+		return true;
+
+	if (of_find_node_by_name(node, "codec"))
+		return true;
+
+	return false;
+}
+
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
 {
 	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
 	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+	struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
 	struct vibra_info *info;
 	struct vibra_info *info;
 	int ret;
 	int ret;
 
 
-	if (!pdata) {
+	if (!pdata && !twl4030_core_node) {
 		dev_dbg(&pdev->dev, "platform_data not available\n");
 		dev_dbg(&pdev->dev, "platform_data not available\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -210,7 +224,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	info->dev = &pdev->dev;
 	info->dev = &pdev->dev;
-	info->coexist = pdata->coexist;
+	info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
 	INIT_WORK(&info->play_work, vibra_play_work);
 	INIT_WORK(&info->play_work, vibra_play_work);
 
 
 	info->input_dev = input_allocate_device();
 	info->input_dev = input_allocate_device();

+ 111 - 16
drivers/input/touchscreen/88pm860x-ts.c

@@ -10,6 +10,7 @@
  */
  */
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input.h>
@@ -113,14 +114,69 @@ static void pm860x_touch_close(struct input_dev *dev)
 	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
 	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
 }
 }
 
 
+#ifdef CONFIG_OF
+static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
+					  struct pm860x_chip *chip,
+					  int *res_x)
+{
+	struct device_node *np = pdev->dev.parent->of_node;
+	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+				 : chip->companion;
+	int data, n, ret;
+	if (!np)
+		return -ENODEV;
+	np = of_find_node_by_name(np, "touch");
+	if (!np) {
+		dev_err(&pdev->dev, "Can't find touch node\n");
+		return -EINVAL;
+	}
+	/* set GPADC MISC1 register */
+	data = 0;
+	if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n))
+		data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK;
+	if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n))
+		data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
+	if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n))
+		data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK;
+	if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n))
+		data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK;
+	if (data) {
+		ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+		if (ret < 0)
+			return -EINVAL;
+	}
+	/* set tsi prebias time */
+	if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
+		ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+		if (ret < 0)
+			return -EINVAL;
+	}
+	/* set prebias & prechg time of pen detect */
+	data = 0;
+	if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n))
+		data |= n & PM8607_PD_PREBIAS_MASK;
+	if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n))
+		data |= n & PM8607_PD_PRECHG_MASK;
+	if (data) {
+		ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+		if (ret < 0)
+			return -EINVAL;
+	}
+	of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
+	return 0;
+}
+#else
+#define pm860x_touch_dt_init(x, y, z)	(-1)
+#endif
+
 static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 {
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_platform_data *pm860x_pdata =		\
-				pdev->dev.parent->platform_data;
-	struct pm860x_touch_pdata *pdata = NULL;
+	struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
 	struct pm860x_touch *touch;
 	struct pm860x_touch *touch;
-	int irq, ret;
+	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+				 : chip->companion;
+	int irq, ret, res_x = 0, data = 0;
 
 
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
@@ -128,16 +184,55 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (!pm860x_pdata) {
-		dev_err(&pdev->dev, "platform data is missing\n");
-		return -EINVAL;
-	}
-
-	pdata = pm860x_pdata->touch;
-	if (!pdata) {
-		dev_err(&pdev->dev, "touchscreen data is missing\n");
-		return -EINVAL;
+	if (pm860x_touch_dt_init(pdev, chip, &res_x)) {
+		if (pdata) {
+			/* set GPADC MISC1 register */
+			data = 0;
+			data |= (pdata->gpadc_prebias << 1)
+				& PM8607_GPADC_PREBIAS_MASK;
+			data |= (pdata->slot_cycle << 3)
+				& PM8607_GPADC_SLOT_CYCLE_MASK;
+			data |= (pdata->off_scale << 5)
+				& PM8607_GPADC_OFF_SCALE_MASK;
+			data |= (pdata->sw_cal << 7)
+				& PM8607_GPADC_SW_CAL_MASK;
+			if (data) {
+				ret = pm860x_reg_write(i2c,
+					PM8607_GPADC_MISC1, data);
+				if (ret < 0)
+					return -EINVAL;
+			}
+			/* set tsi prebias time */
+			if (pdata->tsi_prebias) {
+				data = pdata->tsi_prebias;
+				ret = pm860x_reg_write(i2c,
+					PM8607_TSI_PREBIAS, data);
+				if (ret < 0)
+					return -EINVAL;
+			}
+			/* set prebias & prechg time of pen detect */
+			data = 0;
+			data |= pdata->pen_prebias
+				& PM8607_PD_PREBIAS_MASK;
+			data |= (pdata->pen_prechg << 5)
+				& PM8607_PD_PRECHG_MASK;
+			if (data) {
+				ret = pm860x_reg_write(i2c,
+					PM8607_PD_PREBIAS, data);
+				if (ret < 0)
+					return -EINVAL;
+			}
+			res_x = pdata->res_x;
+		} else {
+			dev_err(&pdev->dev, "failed to get platform data\n");
+			return -EINVAL;
+		}
 	}
 	}
+	/* enable GPADC */
+	ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN,
+			      PM8607_GPADC_EN);
+	if (ret)
+		return ret;
 
 
 	touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
 	touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
 	if (touch == NULL)
 	if (touch == NULL)
@@ -158,9 +253,9 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->open = pm860x_touch_open;
 	touch->idev->close = pm860x_touch_close;
 	touch->idev->close = pm860x_touch_close;
 	touch->chip = chip;
 	touch->chip = chip;
-	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-	touch->irq = irq + chip->irq_base;
-	touch->res_x = pdata->res_x;
+	touch->i2c = i2c;
+	touch->irq = irq;
+	touch->res_x = res_x;
 	input_set_drvdata(touch->idev, touch);
 	input_set_drvdata(touch->idev, touch);
 
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,

+ 98 - 107
drivers/leds/leds-88pm860x.c

@@ -12,6 +12,7 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
@@ -20,18 +21,12 @@
 #include <linux/mfd/88pm860x.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/module.h>
 #include <linux/module.h>
 
 
-#define LED_PWM_SHIFT		(3)
 #define LED_PWM_MASK		(0x1F)
 #define LED_PWM_MASK		(0x1F)
 #define LED_CURRENT_MASK	(0x07 << 5)
 #define LED_CURRENT_MASK	(0x07 << 5)
 
 
-#define LED_BLINK_ON_MASK	(0x07)
 #define LED_BLINK_MASK		(0x7F)
 #define LED_BLINK_MASK		(0x7F)
 
 
-#define LED_BLINK_ON(x)		((x & 0x7) * 66 + 66)
-#define LED_BLINK_ON_MIN	LED_BLINK_ON(0)
-#define LED_BLINK_ON_MAX	LED_BLINK_ON(0x7)
 #define LED_ON_CONTINUOUS	(0x0F << 3)
 #define LED_ON_CONTINUOUS	(0x0F << 3)
-#define LED_TO_ON(x)		((x - 66) / 66)
 
 
 #define LED1_BLINK_EN		(1 << 1)
 #define LED1_BLINK_EN		(1 << 1)
 #define LED2_BLINK_EN		(1 << 2)
 #define LED2_BLINK_EN		(1 << 2)
@@ -49,85 +44,25 @@ struct pm860x_led {
 	unsigned char brightness;
 	unsigned char brightness;
 	unsigned char current_brightness;
 	unsigned char current_brightness;
 
 
-	int blink_data;
-	int blink_time;
-	int blink_on;
-	int blink_off;
+	int reg_control;
+	int reg_blink;
+	int blink_mask;
 };
 };
 
 
-/* return offset of color register */
-static inline int __led_off(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = port - PM8606_LED1_RED + PM8606_RGB1B;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = port - PM8606_LED2_RED + PM8606_RGB2B;
-		break;
-	}
-	return ret;
-}
-
-/* return offset of blink register */
-static inline int __blink_off(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = PM8606_RGB1A;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = PM8606_RGB2A;
-		break;
-	}
-	return ret;
-}
-
-static inline int __blink_ctl_mask(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = LED1_BLINK_EN;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = LED2_BLINK_EN;
-		break;
-	}
-	return ret;
-}
-
 static int led_power_set(struct pm860x_chip *chip, int port, int on)
 static int led_power_set(struct pm860x_chip *chip, int port, int on)
 {
 {
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
 	switch (port) {
 	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
+	case 0:
+	case 1:
+	case 2:
 		ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
 		ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
 			pm8606_osc_disable(chip, RGB1_ENABLE);
 			pm8606_osc_disable(chip, RGB1_ENABLE);
 		break;
 		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
+	case 3:
+	case 4:
+	case 5:
 		ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
 		ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
 			pm8606_osc_disable(chip, RGB2_ENABLE);
 			pm8606_osc_disable(chip, RGB2_ENABLE);
 		break;
 		break;
@@ -141,7 +76,7 @@ static void pm860x_led_work(struct work_struct *work)
 	struct pm860x_led *led;
 	struct pm860x_led *led;
 	struct pm860x_chip *chip;
 	struct pm860x_chip *chip;
 	unsigned char buf[3];
 	unsigned char buf[3];
-	int mask, ret;
+	int ret;
 
 
 	led = container_of(work, struct pm860x_led, work);
 	led = container_of(work, struct pm860x_led, work);
 	chip = led->chip;
 	chip = led->chip;
@@ -149,34 +84,34 @@ static void pm860x_led_work(struct work_struct *work)
 	if ((led->current_brightness == 0) && led->brightness) {
 	if ((led->current_brightness == 0) && led->brightness) {
 		led_power_set(chip, led->port, 1);
 		led_power_set(chip, led->port, 1);
 		if (led->iset) {
 		if (led->iset) {
-			pm860x_set_bits(led->i2c, __led_off(led->port),
+			pm860x_set_bits(led->i2c, led->reg_control,
 					LED_CURRENT_MASK, led->iset);
 					LED_CURRENT_MASK, led->iset);
 		}
 		}
-		pm860x_set_bits(led->i2c, __blink_off(led->port),
+		pm860x_set_bits(led->i2c, led->reg_blink,
 				LED_BLINK_MASK, LED_ON_CONTINUOUS);
 				LED_BLINK_MASK, LED_ON_CONTINUOUS);
-		mask = __blink_ctl_mask(led->port);
-		pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
+		pm860x_set_bits(led->i2c, PM8606_WLED3B, led->blink_mask,
+				led->blink_mask);
 	}
 	}
-	pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
+	pm860x_set_bits(led->i2c, led->reg_control, LED_PWM_MASK,
 			led->brightness);
 			led->brightness);
 
 
 	if (led->brightness == 0) {
 	if (led->brightness == 0) {
-		pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
+		pm860x_bulk_read(led->i2c, led->reg_control, 3, buf);
 		ret = buf[0] & LED_PWM_MASK;
 		ret = buf[0] & LED_PWM_MASK;
 		ret |= buf[1] & LED_PWM_MASK;
 		ret |= buf[1] & LED_PWM_MASK;
 		ret |= buf[2] & LED_PWM_MASK;
 		ret |= buf[2] & LED_PWM_MASK;
 		if (ret == 0) {
 		if (ret == 0) {
 			/* unset current since no led is lighting */
 			/* unset current since no led is lighting */
-			pm860x_set_bits(led->i2c, __led_off(led->port),
+			pm860x_set_bits(led->i2c, led->reg_control,
 					LED_CURRENT_MASK, 0);
 					LED_CURRENT_MASK, 0);
-			mask = __blink_ctl_mask(led->port);
-			pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+			pm860x_set_bits(led->i2c, PM8606_WLED3B,
+					led->blink_mask, 0);
 			led_power_set(chip, led->port, 0);
 			led_power_set(chip, led->port, 0);
 		}
 		}
 	}
 	}
 	led->current_brightness = led->brightness;
 	led->current_brightness = led->brightness;
 	dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
 	dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
-		__led_off(led->port), led->brightness);
+		led->reg_control, led->brightness);
 	mutex_unlock(&led->lock);
 	mutex_unlock(&led->lock);
 }
 }
 
 
@@ -189,39 +124,92 @@ static void pm860x_led_set(struct led_classdev *cdev,
 	schedule_work(&data->work);
 	schedule_work(&data->work);
 }
 }
 
 
+#ifdef CONFIG_OF
+static int pm860x_led_dt_init(struct platform_device *pdev,
+			      struct pm860x_led *data)
+{
+	struct device_node *nproot = pdev->dev.parent->of_node, *np;
+	int iset = 0;
+	if (!nproot)
+		return -ENODEV;
+	nproot = of_find_node_by_name(nproot, "leds");
+	if (!nproot) {
+		dev_err(&pdev->dev, "failed to find leds node\n");
+		return -ENODEV;
+	}
+	for_each_child_of_node(nproot, np) {
+		if (!of_node_cmp(np->name, data->name)) {
+			of_property_read_u32(np, "marvell,88pm860x-iset",
+					     &iset);
+			data->iset = PM8606_LED_CURRENT(iset);
+			break;
+		}
+	}
+	return 0;
+}
+#else
+#define pm860x_led_dt_init(x, y)	(-1)
+#endif
+
 static int pm860x_led_probe(struct platform_device *pdev)
 static int pm860x_led_probe(struct platform_device *pdev)
 {
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_led_pdata *pdata;
+	struct pm860x_led_pdata *pdata = pdev->dev.platform_data;
 	struct pm860x_led *data;
 	struct pm860x_led *data;
 	struct resource *res;
 	struct resource *res;
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource!\n");
-		return -EINVAL;
-	}
-
-	pdata = pdev->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "No platform data!\n");
-		return -EINVAL;
-	}
+	int ret = 0;
 
 
 	data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL);
 	data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL);
 	if (data == NULL)
 	if (data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
-	strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for control\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_control = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for blink\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_blink = res->start;
+	memset(data->name, 0, MFD_NAME_SIZE);
+	switch (pdev->id) {
+	case 0:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-red");
+		break;
+	case 1:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-green");
+		break;
+	case 2:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-blue");
+		break;
+	case 3:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-red");
+		break;
+	case 4:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-green");
+		break;
+	case 5:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-blue");
+		break;
+	}
 	dev_set_drvdata(&pdev->dev, data);
 	dev_set_drvdata(&pdev->dev, data);
 	data->chip = chip;
 	data->chip = chip;
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
-	data->iset = pdata->iset;
-	data->port = pdata->flags;
-	if (data->port < 0) {
-		dev_err(&pdev->dev, "check device failed\n");
-		return -EINVAL;
-	}
+	data->port = pdev->id;
+	if (pm860x_led_dt_init(pdev, data))
+		if (pdata)
+			data->iset = pdata->iset;
 
 
 	data->current_brightness = 0;
 	data->current_brightness = 0;
 	data->cdev.name = data->name;
 	data->cdev.name = data->name;
@@ -236,6 +224,9 @@ static int pm860x_led_probe(struct platform_device *pdev)
 	}
 	}
 	pm860x_led_set(&data->cdev, 0);
 	pm860x_led_set(&data->cdev, 0);
 	return 0;
 	return 0;
+out:
+	devm_kfree(&pdev->dev, data);
+	return ret;
 }
 }
 
 
 static int pm860x_led_remove(struct platform_device *pdev)
 static int pm860x_led_remove(struct platform_device *pdev)

+ 567 - 238
drivers/mfd/88pm860x-core.c

@@ -11,50 +11,116 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/machine.h>
 
 
 #define INT_STATUS_NUM			3
 #define INT_STATUS_NUM			3
 
 
-static struct resource bk_resources[] __devinitdata = {
-	{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
-	{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
-	{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
-};
-
-static struct resource led_resources[] __devinitdata = {
-	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
-	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
-	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
-	{PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,},
-	{PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
-	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
-};
-
-static struct resource regulator_resources[] __devinitdata = {
-	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
-	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
-	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
-	{PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,},
-	{PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,},
-	{PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,},
-	{PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,},
-	{PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,},
-	{PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,},
-	{PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,},
-	{PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,},
-	{PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,},
-	{PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
-	{PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
-	{PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
-	{PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
-	{PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
-	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
+static struct resource bk0_resources[] __devinitdata = {
+	{2, 2, "duty cycle", IORESOURCE_REG, },
+	{3, 3, "always on",  IORESOURCE_REG, },
+	{3, 3, "current",    IORESOURCE_REG, },
+};
+static struct resource bk1_resources[] __devinitdata = {
+	{4, 4, "duty cycle", IORESOURCE_REG, },
+	{5, 5, "always on",  IORESOURCE_REG, },
+	{5, 5, "current",    IORESOURCE_REG, },
+};
+static struct resource bk2_resources[] __devinitdata = {
+	{6, 6, "duty cycle", IORESOURCE_REG, },
+	{7, 7, "always on",  IORESOURCE_REG, },
+	{5, 5, "current",    IORESOURCE_REG, },
+};
+
+static struct resource led0_resources[] __devinitdata = {
+	/* RGB1 Red LED */
+	{0xd, 0xd, "control", IORESOURCE_REG, },
+	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led1_resources[] __devinitdata = {
+	/* RGB1 Green LED */
+	{0xe, 0xe, "control", IORESOURCE_REG, },
+	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led2_resources[] __devinitdata = {
+	/* RGB1 Blue LED */
+	{0xf, 0xf, "control", IORESOURCE_REG, },
+	{0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led3_resources[] __devinitdata = {
+	/* RGB2 Red LED */
+	{0x9, 0x9, "control", IORESOURCE_REG, },
+	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+static struct resource led4_resources[] __devinitdata = {
+	/* RGB2 Green LED */
+	{0xa, 0xa, "control", IORESOURCE_REG, },
+	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+static struct resource led5_resources[] __devinitdata = {
+	/* RGB2 Blue LED */
+	{0xb, 0xb, "control", IORESOURCE_REG, },
+	{0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+
+static struct resource buck1_resources[] __devinitdata = {
+	{0x24, 0x24, "buck set", IORESOURCE_REG, },
+};
+static struct resource buck2_resources[] __devinitdata = {
+	{0x25, 0x25, "buck set", IORESOURCE_REG, },
+};
+static struct resource buck3_resources[] __devinitdata = {
+	{0x26, 0x26, "buck set", IORESOURCE_REG, },
+};
+static struct resource ldo1_resources[] __devinitdata = {
+	{0x10, 0x10, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo2_resources[] __devinitdata = {
+	{0x11, 0x11, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo3_resources[] __devinitdata = {
+	{0x12, 0x12, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo4_resources[] __devinitdata = {
+	{0x13, 0x13, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo5_resources[] __devinitdata = {
+	{0x14, 0x14, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo6_resources[] __devinitdata = {
+	{0x15, 0x15, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo7_resources[] __devinitdata = {
+	{0x16, 0x16, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo8_resources[] __devinitdata = {
+	{0x17, 0x17, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo9_resources[] __devinitdata = {
+	{0x18, 0x18, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo10_resources[] __devinitdata = {
+	{0x19, 0x19, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo12_resources[] __devinitdata = {
+	{0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo_vibrator_resources[] __devinitdata = {
+	{0x28, 0x28, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo14_resources[] __devinitdata = {
+	{0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
 };
 };
 
 
 static struct resource touch_resources[] __devinitdata = {
 static struct resource touch_resources[] __devinitdata = {
@@ -90,48 +156,145 @@ static struct resource charger_resources[] __devinitdata = {
 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
 };
 
 
-static struct resource preg_resources[] __devinitdata = {
-	{PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_IO,},
-};
-
 static struct resource rtc_resources[] __devinitdata = {
 static struct resource rtc_resources[] __devinitdata = {
 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
 };
 };
 
 
-static struct mfd_cell bk_devs[] = {
-	{"88pm860x-backlight", 0,},
-	{"88pm860x-backlight", 1,},
-	{"88pm860x-backlight", 2,},
-};
-
-static struct mfd_cell led_devs[] = {
-	{"88pm860x-led", 0,},
-	{"88pm860x-led", 1,},
-	{"88pm860x-led", 2,},
-	{"88pm860x-led", 3,},
-	{"88pm860x-led", 4,},
-	{"88pm860x-led", 5,},
-};
-
-static struct mfd_cell regulator_devs[] = {
-	{"88pm860x-regulator", 0,},
-	{"88pm860x-regulator", 1,},
-	{"88pm860x-regulator", 2,},
-	{"88pm860x-regulator", 3,},
-	{"88pm860x-regulator", 4,},
-	{"88pm860x-regulator", 5,},
-	{"88pm860x-regulator", 6,},
-	{"88pm860x-regulator", 7,},
-	{"88pm860x-regulator", 8,},
-	{"88pm860x-regulator", 9,},
-	{"88pm860x-regulator", 10,},
-	{"88pm860x-regulator", 11,},
-	{"88pm860x-regulator", 12,},
-	{"88pm860x-regulator", 13,},
-	{"88pm860x-regulator", 14,},
-	{"88pm860x-regulator", 15,},
-	{"88pm860x-regulator", 16,},
-	{"88pm860x-regulator", 17,},
+static struct mfd_cell bk_devs[] __devinitdata = {
+	{
+		.name = "88pm860x-backlight",
+		.id = 0,
+		.num_resources = ARRAY_SIZE(bk0_resources),
+		.resources = bk0_resources,
+	}, {
+		.name = "88pm860x-backlight",
+		.id = 1,
+		.num_resources = ARRAY_SIZE(bk1_resources),
+		.resources = bk1_resources,
+	}, {
+		.name = "88pm860x-backlight",
+		.id = 2,
+		.num_resources = ARRAY_SIZE(bk2_resources),
+		.resources = bk2_resources,
+	},
+};
+
+static struct mfd_cell led_devs[] __devinitdata = {
+	{
+		.name = "88pm860x-led",
+		.id = 0,
+		.num_resources = ARRAY_SIZE(led0_resources),
+		.resources = led0_resources,
+	}, {
+		.name = "88pm860x-led",
+		.id = 1,
+		.num_resources = ARRAY_SIZE(led1_resources),
+		.resources = led1_resources,
+	}, {
+		.name = "88pm860x-led",
+		.id = 2,
+		.num_resources = ARRAY_SIZE(led2_resources),
+		.resources = led2_resources,
+	}, {
+		.name = "88pm860x-led",
+		.id = 3,
+		.num_resources = ARRAY_SIZE(led3_resources),
+		.resources = led3_resources,
+	}, {
+		.name = "88pm860x-led",
+		.id = 4,
+		.num_resources = ARRAY_SIZE(led4_resources),
+		.resources = led4_resources,
+	}, {
+		.name = "88pm860x-led",
+		.id = 5,
+		.num_resources = ARRAY_SIZE(led5_resources),
+		.resources = led5_resources,
+	},
+};
+
+static struct mfd_cell reg_devs[] __devinitdata = {
+	{
+		.name = "88pm860x-regulator",
+		.id = 0,
+		.num_resources = ARRAY_SIZE(buck1_resources),
+		.resources = buck1_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 1,
+		.num_resources = ARRAY_SIZE(buck2_resources),
+		.resources = buck2_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 2,
+		.num_resources = ARRAY_SIZE(buck3_resources),
+		.resources = buck3_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 3,
+		.num_resources = ARRAY_SIZE(ldo1_resources),
+		.resources = ldo1_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 4,
+		.num_resources = ARRAY_SIZE(ldo2_resources),
+		.resources = ldo2_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 5,
+		.num_resources = ARRAY_SIZE(ldo3_resources),
+		.resources = ldo3_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 6,
+		.num_resources = ARRAY_SIZE(ldo4_resources),
+		.resources = ldo4_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 7,
+		.num_resources = ARRAY_SIZE(ldo5_resources),
+		.resources = ldo5_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 8,
+		.num_resources = ARRAY_SIZE(ldo6_resources),
+		.resources = ldo6_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 9,
+		.num_resources = ARRAY_SIZE(ldo7_resources),
+		.resources = ldo7_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 10,
+		.num_resources = ARRAY_SIZE(ldo8_resources),
+		.resources = ldo8_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 11,
+		.num_resources = ARRAY_SIZE(ldo9_resources),
+		.resources = ldo9_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 12,
+		.num_resources = ARRAY_SIZE(ldo10_resources),
+		.resources = ldo10_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 13,
+		.num_resources = ARRAY_SIZE(ldo12_resources),
+		.resources = ldo12_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 14,
+		.num_resources = ARRAY_SIZE(ldo_vibrator_resources),
+		.resources = ldo_vibrator_resources,
+	}, {
+		.name = "88pm860x-regulator",
+		.id = 15,
+		.num_resources = ARRAY_SIZE(ldo14_resources),
+		.resources = ldo14_resources,
+	},
 };
 };
 
 
 static struct mfd_cell touch_devs[] = {
 static struct mfd_cell touch_devs[] = {
@@ -360,15 +523,12 @@ static void pm860x_irq_sync_unlock(struct irq_data *data)
 
 
 static void pm860x_irq_enable(struct irq_data *data)
 static void pm860x_irq_enable(struct irq_data *data)
 {
 {
-	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
-	pm860x_irqs[data->irq - chip->irq_base].enable
-		= pm860x_irqs[data->irq - chip->irq_base].offs;
+	pm860x_irqs[data->hwirq].enable = pm860x_irqs[data->hwirq].offs;
 }
 }
 
 
 static void pm860x_irq_disable(struct irq_data *data)
 static void pm860x_irq_disable(struct irq_data *data)
 {
 {
-	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
-	pm860x_irqs[data->irq - chip->irq_base].enable = 0;
+	pm860x_irqs[data->hwirq].enable = 0;
 }
 }
 
 
 static struct irq_chip pm860x_irq_chip = {
 static struct irq_chip pm860x_irq_chip = {
@@ -379,53 +539,25 @@ static struct irq_chip pm860x_irq_chip = {
 	.irq_disable	= pm860x_irq_disable,
 	.irq_disable	= pm860x_irq_disable,
 };
 };
 
 
-static int __devinit device_gpadc_init(struct pm860x_chip *chip,
-				       struct pm860x_platform_data *pdata)
+static int pm860x_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				 irq_hw_number_t hw)
 {
 {
-	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
-				: chip->companion;
-	int data;
-	int ret;
-
-	/* initialize GPADC without activating it */
-
-	if (!pdata || !pdata->touch)
-		return -EINVAL;
-
-	/* set GPADC MISC1 register */
-	data = 0;
-	data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
-	data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
-	data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
-	data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
-	if (data) {
-		ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
-		if (ret < 0)
-			goto out;
-	}
-	/* set tsi prebias time */
-	if (pdata->touch->tsi_prebias) {
-		data = pdata->touch->tsi_prebias;
-		ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
-		if (ret < 0)
-			goto out;
-	}
-	/* set prebias & prechg time of pen detect */
-	data = 0;
-	data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
-	data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
-	if (data) {
-		ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
-		if (ret < 0)
-			goto out;
-	}
-
-	ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
-			      PM8607_GPADC_EN, PM8607_GPADC_EN);
-out:
-	return ret;
+	irq_set_chip_data(virq, d->host_data);
+	irq_set_chip_and_handler(virq, &pm860x_irq_chip, handle_edge_irq);
+	irq_set_nested_thread(virq, 1);
+#ifdef CONFIG_ARM
+	set_irq_flags(virq, IRQF_VALID);
+#else
+	irq_set_noprobe(virq);
+#endif
+	return 0;
 }
 }
 
 
+static struct irq_domain_ops pm860x_irq_domain_ops = {
+	.map	= pm860x_irq_domain_map,
+	.xlate	= irq_domain_xlate_onetwocell,
+};
+
 static int __devinit device_irq_init(struct pm860x_chip *chip,
 static int __devinit device_irq_init(struct pm860x_chip *chip,
 				     struct pm860x_platform_data *pdata)
 				     struct pm860x_platform_data *pdata)
 {
 {
@@ -433,13 +565,9 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
 				: chip->companion;
 				: chip->companion;
 	unsigned char status_buf[INT_STATUS_NUM];
 	unsigned char status_buf[INT_STATUS_NUM];
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-	int i, data, mask, ret = -EINVAL;
-	int __irq;
-
-	if (!pdata || !pdata->irq_base) {
-		dev_warn(chip->dev, "No interrupt support on IRQ base\n");
-		return -EINVAL;
-	}
+	int data, mask, ret = -EINVAL;
+	int nr_irqs, irq_base = -1;
+	struct device_node *node = i2c->dev.of_node;
 
 
 	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
 	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
 		| PM8607_B0_MISC1_INT_MASK;
 		| PM8607_B0_MISC1_INT_MASK;
@@ -479,26 +607,24 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
 		goto out;
 		goto out;
 
 
 	mutex_init(&chip->irq_lock);
 	mutex_init(&chip->irq_lock);
-	chip->irq_base = pdata->irq_base;
+
+	if (pdata && pdata->irq_base)
+		irq_base = pdata->irq_base;
+	nr_irqs = ARRAY_SIZE(pm860x_irqs);
+	chip->irq_base = irq_alloc_descs(irq_base, 0, nr_irqs, 0);
+	if (chip->irq_base < 0) {
+		dev_err(&i2c->dev, "Failed to allocate interrupts, ret:%d\n",
+			chip->irq_base);
+		ret = -EBUSY;
+		goto out;
+	}
+	irq_domain_add_legacy(node, nr_irqs, chip->irq_base, 0,
+			      &pm860x_irq_domain_ops, chip);
 	chip->core_irq = i2c->irq;
 	chip->core_irq = i2c->irq;
 	if (!chip->core_irq)
 	if (!chip->core_irq)
 		goto out;
 		goto out;
 
 
-	/* register IRQ by genirq */
-	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
-		__irq = i + chip->irq_base;
-		irq_set_chip_data(__irq, chip);
-		irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
-					 handle_edge_irq);
-		irq_set_nested_thread(__irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(__irq, IRQF_VALID);
-#else
-		irq_set_noprobe(__irq);
-#endif
-	}
-
-	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
+	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
 				   "88pm860x", chip);
 				   "88pm860x", chip);
 	if (ret) {
 	if (ret) {
 		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
 		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
@@ -615,108 +741,122 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
 static void __devinit device_bk_init(struct pm860x_chip *chip,
 static void __devinit device_bk_init(struct pm860x_chip *chip,
 				     struct pm860x_platform_data *pdata)
 				     struct pm860x_platform_data *pdata)
 {
 {
-	int ret;
-	int i, j, id;
-
-	if ((pdata == NULL) || (pdata->backlight == NULL))
-		return;
-
-	if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
-		pdata->num_backlights = ARRAY_SIZE(bk_devs);
-
-	for (i = 0; i < pdata->num_backlights; i++) {
-		bk_devs[i].platform_data = &pdata->backlight[i];
-		bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata);
-
-		for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
-			id = bk_resources[j].start;
-			if (pdata->backlight[i].flags != id)
-				continue;
-
-			bk_devs[i].num_resources = 1;
-			bk_devs[i].resources = &bk_resources[j];
-			ret = mfd_add_devices(chip->dev, 0,
-					      &bk_devs[i], 1,
-					      &bk_resources[j], 0, NULL);
-			if (ret < 0) {
-				dev_err(chip->dev, "Failed to add "
-					"backlight subdev\n");
-				return;
-			}
+	int ret, i;
+
+	if (pdata && pdata->backlight) {
+		if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
+			pdata->num_backlights = ARRAY_SIZE(bk_devs);
+		for (i = 0; i < pdata->num_backlights; i++) {
+			bk_devs[i].platform_data = &pdata->backlight[i];
+			bk_devs[i].pdata_size =
+				sizeof(struct pm860x_backlight_pdata);
 		}
 		}
 	}
 	}
+	ret = mfd_add_devices(chip->dev, 0, bk_devs,
+			      ARRAY_SIZE(bk_devs), NULL, 0, NULL);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add backlight subdev\n");
 }
 }
 
 
 static void __devinit device_led_init(struct pm860x_chip *chip,
 static void __devinit device_led_init(struct pm860x_chip *chip,
 				      struct pm860x_platform_data *pdata)
 				      struct pm860x_platform_data *pdata)
 {
 {
-	int ret;
-	int i, j, id;
-
-	if ((pdata == NULL) || (pdata->led == NULL))
-		return;
-
-	if (pdata->num_leds > ARRAY_SIZE(led_devs))
-		pdata->num_leds = ARRAY_SIZE(led_devs);
-
-	for (i = 0; i < pdata->num_leds; i++) {
-		led_devs[i].platform_data = &pdata->led[i];
-		led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
-
-		for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
-			id = led_resources[j].start;
-			if (pdata->led[i].flags != id)
-				continue;
-
-			led_devs[i].num_resources = 1;
-			led_devs[i].resources = &led_resources[j],
-			ret = mfd_add_devices(chip->dev, 0,
-					      &led_devs[i], 1,
-					      &led_resources[j], 0, NULL);
-			if (ret < 0) {
-				dev_err(chip->dev, "Failed to add "
-					"led subdev\n");
-				return;
-			}
+	int ret, i;
+
+	if (pdata && pdata->led) {
+		if (pdata->num_leds > ARRAY_SIZE(led_devs))
+			pdata->num_leds = ARRAY_SIZE(led_devs);
+		for (i = 0; i < pdata->num_leds; i++) {
+			led_devs[i].platform_data = &pdata->led[i];
+			led_devs[i].pdata_size =
+				sizeof(struct pm860x_led_pdata);
 		}
 		}
 	}
 	}
+	ret = mfd_add_devices(chip->dev, 0, led_devs,
+			      ARRAY_SIZE(led_devs), NULL, 0, NULL);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add led subdev\n");
+		return;
+	}
 }
 }
 
 
 static void __devinit device_regulator_init(struct pm860x_chip *chip,
 static void __devinit device_regulator_init(struct pm860x_chip *chip,
 					    struct pm860x_platform_data *pdata)
 					    struct pm860x_platform_data *pdata)
 {
 {
-	struct regulator_init_data *initdata;
 	int ret;
 	int ret;
-	int i, seq;
 
 
-	if ((pdata == NULL) || (pdata->regulator == NULL))
+	if (pdata == NULL)
+		return;
+	if (pdata->buck1) {
+		reg_devs[0].platform_data = pdata->buck1;
+		reg_devs[0].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->buck2) {
+		reg_devs[1].platform_data = pdata->buck2;
+		reg_devs[1].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->buck3) {
+		reg_devs[2].platform_data = pdata->buck3;
+		reg_devs[2].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo1) {
+		reg_devs[3].platform_data = pdata->ldo1;
+		reg_devs[3].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo2) {
+		reg_devs[4].platform_data = pdata->ldo2;
+		reg_devs[4].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo3) {
+		reg_devs[5].platform_data = pdata->ldo3;
+		reg_devs[5].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo4) {
+		reg_devs[6].platform_data = pdata->ldo4;
+		reg_devs[6].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo5) {
+		reg_devs[7].platform_data = pdata->ldo5;
+		reg_devs[7].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo6) {
+		reg_devs[8].platform_data = pdata->ldo6;
+		reg_devs[8].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo7) {
+		reg_devs[9].platform_data = pdata->ldo7;
+		reg_devs[9].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo8) {
+		reg_devs[10].platform_data = pdata->ldo8;
+		reg_devs[10].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo9) {
+		reg_devs[11].platform_data = pdata->ldo9;
+		reg_devs[11].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo10) {
+		reg_devs[12].platform_data = pdata->ldo10;
+		reg_devs[12].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo12) {
+		reg_devs[13].platform_data = pdata->ldo12;
+		reg_devs[13].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo_vibrator) {
+		reg_devs[14].platform_data = pdata->ldo_vibrator;
+		reg_devs[14].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo14) {
+		reg_devs[15].platform_data = pdata->ldo14;
+		reg_devs[15].pdata_size = sizeof(struct regulator_init_data);
+	}
+	ret = mfd_add_devices(chip->dev, 0, reg_devs,
+			      ARRAY_SIZE(reg_devs), NULL, 0, NULL);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add regulator subdev\n");
 		return;
 		return;
-
-	if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
-		pdata->num_regulators = ARRAY_SIZE(regulator_devs);
-
-	for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
-		initdata = &pdata->regulator[i];
-		seq = *(unsigned int *)initdata->driver_data;
-		if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
-			dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
-				seq, initdata->constraints.name);
-			goto out;
-		}
-		regulator_devs[i].platform_data = &pdata->regulator[i];
-		regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
-		regulator_devs[i].num_resources = 1;
-		regulator_devs[i].resources = &regulator_resources[seq];
-
-		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
-				      &regulator_resources[seq], 0, NULL);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add regulator subdev\n");
-			goto out;
-		}
 	}
 	}
-out:
-	return;
 }
 }
 
 
 static void __devinit device_rtc_init(struct pm860x_chip *chip,
 static void __devinit device_rtc_init(struct pm860x_chip *chip,
@@ -785,10 +925,8 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
 
 
 	power_devs[2].platform_data = &preg_init_data;
 	power_devs[2].platform_data = &preg_init_data;
 	power_devs[2].pdata_size = sizeof(struct regulator_init_data);
 	power_devs[2].pdata_size = sizeof(struct regulator_init_data);
-	power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
-	power_devs[2].resources = &preg_resources[0],
 	ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
 	ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
-			      &preg_resources[0], chip->irq_base, NULL);
+			      NULL, chip->irq_base, NULL);
 	if (ret < 0)
 	if (ret < 0)
 		dev_err(chip->dev, "Failed to add preg subdev\n");
 		dev_err(chip->dev, "Failed to add preg subdev\n");
 }
 }
@@ -868,10 +1006,6 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	ret = device_gpadc_init(chip, pdata);
-	if (ret < 0)
-		goto out;
-
 	ret = device_irq_init(chip, pdata);
 	ret = device_irq_init(chip, pdata);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
@@ -895,8 +1029,8 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
 	device_led_init(chip, pdata);
 	device_led_init(chip, pdata);
 }
 }
 
 
-int __devinit pm860x_device_init(struct pm860x_chip *chip,
-		       struct pm860x_platform_data *pdata)
+static int __devinit pm860x_device_init(struct pm860x_chip *chip,
+					struct pm860x_platform_data *pdata)
 {
 {
 	chip->core_irq = 0;
 	chip->core_irq = 0;
 
 
@@ -923,12 +1057,207 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
 	return 0;
 	return 0;
 }
 }
 
 
-void __devexit pm860x_device_exit(struct pm860x_chip *chip)
+static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
 {
 {
 	device_irq_exit(chip);
 	device_irq_exit(chip);
 	mfd_remove_devices(chip->dev);
 	mfd_remove_devices(chip->dev);
 }
 }
 
 
+static int verify_addr(struct i2c_client *i2c)
+{
+	unsigned short addr_8607[] = {0x30, 0x34};
+	unsigned short addr_8606[] = {0x10, 0x11};
+	int size, i;
+
+	if (i2c == NULL)
+		return 0;
+	size = ARRAY_SIZE(addr_8606);
+	for (i = 0; i < size; i++) {
+		if (i2c->addr == *(addr_8606 + i))
+			return CHIP_PM8606;
+	}
+	size = ARRAY_SIZE(addr_8607);
+	for (i = 0; i < size; i++) {
+		if (i2c->addr == *(addr_8607 + i))
+			return CHIP_PM8607;
+	}
+	return 0;
+}
+
+static struct regmap_config pm860x_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int __devinit pm860x_dt_init(struct device_node *np,
+				    struct device *dev,
+				    struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL))
+		pdata->irq_mode = 1;
+	ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
+				   &pdata->companion_addr);
+	if (ret) {
+		dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
+			"property\n");
+		pdata->companion_addr = 0;
+	}
+	return 0;
+}
+
+static int __devinit pm860x_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct pm860x_platform_data *pdata = client->dev.platform_data;
+	struct device_node *node = client->dev.of_node;
+	struct pm860x_chip *chip;
+	int ret;
+
+	if (node && !pdata) {
+		/* parse DT to get platform data */
+		pdata = devm_kzalloc(&client->dev,
+				     sizeof(struct pm860x_platform_data),
+				     GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+		ret = pm860x_dt_init(node, &client->dev, pdata);
+		if (ret)
+			goto err;
+	} else if (!pdata) {
+		pr_info("No platform data in %s!\n", __func__);
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
+	if (chip == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	chip->id = verify_addr(client);
+	chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		ret = PTR_ERR(chip->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+				ret);
+		kfree(chip);
+		return ret;
+	}
+	chip->client = client;
+	i2c_set_clientdata(client, chip);
+	chip->dev = &client->dev;
+	dev_set_drvdata(chip->dev, chip);
+
+	/*
+	 * Both client and companion client shares same platform driver.
+	 * Driver distinguishes them by pdata->companion_addr.
+	 * pdata->companion_addr is only assigned if companion chip exists.
+	 * At the same time, the companion_addr shouldn't equal to client
+	 * address.
+	 */
+	if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
+		chip->companion_addr = pdata->companion_addr;
+		chip->companion = i2c_new_dummy(chip->client->adapter,
+						chip->companion_addr);
+		chip->regmap_companion = regmap_init_i2c(chip->companion,
+							&pm860x_regmap_config);
+		if (IS_ERR(chip->regmap_companion)) {
+			ret = PTR_ERR(chip->regmap_companion);
+			dev_err(&chip->companion->dev,
+				"Failed to allocate register map: %d\n", ret);
+			return ret;
+		}
+		i2c_set_clientdata(chip->companion, chip);
+	}
+
+	pm860x_device_init(chip, pdata);
+	return 0;
+err:
+	if (node)
+		devm_kfree(&client->dev, pdata);
+	return ret;
+}
+
+static int __devexit pm860x_remove(struct i2c_client *client)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+	pm860x_device_exit(chip);
+	if (chip->companion) {
+		regmap_exit(chip->regmap_companion);
+		i2c_unregister_device(chip->companion);
+	}
+	regmap_exit(chip->regmap);
+	kfree(chip);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev) && chip->wakeup_flag)
+		enable_irq_wake(chip->core_irq);
+	return 0;
+}
+
+static int pm860x_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev) && chip->wakeup_flag)
+		disable_irq_wake(chip->core_irq);
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
+
+static const struct i2c_device_id pm860x_id_table[] = {
+	{ "88PM860x", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
+
+static const struct of_device_id pm860x_dt_ids[] = {
+	{ .compatible = "marvell,88pm860x", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pm860x_dt_ids);
+
+static struct i2c_driver pm860x_driver = {
+	.driver	= {
+		.name	= "88PM860x",
+		.owner	= THIS_MODULE,
+		.pm     = &pm860x_pm_ops,
+		.of_match_table	= of_match_ptr(pm860x_dt_ids),
+	},
+	.probe		= pm860x_probe,
+	.remove		= __devexit_p(pm860x_remove),
+	.id_table	= pm860x_id_table,
+};
+
+static int __init pm860x_i2c_init(void)
+{
+	int ret;
+	ret = i2c_add_driver(&pm860x_driver);
+	if (ret != 0)
+		pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
+	return ret;
+}
+subsys_initcall(pm860x_i2c_init);
+
+static void __exit pm860x_i2c_exit(void)
+{
+	i2c_del_driver(&pm860x_driver);
+}
+module_exit(pm860x_i2c_exit);
+
 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 12 - 162
drivers/mfd/88pm860x-i2c.c

@@ -10,12 +10,9 @@
  */
  */
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
-#include <linux/err.h>
 #include <linux/regmap.h>
 #include <linux/regmap.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 
 int pm860x_reg_read(struct i2c_client *i2c, int reg)
 int pm860x_reg_read(struct i2c_client *i2c, int reg)
 {
 {
@@ -91,8 +88,18 @@ static int read_device(struct i2c_client *i2c, int reg,
 	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
 	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
 	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
 	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
 	struct i2c_adapter *adap = i2c->adapter;
 	struct i2c_adapter *adap = i2c->adapter;
-	struct i2c_msg msg[2] = {{i2c->addr, 0, 1, msgbuf0},
-				 {i2c->addr, I2C_M_RD, 0, msgbuf1},
+	struct i2c_msg msg[2] = {
+					{
+						.addr = i2c->addr,
+						.flags = 0,
+						.len = 1,
+						.buf = msgbuf0
+					},
+					{	.addr = i2c->addr,
+						.flags = I2C_M_RD,
+						.len = 0,
+						.buf = msgbuf1
+					},
 				};
 				};
 	int num = 1, ret = 0;
 	int num = 1, ret = 0;
 
 
@@ -231,160 +238,3 @@ out:
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL(pm860x_page_set_bits);
 EXPORT_SYMBOL(pm860x_page_set_bits);
-
-static const struct i2c_device_id pm860x_id_table[] = {
-	{ "88PM860x", 0 },
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
-
-static int verify_addr(struct i2c_client *i2c)
-{
-	unsigned short addr_8607[] = {0x30, 0x34};
-	unsigned short addr_8606[] = {0x10, 0x11};
-	int size, i;
-
-	if (i2c == NULL)
-		return 0;
-	size = ARRAY_SIZE(addr_8606);
-	for (i = 0; i < size; i++) {
-		if (i2c->addr == *(addr_8606 + i))
-			return CHIP_PM8606;
-	}
-	size = ARRAY_SIZE(addr_8607);
-	for (i = 0; i < size; i++) {
-		if (i2c->addr == *(addr_8607 + i))
-			return CHIP_PM8607;
-	}
-	return 0;
-}
-
-static struct regmap_config pm860x_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
-static int __devinit pm860x_probe(struct i2c_client *client,
-				  const struct i2c_device_id *id)
-{
-	struct pm860x_platform_data *pdata = client->dev.platform_data;
-	struct pm860x_chip *chip;
-	int ret;
-
-	if (!pdata) {
-		pr_info("No platform data in %s!\n", __func__);
-		return -EINVAL;
-	}
-
-	chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	chip->id = verify_addr(client);
-	chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
-	if (IS_ERR(chip->regmap)) {
-		ret = PTR_ERR(chip->regmap);
-		dev_err(&client->dev, "Failed to allocate register map: %d\n",
-				ret);
-		kfree(chip);
-		return ret;
-	}
-	chip->client = client;
-	i2c_set_clientdata(client, chip);
-	chip->dev = &client->dev;
-	dev_set_drvdata(chip->dev, chip);
-
-	/*
-	 * Both client and companion client shares same platform driver.
-	 * Driver distinguishes them by pdata->companion_addr.
-	 * pdata->companion_addr is only assigned if companion chip exists.
-	 * At the same time, the companion_addr shouldn't equal to client
-	 * address.
-	 */
-	if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
-		chip->companion_addr = pdata->companion_addr;
-		chip->companion = i2c_new_dummy(chip->client->adapter,
-						chip->companion_addr);
-		chip->regmap_companion = regmap_init_i2c(chip->companion,
-							&pm860x_regmap_config);
-		if (IS_ERR(chip->regmap_companion)) {
-			ret = PTR_ERR(chip->regmap_companion);
-			dev_err(&chip->companion->dev,
-				"Failed to allocate register map: %d\n", ret);
-			return ret;
-		}
-		i2c_set_clientdata(chip->companion, chip);
-	}
-
-	pm860x_device_init(chip, pdata);
-	return 0;
-}
-
-static int __devexit pm860x_remove(struct i2c_client *client)
-{
-	struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-	pm860x_device_exit(chip);
-	if (chip->companion) {
-		regmap_exit(chip->regmap_companion);
-		i2c_unregister_device(chip->companion);
-	}
-	regmap_exit(chip->regmap);
-	kfree(chip);
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int pm860x_suspend(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-	if (device_may_wakeup(dev) && chip->wakeup_flag)
-		enable_irq_wake(chip->core_irq);
-	return 0;
-}
-
-static int pm860x_resume(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-	if (device_may_wakeup(dev) && chip->wakeup_flag)
-		disable_irq_wake(chip->core_irq);
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
-
-static struct i2c_driver pm860x_driver = {
-	.driver	= {
-		.name	= "88PM860x",
-		.owner	= THIS_MODULE,
-		.pm     = &pm860x_pm_ops,
-	},
-	.probe		= pm860x_probe,
-	.remove		= __devexit_p(pm860x_remove),
-	.id_table	= pm860x_id_table,
-};
-
-static int __init pm860x_i2c_init(void)
-{
-	int ret;
-	ret = i2c_add_driver(&pm860x_driver);
-	if (ret != 0)
-		pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
-	return ret;
-}
-subsys_initcall(pm860x_i2c_init);
-
-static void __exit pm860x_i2c_exit(void)
-{
-	i2c_del_driver(&pm860x_driver);
-}
-module_exit(pm860x_i2c_exit);
-
-MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_LICENSE("GPL");

+ 58 - 17
drivers/mfd/Kconfig

@@ -298,16 +298,6 @@ config MFD_TWL4030_AUDIO
 	select MFD_CORE
 	select MFD_CORE
 	default n
 	default n
 
 
-config TWL6030_PWM
-	tristate "TWL6030 PWM (Pulse Width Modulator) Support"
-	depends on TWL4030_CORE
-	select HAVE_PWM
-	depends on !PWM
-	default n
-	help
-	  Say yes here if you want support for TWL6030 PWM.
-	  This is used to control charging LED brightness.
-
 config TWL6040_CORE
 config TWL6040_CORE
 	bool "Support for TWL6040 audio codec"
 	bool "Support for TWL6040 audio codec"
 	depends on I2C=y && GENERIC_HARDIRQS
 	depends on I2C=y && GENERIC_HARDIRQS
@@ -385,6 +375,18 @@ config MFD_T7L66XB
 	help
 	help
 	  Support for Toshiba Mobile IO Controller T7L66XB
 	  Support for Toshiba Mobile IO Controller T7L66XB
 
 
+config MFD_SMSC
+       bool "Support for the SMSC ECE1099 series chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+        If you say yes here you get support for the
+        ece1099 chips from SMSC.
+
+        To compile this driver as a module, choose M here: the
+        module will be called smsc.
+
 config MFD_TC6387XB
 config MFD_TC6387XB
 	bool "Support Toshiba TC6387XB"
 	bool "Support Toshiba TC6387XB"
 	depends on ARM && HAVE_CLK
 	depends on ARM && HAVE_CLK
@@ -441,6 +443,23 @@ config MFD_DA9052_I2C
 	  for accessing the device, additional drivers must be enabled in
 	  for accessing the device, additional drivers must be enabled in
 	  order to use the functionality of the device.
 	  order to use the functionality of the device.
 
 
+config MFD_DA9055
+	bool "Dialog Semiconductor DA9055 PMIC Support"
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	select PMIC_DA9055
+	select MFD_CORE
+	depends on I2C=y
+	help
+	  Say yes here for support of Dialog Semiconductor DA9055. This is
+	  a Power Management IC. This driver provides common support for
+	  accessing the device as well as the I2C interface to the chip itself.
+	  Additional drivers must be enabled in order to use the functionality
+	  of the device.
+
+	  This driver can be built as a module. If built as a module it will be
+	  called "da9055"
+
 config PMIC_ADP5520
 config PMIC_ADP5520
 	bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
 	bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
 	depends on I2C=y
 	depends on I2C=y
@@ -451,6 +470,16 @@ config PMIC_ADP5520
 	  individual components like LCD backlight, LEDs, GPIOs and Kepad
 	  individual components like LCD backlight, LEDs, GPIOs and Kepad
 	  under the corresponding menus.
 	  under the corresponding menus.
 
 
+config MFD_LP8788
+	bool "Texas Instruments LP8788 Power Management Unit Driver"
+	depends on I2C=y
+	select MFD_CORE
+	select REGMAP_I2C
+	select IRQ_DOMAIN
+	help
+	  TI LP8788 PMU supports regulators, battery charger, RTC,
+	  ADC, backlight driver and current sinks.
+
 config MFD_MAX77686
 config MFD_MAX77686
 	bool "Maxim Semiconductor MAX77686 PMIC Support"
 	bool "Maxim Semiconductor MAX77686 PMIC Support"
 	depends on I2C=y && GENERIC_HARDIRQS
 	depends on I2C=y && GENERIC_HARDIRQS
@@ -477,6 +506,18 @@ config MFD_MAX77693
 	  additional drivers must be enabled in order to use the functionality
 	  additional drivers must be enabled in order to use the functionality
 	  of the device.
 	  of the device.
 
 
+config MFD_MAX8907
+	tristate "Maxim Semiconductor MAX8907 PMIC Support"
+	select MFD_CORE
+	depends on I2C=y && GENERIC_HARDIRQS
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  Say yes here to support for Maxim Semiconductor MAX8907. This is
+	  a Power Management IC. This driver provides common support for
+	  accessing the device; additional drivers must be enabled in order
+	  to use the functionality of the device.
+
 config MFD_MAX8925
 config MFD_MAX8925
 	bool "Maxim Semiconductor MAX8925 PMIC Support"
 	bool "Maxim Semiconductor MAX8925 PMIC Support"
 	depends on I2C=y && GENERIC_HARDIRQS
 	depends on I2C=y && GENERIC_HARDIRQS
@@ -896,7 +937,7 @@ config MFD_WL1273_CORE
 	  audio codec.
 	  audio codec.
 
 
 config MFD_OMAP_USB_HOST
 config MFD_OMAP_USB_HOST
-	bool "Support OMAP USBHS core driver"
+	bool "Support OMAP USBHS core and TLL driver"
 	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
 	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
 	default y
 	default y
 	help
 	help
@@ -985,13 +1026,13 @@ config MFD_STA2X11
 	depends on STA2X11
 	depends on STA2X11
 	select MFD_CORE
 	select MFD_CORE
 
 
-config MFD_ANATOP
-	bool "Support for Freescale i.MX on-chip ANATOP controller"
-	depends on SOC_IMX6Q
+config MFD_SYSCON
+	bool "System Controller Register R/W Based on Regmap"
+	depends on OF
+	select REGMAP_MMIO
 	help
 	help
-	  Select this option to enable Freescale i.MX on-chip ANATOP
-	  MFD controller. This controller embeds regulator and
-	  thermal devices for Freescale i.MX platforms.
+	  Select this option to enable accessing system control registers
+	  via regmap.
 
 
 config MFD_PALMAS
 config MFD_PALMAS
 	bool "Support for the TI Palmas series chips"
 	bool "Support for the TI Palmas series chips"

+ 9 - 3
drivers/mfd/Makefile

@@ -63,7 +63,6 @@ obj-$(CONFIG_TWL4030_CORE)	+= twl-core.o twl4030-irq.o twl6030-irq.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_MFD_TWL4030_AUDIO)	+= twl4030-audio.o
 obj-$(CONFIG_MFD_TWL4030_AUDIO)	+= twl4030-audio.o
-obj-$(CONFIG_TWL6030_PWM)	+= twl6030-pwm.o
 obj-$(CONFIG_TWL6040_CORE)	+= twl6040-core.o twl6040-irq.o
 obj-$(CONFIG_TWL6040_CORE)	+= twl6040-core.o twl6040-irq.o
 
 
 obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx-core.o
 obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx-core.o
@@ -77,6 +76,7 @@ obj-$(CONFIG_EZX_PCAP)		+= ezx-pcap.o
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
+obj-$(CONFIG_MFD_SMSC)        += smsc-ece1099.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
 ifeq ($(CONFIG_SA1100_ASSABET),y)
@@ -90,8 +90,14 @@ obj-$(CONFIG_PMIC_DA9052)	+= da9052-core.o
 obj-$(CONFIG_MFD_DA9052_SPI)	+= da9052-spi.o
 obj-$(CONFIG_MFD_DA9052_SPI)	+= da9052-spi.o
 obj-$(CONFIG_MFD_DA9052_I2C)	+= da9052-i2c.o
 obj-$(CONFIG_MFD_DA9052_I2C)	+= da9052-i2c.o
 
 
+obj-$(CONFIG_MFD_LP8788)	+= lp8788.o lp8788-irq.o
+
+da9055-objs			:= da9055-core.o da9055-i2c.o
+obj-$(CONFIG_MFD_DA9055)	+= da9055.o
+
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
 obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
 obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
+obj-$(CONFIG_MFD_MAX8907)	+= max8907.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
 obj-$(CONFIG_MFD_MAX8997)	+= max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8997)	+= max8997.o max8997-irq.o
@@ -120,7 +126,7 @@ obj-$(CONFIG_MFD_TPS6586X)	+= tps6586x.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
-obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
+obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
@@ -130,5 +136,5 @@ obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
 obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
 obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
-obj-$(CONFIG_MFD_ANATOP)	+= anatop-mfd.o
+obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o

+ 1 - 0
drivers/mfd/ab3100-core.c

@@ -21,6 +21,7 @@
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500.h>
 
 
 /* These are the only registers inside AB3100 used in this main file */
 /* These are the only registers inside AB3100 used in this main file */

+ 19 - 18
drivers/mfd/ab8500-core.c

@@ -472,6 +472,22 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+/**
+ * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
+ *
+ * @ab8500: ab8500_irq controller to operate on.
+ * @irq: index of the interrupt requested in the chip IRQs
+ *
+ * Useful for drivers to request their own IRQs.
+ */
+static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
+{
+	if (!ab8500)
+		return -EINVAL;
+
+	return irq_create_mapping(ab8500->domain, irq);
+}
+
 static irqreturn_t ab8500_irq(int irq, void *dev)
 static irqreturn_t ab8500_irq(int irq, void *dev)
 {
 {
 	struct ab8500 *ab8500 = dev;
 	struct ab8500 *ab8500 = dev;
@@ -501,8 +517,9 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
 		do {
 		do {
 			int bit = __ffs(value);
 			int bit = __ffs(value);
 			int line = i * 8 + bit;
 			int line = i * 8 + bit;
+			int virq = ab8500_irq_get_virq(ab8500, line);
 
 
-			handle_nested_irq(ab8500->irq_base + line);
+			handle_nested_irq(virq);
 			value &= ~(1 << bit);
 			value &= ~(1 << bit);
 
 
 		} while (value);
 		} while (value);
@@ -511,23 +528,6 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-/**
- * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
- *
- * @ab8500: ab8500_irq controller to operate on.
- * @irq: index of the interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
-{
-	if (!ab8500)
-		return -EINVAL;
-
-	return irq_create_mapping(ab8500->domain, irq);
-}
-EXPORT_SYMBOL_GPL(ab8500_irq_get_virq);
-
 static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
 static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hwirq)
 				irq_hw_number_t hwirq)
 {
 {
@@ -1076,6 +1076,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
 	},
 	},
 	{
 	{
 		.name = "ab8500-codec",
 		.name = "ab8500-codec",
+		.of_compatible = "stericsson,ab8500-codec",
 	},
 	},
 };
 };
 
 

+ 0 - 124
drivers/mfd/anatop-mfd.c

@@ -1,124 +0,0 @@
-/*
- * Anatop MFD driver
- *
- * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
- * Copyright (C) 2012 Linaro
- *
- *  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.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *  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.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/mfd/anatop.h>
-
-u32 anatop_read_reg(struct anatop *adata, u32 addr)
-{
-	return readl(adata->ioreg + addr);
-}
-EXPORT_SYMBOL_GPL(anatop_read_reg);
-
-void anatop_write_reg(struct anatop *adata, u32 addr, u32 data, u32 mask)
-{
-	u32 val;
-
-	data &= mask;
-
-	spin_lock(&adata->reglock);
-	val = readl(adata->ioreg + addr);
-	val &= ~mask;
-	val |= data;
-	writel(val, adata->ioreg + addr);
-	spin_unlock(&adata->reglock);
-}
-EXPORT_SYMBOL_GPL(anatop_write_reg);
-
-static const struct of_device_id of_anatop_match[] = {
-	{ .compatible = "fsl,imx6q-anatop", },
-	{ },
-};
-
-static int __devinit of_anatop_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
-	void *ioreg;
-	struct anatop *drvdata;
-
-	ioreg = of_iomap(np, 0);
-	if (!ioreg)
-		return -EADDRNOTAVAIL;
-	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata)
-		return -ENOMEM;
-	drvdata->ioreg = ioreg;
-	spin_lock_init(&drvdata->reglock);
-	platform_set_drvdata(pdev, drvdata);
-	of_platform_populate(np, NULL, NULL, dev);
-
-	return 0;
-}
-
-static int __devexit of_anatop_remove(struct platform_device *pdev)
-{
-	struct anatop *drvdata;
-	drvdata = platform_get_drvdata(pdev);
-	iounmap(drvdata->ioreg);
-
-	return 0;
-}
-
-static struct platform_driver anatop_of_driver = {
-	.driver = {
-		.name = "anatop-mfd",
-		.owner = THIS_MODULE,
-		.of_match_table = of_anatop_match,
-	},
-	.probe		= of_anatop_probe,
-	.remove		= of_anatop_remove,
-};
-
-static int __init anatop_init(void)
-{
-	return platform_driver_register(&anatop_of_driver);
-}
-postcore_initcall(anatop_init);
-
-static void __exit anatop_exit(void)
-{
-	platform_driver_unregister(&anatop_of_driver);
-}
-module_exit(anatop_exit);
-
-MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
-MODULE_DESCRIPTION("ANATOP MFD driver");
-MODULE_LICENSE("GPL v2");

+ 45 - 11
drivers/mfd/arizona-irq.c

@@ -94,7 +94,8 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
 static irqreturn_t arizona_irq_thread(int irq, void *data)
 static irqreturn_t arizona_irq_thread(int irq, void *data)
 {
 {
 	struct arizona *arizona = data;
 	struct arizona *arizona = data;
-	int i, ret;
+	unsigned int val;
+	int ret;
 
 
 	ret = pm_runtime_get_sync(arizona->dev);
 	ret = pm_runtime_get_sync(arizona->dev);
 	if (ret < 0) {
 	if (ret < 0) {
@@ -102,9 +103,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
 		return IRQ_NONE;
 		return IRQ_NONE;
 	}
 	}
 
 
-	/* Check both domains */
-	for (i = 0; i < 2; i++)
-		handle_nested_irq(irq_find_mapping(arizona->virq, i));
+	/* Always handle the AoD domain */
+	handle_nested_irq(irq_find_mapping(arizona->virq, 0));
+
+	/*
+	 * Check if one of the main interrupts is asserted and only
+	 * check that domain if it is.
+	 */
+	ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS, &val);
+	if (ret == 0 && val & ARIZONA_IRQ1_STS) {
+		handle_nested_irq(irq_find_mapping(arizona->virq, 1));
+	} else if (ret != 0) {
+		dev_err(arizona->dev, "Failed to read main IRQ status: %d\n",
+			ret);
+	}
 
 
 	pm_runtime_mark_last_busy(arizona->dev);
 	pm_runtime_mark_last_busy(arizona->dev);
 	pm_runtime_put_autosuspend(arizona->dev);
 	pm_runtime_put_autosuspend(arizona->dev);
@@ -156,18 +168,36 @@ int arizona_irq_init(struct arizona *arizona)
 	int flags = IRQF_ONESHOT;
 	int flags = IRQF_ONESHOT;
 	int ret, i;
 	int ret, i;
 	const struct regmap_irq_chip *aod, *irq;
 	const struct regmap_irq_chip *aod, *irq;
+	bool ctrlif_error = true;
 
 
 	switch (arizona->type) {
 	switch (arizona->type) {
 #ifdef CONFIG_MFD_WM5102
 #ifdef CONFIG_MFD_WM5102
 	case WM5102:
 	case WM5102:
 		aod = &wm5102_aod;
 		aod = &wm5102_aod;
 		irq = &wm5102_irq;
 		irq = &wm5102_irq;
+
+		switch (arizona->rev) {
+		case 0:
+			ctrlif_error = false;
+			break;
+		default:
+			break;
+		}
 		break;
 		break;
 #endif
 #endif
 #ifdef CONFIG_MFD_WM5110
 #ifdef CONFIG_MFD_WM5110
 	case WM5110:
 	case WM5110:
 		aod = &wm5110_aod;
 		aod = &wm5110_aod;
 		irq = &wm5110_irq;
 		irq = &wm5110_irq;
+
+		switch (arizona->rev) {
+		case 0:
+		case 1:
+			ctrlif_error = false;
+			break;
+		default:
+			break;
+		}
 		break;
 		break;
 #endif
 #endif
 	default:
 	default:
@@ -226,13 +256,17 @@ int arizona_irq_init(struct arizona *arizona)
 	}
 	}
 
 
 	/* Handle control interface errors in the core */
 	/* Handle control interface errors in the core */
-	i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
-	ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT,
-				   "Control interface error", arizona);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
-			arizona->irq, ret);
-		goto err_ctrlif;
+	if (ctrlif_error) {
+		i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
+		ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
+					   IRQF_ONESHOT,
+					   "Control interface error", arizona);
+		if (ret != 0) {
+			dev_err(arizona->dev,
+				"Failed to request CTRLIF_ERR %d: %d\n",
+				arizona->irq, ret);
+			goto err_ctrlif;
+		}
 	}
 	}
 
 
 	ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
 	ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,

+ 423 - 0
drivers/mfd/da9055-core.c

@@ -0,0 +1,423 @@
+/*
+ * Device access for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  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.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/pdata.h>
+#include <linux/mfd/da9055/reg.h>
+
+#define DA9055_IRQ_NONKEY_MASK		0x01
+#define DA9055_IRQ_ALM_MASK		0x02
+#define DA9055_IRQ_TICK_MASK		0x04
+#define DA9055_IRQ_ADC_MASK		0x08
+#define DA9055_IRQ_BUCK_ILIM_MASK	0x08
+
+static bool da9055_register_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA9055_REG_STATUS_A:
+	case DA9055_REG_STATUS_B:
+	case DA9055_REG_EVENT_A:
+	case DA9055_REG_EVENT_B:
+	case DA9055_REG_EVENT_C:
+	case DA9055_REG_IRQ_MASK_A:
+	case DA9055_REG_IRQ_MASK_B:
+	case DA9055_REG_IRQ_MASK_C:
+
+	case DA9055_REG_CONTROL_A:
+	case DA9055_REG_CONTROL_B:
+	case DA9055_REG_CONTROL_C:
+	case DA9055_REG_CONTROL_D:
+	case DA9055_REG_CONTROL_E:
+
+	case DA9055_REG_ADC_MAN:
+	case DA9055_REG_ADC_CONT:
+	case DA9055_REG_VSYS_MON:
+	case DA9055_REG_ADC_RES_L:
+	case DA9055_REG_ADC_RES_H:
+	case DA9055_REG_VSYS_RES:
+	case DA9055_REG_ADCIN1_RES:
+	case DA9055_REG_ADCIN2_RES:
+	case DA9055_REG_ADCIN3_RES:
+
+	case DA9055_REG_COUNT_S:
+	case DA9055_REG_COUNT_MI:
+	case DA9055_REG_COUNT_H:
+	case DA9055_REG_COUNT_D:
+	case DA9055_REG_COUNT_MO:
+	case DA9055_REG_COUNT_Y:
+	case DA9055_REG_ALARM_H:
+	case DA9055_REG_ALARM_D:
+	case DA9055_REG_ALARM_MI:
+	case DA9055_REG_ALARM_MO:
+	case DA9055_REG_ALARM_Y:
+
+	case DA9055_REG_GPIO0_1:
+	case DA9055_REG_GPIO2:
+	case DA9055_REG_GPIO_MODE0_2:
+
+	case DA9055_REG_BCORE_CONT:
+	case DA9055_REG_BMEM_CONT:
+	case DA9055_REG_LDO1_CONT:
+	case DA9055_REG_LDO2_CONT:
+	case DA9055_REG_LDO3_CONT:
+	case DA9055_REG_LDO4_CONT:
+	case DA9055_REG_LDO5_CONT:
+	case DA9055_REG_LDO6_CONT:
+	case DA9055_REG_BUCK_LIM:
+	case DA9055_REG_BCORE_MODE:
+	case DA9055_REG_VBCORE_A:
+	case DA9055_REG_VBMEM_A:
+	case DA9055_REG_VLDO1_A:
+	case DA9055_REG_VLDO2_A:
+	case DA9055_REG_VLDO3_A:
+	case DA9055_REG_VLDO4_A:
+	case DA9055_REG_VLDO5_A:
+	case DA9055_REG_VLDO6_A:
+	case DA9055_REG_VBCORE_B:
+	case DA9055_REG_VBMEM_B:
+	case DA9055_REG_VLDO1_B:
+	case DA9055_REG_VLDO2_B:
+	case DA9055_REG_VLDO3_B:
+	case DA9055_REG_VLDO4_B:
+	case DA9055_REG_VLDO5_B:
+	case DA9055_REG_VLDO6_B:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool da9055_register_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA9055_REG_STATUS_A:
+	case DA9055_REG_STATUS_B:
+	case DA9055_REG_EVENT_A:
+	case DA9055_REG_EVENT_B:
+	case DA9055_REG_EVENT_C:
+	case DA9055_REG_IRQ_MASK_A:
+	case DA9055_REG_IRQ_MASK_B:
+	case DA9055_REG_IRQ_MASK_C:
+
+	case DA9055_REG_CONTROL_A:
+	case DA9055_REG_CONTROL_B:
+	case DA9055_REG_CONTROL_C:
+	case DA9055_REG_CONTROL_D:
+	case DA9055_REG_CONTROL_E:
+
+	case DA9055_REG_ADC_MAN:
+	case DA9055_REG_ADC_CONT:
+	case DA9055_REG_VSYS_MON:
+	case DA9055_REG_ADC_RES_L:
+	case DA9055_REG_ADC_RES_H:
+	case DA9055_REG_VSYS_RES:
+	case DA9055_REG_ADCIN1_RES:
+	case DA9055_REG_ADCIN2_RES:
+	case DA9055_REG_ADCIN3_RES:
+
+	case DA9055_REG_COUNT_S:
+	case DA9055_REG_COUNT_MI:
+	case DA9055_REG_COUNT_H:
+	case DA9055_REG_COUNT_D:
+	case DA9055_REG_COUNT_MO:
+	case DA9055_REG_COUNT_Y:
+	case DA9055_REG_ALARM_H:
+	case DA9055_REG_ALARM_D:
+	case DA9055_REG_ALARM_MI:
+	case DA9055_REG_ALARM_MO:
+	case DA9055_REG_ALARM_Y:
+
+	case DA9055_REG_GPIO0_1:
+	case DA9055_REG_GPIO2:
+	case DA9055_REG_GPIO_MODE0_2:
+
+	case DA9055_REG_BCORE_CONT:
+	case DA9055_REG_BMEM_CONT:
+	case DA9055_REG_LDO1_CONT:
+	case DA9055_REG_LDO2_CONT:
+	case DA9055_REG_LDO3_CONT:
+	case DA9055_REG_LDO4_CONT:
+	case DA9055_REG_LDO5_CONT:
+	case DA9055_REG_LDO6_CONT:
+	case DA9055_REG_BUCK_LIM:
+	case DA9055_REG_BCORE_MODE:
+	case DA9055_REG_VBCORE_A:
+	case DA9055_REG_VBMEM_A:
+	case DA9055_REG_VLDO1_A:
+	case DA9055_REG_VLDO2_A:
+	case DA9055_REG_VLDO3_A:
+	case DA9055_REG_VLDO4_A:
+	case DA9055_REG_VLDO5_A:
+	case DA9055_REG_VLDO6_A:
+	case DA9055_REG_VBCORE_B:
+	case DA9055_REG_VBMEM_B:
+	case DA9055_REG_VLDO1_B:
+	case DA9055_REG_VLDO2_B:
+	case DA9055_REG_VLDO3_B:
+	case DA9055_REG_VLDO4_B:
+	case DA9055_REG_VLDO5_B:
+	case DA9055_REG_VLDO6_B:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool da9055_register_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA9055_REG_STATUS_A:
+	case DA9055_REG_STATUS_B:
+	case DA9055_REG_EVENT_A:
+	case DA9055_REG_EVENT_B:
+	case DA9055_REG_EVENT_C:
+
+	case DA9055_REG_CONTROL_A:
+	case DA9055_REG_CONTROL_E:
+
+	case DA9055_REG_ADC_MAN:
+	case DA9055_REG_ADC_RES_L:
+	case DA9055_REG_ADC_RES_H:
+	case DA9055_REG_VSYS_RES:
+	case DA9055_REG_ADCIN1_RES:
+	case DA9055_REG_ADCIN2_RES:
+	case DA9055_REG_ADCIN3_RES:
+
+	case DA9055_REG_COUNT_S:
+	case DA9055_REG_COUNT_MI:
+	case DA9055_REG_COUNT_H:
+	case DA9055_REG_COUNT_D:
+	case DA9055_REG_COUNT_MO:
+	case DA9055_REG_COUNT_Y:
+	case DA9055_REG_ALARM_MI:
+
+	case DA9055_REG_BCORE_CONT:
+	case DA9055_REG_BMEM_CONT:
+	case DA9055_REG_LDO1_CONT:
+	case DA9055_REG_LDO2_CONT:
+	case DA9055_REG_LDO3_CONT:
+	case DA9055_REG_LDO4_CONT:
+	case DA9055_REG_LDO5_CONT:
+	case DA9055_REG_LDO6_CONT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static struct regmap_irq da9055_irqs[] = {
+	[DA9055_IRQ_NONKEY] = {
+		.reg_offset = 0,
+		.mask = DA9055_IRQ_NONKEY_MASK,
+	},
+	[DA9055_IRQ_ALARM] = {
+		.reg_offset = 0,
+		.mask = DA9055_IRQ_ALM_MASK,
+	},
+	[DA9055_IRQ_TICK] = {
+		.reg_offset = 0,
+		.mask = DA9055_IRQ_TICK_MASK,
+	},
+	[DA9055_IRQ_HWMON] = {
+		.reg_offset = 0,
+		.mask = DA9055_IRQ_ADC_MASK,
+	},
+	[DA9055_IRQ_REGULATOR] = {
+		.reg_offset = 1,
+		.mask = DA9055_IRQ_BUCK_ILIM_MASK,
+	},
+};
+
+struct regmap_config da9055_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.cache_type = REGCACHE_RBTREE,
+
+	.max_register = DA9055_MAX_REGISTER_CNT,
+	.readable_reg = da9055_register_readable,
+	.writeable_reg = da9055_register_writeable,
+	.volatile_reg = da9055_register_volatile,
+};
+EXPORT_SYMBOL_GPL(da9055_regmap_config);
+
+static struct resource da9055_onkey_resource = {
+	.name = "ONKEY",
+	.start = DA9055_IRQ_NONKEY,
+	.end   = DA9055_IRQ_NONKEY,
+	.flags = IORESOURCE_IRQ,
+};
+
+static struct resource da9055_rtc_resource[] = {
+	{
+		.name = "ALM",
+		.start = DA9055_IRQ_ALARM,
+		.end   = DA9055_IRQ_ALARM,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "TICK",
+		.start = DA9055_IRQ_TICK,
+		.end   = DA9055_IRQ_TICK,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource da9055_hwmon_resource = {
+	.name = "HWMON",
+	.start = DA9055_IRQ_HWMON,
+	.end   = DA9055_IRQ_HWMON,
+	.flags = IORESOURCE_IRQ,
+};
+
+static struct resource da9055_ld05_6_resource = {
+	.name = "REGULATOR",
+	.start = DA9055_IRQ_REGULATOR,
+	.end   = DA9055_IRQ_REGULATOR,
+	.flags = IORESOURCE_IRQ,
+};
+
+static struct mfd_cell da9055_devs[] = {
+	{
+		.of_compatible = "dialog,da9055-gpio",
+		.name = "da9055-gpio",
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 1,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 2,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 3,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 4,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 5,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 6,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.id = 7,
+		.resources = &da9055_ld05_6_resource,
+		.num_resources = 1,
+	},
+	{
+		.of_compatible = "dialog,da9055-regulator",
+		.name = "da9055-regulator",
+		.resources = &da9055_ld05_6_resource,
+		.num_resources = 1,
+		.id = 8,
+	},
+	{
+		.of_compatible = "dialog,da9055-onkey",
+		.name = "da9055-onkey",
+		.resources = &da9055_onkey_resource,
+		.num_resources = 1,
+	},
+	{
+		.of_compatible = "dialog,da9055-rtc",
+		.name = "da9055-rtc",
+		.resources = da9055_rtc_resource,
+		.num_resources = ARRAY_SIZE(da9055_rtc_resource),
+	},
+	{
+		.of_compatible = "dialog,da9055-hwmon",
+		.name = "da9055-hwmon",
+		.resources = &da9055_hwmon_resource,
+		.num_resources = 1,
+	},
+	{
+		.of_compatible = "dialog,da9055-watchdog",
+		.name = "da9055-watchdog",
+	},
+};
+
+static struct regmap_irq_chip da9055_regmap_irq_chip = {
+	.name = "da9055_irq",
+	.status_base = DA9055_REG_EVENT_A,
+	.mask_base = DA9055_REG_IRQ_MASK_A,
+	.ack_base = DA9055_REG_EVENT_A,
+	.num_regs = 3,
+	.irqs = da9055_irqs,
+	.num_irqs = ARRAY_SIZE(da9055_irqs),
+};
+
+int __devinit da9055_device_init(struct da9055 *da9055)
+{
+	struct da9055_pdata *pdata = da9055->dev->platform_data;
+	int ret;
+
+	if (pdata && pdata->init != NULL)
+		pdata->init(da9055);
+
+	if (!pdata || !pdata->irq_base)
+		da9055->irq_base = -1;
+	else
+		da9055->irq_base = pdata->irq_base;
+
+	ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
+				  IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				  da9055->irq_base, &da9055_regmap_irq_chip,
+				  &da9055->irq_data);
+	if (ret < 0)
+		return ret;
+
+	da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
+
+	ret = mfd_add_devices(da9055->dev, -1,
+			      da9055_devs, ARRAY_SIZE(da9055_devs),
+			      NULL, da9055->irq_base, NULL);
+	if (ret)
+		goto err;
+
+	return 0;
+
+err:
+	mfd_remove_devices(da9055->dev);
+	return ret;
+}
+
+void __devexit da9055_device_exit(struct da9055 *da9055)
+{
+	regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
+	mfd_remove_devices(da9055->dev);
+}
+
+MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");

+ 93 - 0
drivers/mfd/da9055-i2c.c

@@ -0,0 +1,93 @@
+ /* I2C access for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+
+#include <linux/mfd/da9055/core.h>
+
+static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct da9055 *da9055;
+	int ret;
+
+	da9055 = devm_kzalloc(&i2c->dev, sizeof(struct da9055), GFP_KERNEL);
+	if (!da9055)
+		return -ENOMEM;
+
+	da9055->regmap = devm_regmap_init_i2c(i2c, &da9055_regmap_config);
+	if (IS_ERR(da9055->regmap)) {
+		ret = PTR_ERR(da9055->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	da9055->dev = &i2c->dev;
+	da9055->chip_irq = i2c->irq;
+
+	i2c_set_clientdata(i2c, da9055);
+
+	return da9055_device_init(da9055);
+}
+
+static int __devexit da9055_i2c_remove(struct i2c_client *i2c)
+{
+	struct da9055 *da9055 = i2c_get_clientdata(i2c);
+
+	da9055_device_exit(da9055);
+
+	return 0;
+}
+
+static struct i2c_device_id da9055_i2c_id[] = {
+	{"da9055-pmic", 0},
+	{ }
+};
+
+static struct i2c_driver da9055_i2c_driver = {
+	.probe = da9055_i2c_probe,
+	.remove = __devexit_p(da9055_i2c_remove),
+	.id_table = da9055_i2c_id,
+	.driver = {
+		.name = "da9055",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init da9055_i2c_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&da9055_i2c_driver);
+	if (ret != 0) {
+		pr_err("DA9055 I2C registration failed %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+subsys_initcall(da9055_i2c_init);
+
+static void __exit da9055_i2c_exit(void)
+{
+	i2c_del_driver(&da9055_i2c_driver);
+}
+module_exit(da9055_i2c_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("I2C driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");

+ 35 - 12
drivers/mfd/db8500-prcmu.c

@@ -270,6 +270,8 @@ static struct {
 	struct prcmu_fw_version version;
 	struct prcmu_fw_version version;
 } fw_info;
 } fw_info;
 
 
+static struct irq_domain *db8500_irq_domain;
+
 /*
 /*
  * This vector maps irq numbers to the bits in the bit field used in
  * This vector maps irq numbers to the bits in the bit field used in
  * communication with the PRCMU firmware.
  * communication with the PRCMU firmware.
@@ -2624,7 +2626,7 @@ static void prcmu_irq_mask(struct irq_data *d)
 
 
 	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 
 
-	mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE];
+	mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
 
 
 	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 
 
@@ -2638,7 +2640,7 @@ static void prcmu_irq_unmask(struct irq_data *d)
 
 
 	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 
 
-	mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE];
+	mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
 
 
 	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 
 
@@ -2678,9 +2680,37 @@ static char *fw_project_name(u8 project)
 	}
 	}
 }
 }
 
 
+static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(virq, &prcmu_irq_chip,
+				handle_simple_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops db8500_irq_ops = {
+        .map    = db8500_irq_map,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int db8500_irq_init(struct device_node *np)
+{
+	db8500_irq_domain = irq_domain_add_legacy(
+		np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE,
+		0, &db8500_irq_ops, NULL);
+
+	if (!db8500_irq_domain) {
+		pr_err("Failed to create irqdomain\n");
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
 void __init db8500_prcmu_early_init(void)
 void __init db8500_prcmu_early_init(void)
 {
 {
-	unsigned int i;
 	if (cpu_is_u8500v2()) {
 	if (cpu_is_u8500v2()) {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 
 
@@ -2725,15 +2755,6 @@ void __init db8500_prcmu_early_init(void)
 
 
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 
 
-	/* Initalize irqs. */
-	for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) {
-		unsigned int irq;
-
-		irq = IRQ_PRCMU_BASE + i;
-		irq_set_chip_and_handler(irq, &prcmu_irq_chip,
-					 handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
 	compute_armss_rate();
 	compute_armss_rate();
 }
 }
 
 
@@ -3041,6 +3062,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 		goto no_irq_return;
 		goto no_irq_return;
 	}
 	}
 
 
+	db8500_irq_init(np);
+
 	for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
 	for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
 		if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
 		if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
 			db8500_prcmu_devs[i].platform_data = ab8500_platdata;
 			db8500_prcmu_devs[i].platform_data = ab8500_platdata;

+ 198 - 0
drivers/mfd/lp8788-irq.c

@@ -0,0 +1,198 @@
+/*
+ * TI LP8788 MFD - interrupt handler
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/device.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/* register address */
+#define LP8788_INT_1			0x00
+#define LP8788_INTEN_1			0x03
+
+#define BASE_INTEN_ADDR			LP8788_INTEN_1
+#define SIZE_REG			8
+#define NUM_REGS			3
+
+/*
+ * struct lp8788_irq_data
+ * @lp               : used for accessing to lp8788 registers
+ * @irq_lock         : mutex for enabling/disabling the interrupt
+ * @domain           : IRQ domain for handling nested interrupt
+ * @enabled          : status of enabled interrupt
+ */
+struct lp8788_irq_data {
+	struct lp8788 *lp;
+	struct mutex irq_lock;
+	struct irq_domain *domain;
+	int enabled[LP8788_INT_MAX];
+};
+
+static inline u8 _irq_to_addr(enum lp8788_int_id id)
+{
+	return id / SIZE_REG;
+}
+
+static inline u8 _irq_to_enable_addr(enum lp8788_int_id id)
+{
+	return _irq_to_addr(id) + BASE_INTEN_ADDR;
+}
+
+static inline u8 _irq_to_mask(enum lp8788_int_id id)
+{
+	return 1 << (id % SIZE_REG);
+}
+
+static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
+{
+	return enable << (id % SIZE_REG);
+}
+
+static void lp8788_irq_enable(struct irq_data *data)
+{
+	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+	irqd->enabled[data->hwirq] = 1;
+}
+
+static void lp8788_irq_disable(struct irq_data *data)
+{
+	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+	irqd->enabled[data->hwirq] = 0;
+}
+
+static void lp8788_irq_bus_lock(struct irq_data *data)
+{
+	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&irqd->irq_lock);
+}
+
+static void lp8788_irq_bus_sync_unlock(struct irq_data *data)
+{
+	struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+	enum lp8788_int_id irq = data->hwirq;
+	u8 addr, mask, val;
+
+	addr = _irq_to_enable_addr(irq);
+	mask = _irq_to_mask(irq);
+	val = _irq_to_val(irq, irqd->enabled[irq]);
+
+	lp8788_update_bits(irqd->lp, addr, mask, val);
+
+	mutex_unlock(&irqd->irq_lock);
+}
+
+static struct irq_chip lp8788_irq_chip = {
+	.name			= "lp8788",
+	.irq_enable		= lp8788_irq_enable,
+	.irq_disable		= lp8788_irq_disable,
+	.irq_bus_lock		= lp8788_irq_bus_lock,
+	.irq_bus_sync_unlock	= lp8788_irq_bus_sync_unlock,
+};
+
+static irqreturn_t lp8788_irq_handler(int irq, void *ptr)
+{
+	struct lp8788_irq_data *irqd = ptr;
+	struct lp8788 *lp = irqd->lp;
+	u8 status[NUM_REGS], addr, mask;
+	bool handled;
+	int i;
+
+	if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS))
+		return IRQ_NONE;
+
+	for (i = 0 ; i < LP8788_INT_MAX ; i++) {
+		addr = _irq_to_addr(i);
+		mask = _irq_to_mask(i);
+
+		/* reporting only if the irq is enabled */
+		if (status[addr] & mask) {
+			handle_nested_irq(irq_find_mapping(irqd->domain, i));
+			handled = true;
+		}
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int lp8788_irq_map(struct irq_domain *d, unsigned int virq,
+			irq_hw_number_t hwirq)
+{
+	struct lp8788_irq_data *irqd = d->host_data;
+	struct irq_chip *chip = &lp8788_irq_chip;
+
+	irq_set_chip_data(virq, irqd);
+	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+	irq_set_nested_thread(virq, 1);
+
+#ifdef CONFIG_ARM
+	set_irq_flags(virq, IRQF_VALID);
+#else
+	irq_set_noprobe(virq);
+#endif
+
+	return 0;
+}
+
+static struct irq_domain_ops lp8788_domain_ops = {
+	.map = lp8788_irq_map,
+};
+
+int lp8788_irq_init(struct lp8788 *lp, int irq)
+{
+	struct lp8788_irq_data *irqd;
+	int ret;
+
+	if (irq <= 0) {
+		dev_warn(lp->dev, "invalid irq number: %d\n", irq);
+		return 0;
+	}
+
+	irqd = devm_kzalloc(lp->dev, sizeof(*irqd), GFP_KERNEL);
+	if (!irqd)
+		return -ENOMEM;
+
+	irqd->lp = lp;
+	irqd->domain = irq_domain_add_linear(lp->dev->of_node, LP8788_INT_MAX,
+					&lp8788_domain_ops, irqd);
+	if (!irqd->domain) {
+		dev_err(lp->dev, "failed to add irq domain err\n");
+		return -EINVAL;
+	}
+
+	lp->irqdm = irqd->domain;
+	mutex_init(&irqd->irq_lock);
+
+	ret = request_threaded_irq(irq, NULL, lp8788_irq_handler,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				"lp8788-irq", irqd);
+	if (ret) {
+		dev_err(lp->dev, "failed to create a thread for IRQ_N\n");
+		return ret;
+	}
+
+	lp->irq = irq;
+
+	return 0;
+}
+
+void lp8788_irq_exit(struct lp8788 *lp)
+{
+	if (lp->irq)
+		free_irq(lp->irq, lp->irqdm);
+}

+ 245 - 0
drivers/mfd/lp8788.c

@@ -0,0 +1,245 @@
+/*
+ * TI LP8788 MFD - core interface
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define MAX_LP8788_REGISTERS		0xA2
+
+#define MFD_DEV_SIMPLE(_name)					\
+{								\
+	.name = LP8788_DEV_##_name,				\
+}
+
+#define MFD_DEV_WITH_ID(_name, _id)				\
+{								\
+	.name = LP8788_DEV_##_name,				\
+	.id = _id,						\
+}
+
+#define MFD_DEV_WITH_RESOURCE(_name, _resource, num_resource)	\
+{								\
+	.name = LP8788_DEV_##_name,				\
+	.resources = _resource,					\
+	.num_resources = num_resource,				\
+}
+
+static struct resource chg_irqs[] = {
+	/* Charger Interrupts */
+	{
+		.start = LP8788_INT_CHG_INPUT_STATE,
+		.end   = LP8788_INT_PRECHG_TIMEOUT,
+		.name  = LP8788_CHG_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* Power Routing Switch Interrupts */
+	{
+		.start = LP8788_INT_ENTER_SYS_SUPPORT,
+		.end   = LP8788_INT_EXIT_SYS_SUPPORT,
+		.name  = LP8788_PRSW_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* Battery Interrupts */
+	{
+		.start = LP8788_INT_BATT_LOW,
+		.end   = LP8788_INT_NO_BATT,
+		.name  = LP8788_BATT_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource rtc_irqs[] = {
+	{
+		.start = LP8788_INT_RTC_ALARM1,
+		.end   = LP8788_INT_RTC_ALARM2,
+		.name  = LP8788_ALM_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell lp8788_devs[] = {
+	/* 4 bucks */
+	MFD_DEV_WITH_ID(BUCK, 1),
+	MFD_DEV_WITH_ID(BUCK, 2),
+	MFD_DEV_WITH_ID(BUCK, 3),
+	MFD_DEV_WITH_ID(BUCK, 4),
+
+	/* 12 digital ldos */
+	MFD_DEV_WITH_ID(DLDO, 1),
+	MFD_DEV_WITH_ID(DLDO, 2),
+	MFD_DEV_WITH_ID(DLDO, 3),
+	MFD_DEV_WITH_ID(DLDO, 4),
+	MFD_DEV_WITH_ID(DLDO, 5),
+	MFD_DEV_WITH_ID(DLDO, 6),
+	MFD_DEV_WITH_ID(DLDO, 7),
+	MFD_DEV_WITH_ID(DLDO, 8),
+	MFD_DEV_WITH_ID(DLDO, 9),
+	MFD_DEV_WITH_ID(DLDO, 10),
+	MFD_DEV_WITH_ID(DLDO, 11),
+	MFD_DEV_WITH_ID(DLDO, 12),
+
+	/* 10 analog ldos */
+	MFD_DEV_WITH_ID(ALDO, 1),
+	MFD_DEV_WITH_ID(ALDO, 2),
+	MFD_DEV_WITH_ID(ALDO, 3),
+	MFD_DEV_WITH_ID(ALDO, 4),
+	MFD_DEV_WITH_ID(ALDO, 5),
+	MFD_DEV_WITH_ID(ALDO, 6),
+	MFD_DEV_WITH_ID(ALDO, 7),
+	MFD_DEV_WITH_ID(ALDO, 8),
+	MFD_DEV_WITH_ID(ALDO, 9),
+	MFD_DEV_WITH_ID(ALDO, 10),
+
+	/* ADC */
+	MFD_DEV_SIMPLE(ADC),
+
+	/* battery charger */
+	MFD_DEV_WITH_RESOURCE(CHARGER, chg_irqs, ARRAY_SIZE(chg_irqs)),
+
+	/* rtc */
+	MFD_DEV_WITH_RESOURCE(RTC, rtc_irqs, ARRAY_SIZE(rtc_irqs)),
+
+	/* backlight */
+	MFD_DEV_SIMPLE(BACKLIGHT),
+
+	/* current sink for vibrator */
+	MFD_DEV_SIMPLE(VIBRATOR),
+
+	/* current sink for keypad LED */
+	MFD_DEV_SIMPLE(KEYLED),
+};
+
+int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data)
+{
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(lp->regmap, reg, &val);
+	if (ret < 0) {
+		dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
+		return ret;
+	}
+
+	*data = (u8)val;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lp8788_read_byte);
+
+int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count)
+{
+	return regmap_bulk_read(lp->regmap, reg, data, count);
+}
+EXPORT_SYMBOL_GPL(lp8788_read_multi_bytes);
+
+int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data)
+{
+	return regmap_write(lp->regmap, reg, data);
+}
+EXPORT_SYMBOL_GPL(lp8788_write_byte);
+
+int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data)
+{
+	return regmap_update_bits(lp->regmap, reg, mask, data);
+}
+EXPORT_SYMBOL_GPL(lp8788_update_bits);
+
+static int lp8788_platform_init(struct lp8788 *lp)
+{
+	struct lp8788_platform_data *pdata = lp->pdata;
+
+	return (pdata && pdata->init_func) ? pdata->init_func(lp) : 0;
+}
+
+static const struct regmap_config lp8788_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX_LP8788_REGISTERS,
+};
+
+static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+	struct lp8788 *lp;
+	struct lp8788_platform_data *pdata = cl->dev.platform_data;
+	int ret;
+
+	lp = devm_kzalloc(&cl->dev, sizeof(struct lp8788), GFP_KERNEL);
+	if (!lp)
+		return -ENOMEM;
+
+	lp->regmap = devm_regmap_init_i2c(cl, &lp8788_regmap_config);
+	if (IS_ERR(lp->regmap)) {
+		ret = PTR_ERR(lp->regmap);
+		dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
+		return ret;
+	}
+
+	lp->pdata = pdata;
+	lp->dev = &cl->dev;
+	i2c_set_clientdata(cl, lp);
+
+	ret = lp8788_platform_init(lp);
+	if (ret)
+		return ret;
+
+	ret = lp8788_irq_init(lp, cl->irq);
+	if (ret)
+		return ret;
+
+	return mfd_add_devices(lp->dev, -1, lp8788_devs,
+			       ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+}
+
+static int __devexit lp8788_remove(struct i2c_client *cl)
+{
+	struct lp8788 *lp = i2c_get_clientdata(cl);
+
+	mfd_remove_devices(lp->dev);
+	lp8788_irq_exit(lp);
+	return 0;
+}
+
+static const struct i2c_device_id lp8788_ids[] = {
+	{"lp8788", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lp8788_ids);
+
+static struct i2c_driver lp8788_driver = {
+	.driver = {
+		.name = "lp8788",
+		.owner = THIS_MODULE,
+	},
+	.probe = lp8788_probe,
+	.remove = __devexit_p(lp8788_remove),
+	.id_table = lp8788_ids,
+};
+
+static int __init lp8788_init(void)
+{
+	return i2c_add_driver(&lp8788_driver);
+}
+subsys_initcall(lp8788_init);
+
+static void __exit lp8788_exit(void)
+{
+	i2c_del_driver(&lp8788_driver);
+}
+module_exit(lp8788_exit);
+
+MODULE_DESCRIPTION("TI LP8788 MFD Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");

+ 41 - 2
drivers/mfd/lpc_ich.c

@@ -49,6 +49,7 @@
  *	document number TBD : DH89xxCC
  *	document number TBD : DH89xxCC
  *	document number TBD : Panther Point
  *	document number TBD : Panther Point
  *	document number TBD : Lynx Point
  *	document number TBD : Lynx Point
+ *	document number TBD : Lynx Point-LP
  */
  */
 
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -192,6 +193,7 @@ enum lpc_chipsets {
 	LPC_DH89XXCC,	/* DH89xxCC */
 	LPC_DH89XXCC,	/* DH89xxCC */
 	LPC_PPT,	/* Panther Point */
 	LPC_PPT,	/* Panther Point */
 	LPC_LPT,	/* Lynx Point */
 	LPC_LPT,	/* Lynx Point */
+	LPC_LPT_LP,	/* Lynx Point-LP */
 };
 };
 
 
 struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
 struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
@@ -468,6 +470,10 @@ struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
 		.name = "Lynx Point",
 		.name = "Lynx Point",
 		.iTCO_version = 2,
 		.iTCO_version = 2,
 	},
 	},
+	[LPC_LPT_LP] = {
+		.name = "Lynx Point_LP",
+		.iTCO_version = 2,
+	},
 };
 };
 
 
 /*
 /*
@@ -641,6 +647,14 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
 	{ PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
 	{ PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
 	{ PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
 	{ PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
 	{ PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
 	{ PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
+	{ PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
+	{ PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
 	{ 0, },			/* End of list */
 	{ 0, },			/* End of list */
 };
 };
 MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
 MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@@ -683,6 +697,30 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
 	cell->pdata_size = sizeof(struct lpc_ich_info);
 	cell->pdata_size = sizeof(struct lpc_ich_info);
 }
 }
 
 
+/*
+ * We don't check for resource conflict globally. There are 2 or 3 independent
+ * GPIO groups and it's enough to have access to one of these to instantiate
+ * the device.
+ */
+static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+{
+	int ret;
+	u8 use_gpio = 0;
+
+	if (resource_size(res) >= 0x50 &&
+	    !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3"))
+		use_gpio |= 1 << 2;
+
+	if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2"))
+		use_gpio |= 1 << 1;
+
+	ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1");
+	if (!ret)
+		use_gpio |= 1 << 0;
+
+	return use_gpio ? use_gpio : ret;
+}
+
 static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
 static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
 				const struct pci_device_id *id)
 				const struct pci_device_id *id)
 {
 {
@@ -740,12 +778,13 @@ gpe0_done:
 		break;
 		break;
 	}
 	}
 
 
-	ret = acpi_check_resource_conflict(res);
-	if (ret) {
+	ret = lpc_ich_check_conflict_gpio(res);
+	if (ret < 0) {
 		/* this isn't necessarily fatal for the GPIO */
 		/* this isn't necessarily fatal for the GPIO */
 		acpi_conflict = true;
 		acpi_conflict = true;
 		goto gpio_done;
 		goto gpio_done;
 	}
 	}
+	lpc_chipset_info[id->driver_data].use_gpio = ret;
 	lpc_ich_enable_gpio_space(dev);
 	lpc_ich_enable_gpio_space(dev);
 
 
 	lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
 	lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);

+ 351 - 0
drivers/mfd/max8907.c

@@ -0,0 +1,351 @@
+/*
+ * max8907.c - mfd driver for MAX8907
+ *
+ * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
+ * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max8907.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static struct mfd_cell max8907_cells[] = {
+	{ .name = "max8907-regulator", },
+	{ .name = "max8907-rtc", },
+};
+
+static bool max8907_gen_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX8907_REG_ON_OFF_IRQ1:
+	case MAX8907_REG_ON_OFF_STAT:
+	case MAX8907_REG_ON_OFF_IRQ2:
+	case MAX8907_REG_CHG_IRQ1:
+	case MAX8907_REG_CHG_IRQ2:
+	case MAX8907_REG_CHG_STAT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max8907_gen_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX8907_REG_ON_OFF_IRQ1:
+	case MAX8907_REG_ON_OFF_IRQ2:
+	case MAX8907_REG_CHG_IRQ1:
+	case MAX8907_REG_CHG_IRQ2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max8907_gen_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return !max8907_gen_is_volatile_reg(dev, reg);
+}
+
+static const struct regmap_config max8907_regmap_gen_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = max8907_gen_is_volatile_reg,
+	.precious_reg = max8907_gen_is_precious_reg,
+	.writeable_reg = max8907_gen_is_writeable_reg,
+	.max_register = MAX8907_REG_LDO20VOUT,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static bool max8907_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	if (reg <= MAX8907_REG_RTC_YEAR2)
+		return true;
+
+	switch (reg) {
+	case MAX8907_REG_RTC_STATUS:
+	case MAX8907_REG_RTC_IRQ:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max8907_rtc_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX8907_REG_RTC_IRQ:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max8907_rtc_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX8907_REG_RTC_STATUS:
+	case MAX8907_REG_RTC_IRQ:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static const struct regmap_config max8907_regmap_rtc_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = max8907_rtc_is_volatile_reg,
+	.precious_reg = max8907_rtc_is_precious_reg,
+	.writeable_reg = max8907_rtc_is_writeable_reg,
+	.max_register = MAX8907_REG_MPL_CNTL,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq max8907_chg_irqs[] = {
+	{ .reg_offset = 0, .mask = 1 << 0, },
+	{ .reg_offset = 0, .mask = 1 << 1, },
+	{ .reg_offset = 0, .mask = 1 << 2, },
+	{ .reg_offset = 1, .mask = 1 << 0, },
+	{ .reg_offset = 1, .mask = 1 << 1, },
+	{ .reg_offset = 1, .mask = 1 << 2, },
+	{ .reg_offset = 1, .mask = 1 << 3, },
+	{ .reg_offset = 1, .mask = 1 << 4, },
+	{ .reg_offset = 1, .mask = 1 << 5, },
+	{ .reg_offset = 1, .mask = 1 << 6, },
+	{ .reg_offset = 1, .mask = 1 << 7, },
+};
+
+static const struct regmap_irq_chip max8907_chg_irq_chip = {
+	.name = "max8907 chg",
+	.status_base = MAX8907_REG_CHG_IRQ1,
+	.mask_base = MAX8907_REG_CHG_IRQ1_MASK,
+	.wake_base = MAX8907_REG_CHG_IRQ1_MASK,
+	.irq_reg_stride = MAX8907_REG_CHG_IRQ2 - MAX8907_REG_CHG_IRQ1,
+	.num_regs = 2,
+	.irqs = max8907_chg_irqs,
+	.num_irqs = ARRAY_SIZE(max8907_chg_irqs),
+};
+
+static const struct regmap_irq max8907_on_off_irqs[] = {
+	{ .reg_offset = 0, .mask = 1 << 0, },
+	{ .reg_offset = 0, .mask = 1 << 1, },
+	{ .reg_offset = 0, .mask = 1 << 2, },
+	{ .reg_offset = 0, .mask = 1 << 3, },
+	{ .reg_offset = 0, .mask = 1 << 4, },
+	{ .reg_offset = 0, .mask = 1 << 5, },
+	{ .reg_offset = 0, .mask = 1 << 6, },
+	{ .reg_offset = 0, .mask = 1 << 7, },
+	{ .reg_offset = 1, .mask = 1 << 0, },
+	{ .reg_offset = 1, .mask = 1 << 1, },
+};
+
+static const struct regmap_irq_chip max8907_on_off_irq_chip = {
+	.name = "max8907 on_off",
+	.status_base = MAX8907_REG_ON_OFF_IRQ1,
+	.mask_base = MAX8907_REG_ON_OFF_IRQ1_MASK,
+	.irq_reg_stride = MAX8907_REG_ON_OFF_IRQ2 - MAX8907_REG_ON_OFF_IRQ1,
+	.num_regs = 2,
+	.irqs = max8907_on_off_irqs,
+	.num_irqs = ARRAY_SIZE(max8907_on_off_irqs),
+};
+
+static const struct regmap_irq max8907_rtc_irqs[] = {
+	{ .reg_offset = 0, .mask = 1 << 2, },
+	{ .reg_offset = 0, .mask = 1 << 3, },
+};
+
+static const struct regmap_irq_chip max8907_rtc_irq_chip = {
+	.name = "max8907 rtc",
+	.status_base = MAX8907_REG_RTC_IRQ,
+	.mask_base = MAX8907_REG_RTC_IRQ_MASK,
+	.num_regs = 1,
+	.irqs = max8907_rtc_irqs,
+	.num_irqs = ARRAY_SIZE(max8907_rtc_irqs),
+};
+
+static struct max8907 *max8907_pm_off;
+static void max8907_power_off(void)
+{
+	regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG,
+			MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+}
+
+static __devinit int max8907_i2c_probe(struct i2c_client *i2c,
+				       const struct i2c_device_id *id)
+{
+	struct max8907 *max8907;
+	int ret;
+	struct max8907_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	bool pm_off = false;
+
+	if (pdata)
+		pm_off = pdata->pm_off;
+	else if (i2c->dev.of_node)
+		pm_off = of_property_read_bool(i2c->dev.of_node,
+					"maxim,system-power-controller");
+
+	max8907 = devm_kzalloc(&i2c->dev, sizeof(struct max8907), GFP_KERNEL);
+	if (!max8907) {
+		ret = -ENOMEM;
+		goto err_alloc_drvdata;
+	}
+
+	max8907->dev = &i2c->dev;
+	dev_set_drvdata(max8907->dev, max8907);
+
+	max8907->i2c_gen = i2c;
+	i2c_set_clientdata(i2c, max8907);
+	max8907->regmap_gen = devm_regmap_init_i2c(i2c,
+						&max8907_regmap_gen_config);
+	if (IS_ERR(max8907->regmap_gen)) {
+		ret = PTR_ERR(max8907->regmap_gen);
+		dev_err(&i2c->dev, "gen regmap init failed: %d\n", ret);
+		goto err_regmap_gen;
+	}
+
+	max8907->i2c_rtc = i2c_new_dummy(i2c->adapter, MAX8907_RTC_I2C_ADDR);
+	if (!max8907->i2c_rtc) {
+		ret = -ENOMEM;
+		goto err_dummy_rtc;
+	}
+	i2c_set_clientdata(max8907->i2c_rtc, max8907);
+	max8907->regmap_rtc = devm_regmap_init_i2c(max8907->i2c_rtc,
+						&max8907_regmap_rtc_config);
+	if (IS_ERR(max8907->regmap_rtc)) {
+		ret = PTR_ERR(max8907->regmap_rtc);
+		dev_err(&i2c->dev, "rtc regmap init failed: %d\n", ret);
+		goto err_regmap_rtc;
+	}
+
+	irq_set_status_flags(max8907->i2c_gen->irq, IRQ_NOAUTOEN);
+
+	ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
+				  IRQF_ONESHOT | IRQF_SHARED, -1,
+				  &max8907_chg_irq_chip,
+				  &max8907->irqc_chg);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "failed to add chg irq chip: %d\n", ret);
+		goto err_irqc_chg;
+	}
+	ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
+				  IRQF_ONESHOT | IRQF_SHARED, -1,
+				  &max8907_on_off_irq_chip,
+				  &max8907->irqc_on_off);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "failed to add on off irq chip: %d\n", ret);
+		goto err_irqc_on_off;
+	}
+	ret = regmap_add_irq_chip(max8907->regmap_rtc, max8907->i2c_gen->irq,
+				  IRQF_ONESHOT | IRQF_SHARED, -1,
+				  &max8907_rtc_irq_chip,
+				  &max8907->irqc_rtc);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "failed to add rtc irq chip: %d\n", ret);
+		goto err_irqc_rtc;
+	}
+
+	enable_irq(max8907->i2c_gen->irq);
+
+	ret = mfd_add_devices(max8907->dev, -1, max8907_cells,
+			      ARRAY_SIZE(max8907_cells), NULL, 0, NULL);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "failed to add MFD devices %d\n", ret);
+		goto err_add_devices;
+	}
+
+	if (pm_off && !pm_power_off) {
+		max8907_pm_off = max8907;
+		pm_power_off = max8907_power_off;
+	}
+
+	return 0;
+
+err_add_devices:
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
+err_irqc_rtc:
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
+err_irqc_on_off:
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
+err_irqc_chg:
+err_regmap_rtc:
+	i2c_unregister_device(max8907->i2c_rtc);
+err_dummy_rtc:
+err_regmap_gen:
+err_alloc_drvdata:
+	return ret;
+}
+
+static __devexit int max8907_i2c_remove(struct i2c_client *i2c)
+{
+	struct max8907 *max8907 = i2c_get_clientdata(i2c);
+
+	mfd_remove_devices(max8907->dev);
+
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
+	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
+
+	i2c_unregister_device(max8907->i2c_rtc);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id max8907_of_match[] = {
+	{ .compatible = "maxim,max8907" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, max8907_of_match);
+#endif
+
+static const struct i2c_device_id max8907_i2c_id[] = {
+	{"max8907", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, max8907_i2c_id);
+
+static struct i2c_driver max8907_i2c_driver = {
+	.driver = {
+		.name = "max8907",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(max8907_of_match),
+	},
+	.probe = max8907_i2c_probe,
+	.remove = max8907_i2c_remove,
+	.id_table = max8907_i2c_id,
+};
+
+static int __init max8907_i2c_init(void)
+{
+	int ret = -ENODEV;
+
+	ret = i2c_add_driver(&max8907_i2c_driver);
+	if (ret != 0)
+		pr_err("Failed to register I2C driver: %d\n", ret);
+
+	return ret;
+}
+subsys_initcall(max8907_i2c_init);
+
+static void __exit max8907_i2c_exit(void)
+{
+	i2c_del_driver(&max8907_i2c_driver);
+}
+module_exit(max8907_i2c_exit);
+
+MODULE_DESCRIPTION("MAX8907 multi-function core driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
+MODULE_LICENSE("GPL v2");

+ 334 - 93
drivers/mfd/max8925-core.c

@@ -15,23 +15,20 @@
 #include <linux/irq.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
 #include <linux/mfd/max8925.h>
 
 
-static struct resource backlight_resources[] = {
-	{
-		.name	= "max8925-backlight",
-		.start	= MAX8925_WLED_MODE_CNTL,
-		.end	= MAX8925_WLED_CNTL,
-		.flags	= IORESOURCE_IO,
-	},
+static struct resource bk_resources[] __devinitdata = {
+	{ 0x84, 0x84, "mode control", IORESOURCE_REG, },
+	{ 0x85, 0x85, "control",      IORESOURCE_REG, },
 };
 };
 
 
-static struct mfd_cell backlight_devs[] = {
+static struct mfd_cell bk_devs[] __devinitdata = {
 	{
 	{
 		.name		= "max8925-backlight",
 		.name		= "max8925-backlight",
-		.num_resources	= 1,
-		.resources	= &backlight_resources[0],
+		.num_resources	= ARRAY_SIZE(bk_resources),
+		.resources	= &bk_resources[0],
 		.id		= -1,
 		.id		= -1,
 	},
 	},
 };
 };
@@ -41,7 +38,7 @@ static struct resource touch_resources[] = {
 		.name	= "max8925-tsc",
 		.name	= "max8925-tsc",
 		.start	= MAX8925_TSC_IRQ,
 		.start	= MAX8925_TSC_IRQ,
 		.end	= MAX8925_ADC_RES_END,
 		.end	= MAX8925_ADC_RES_END,
-		.flags	= IORESOURCE_IO,
+		.flags	= IORESOURCE_REG,
 	},
 	},
 };
 };
 
 
@@ -59,7 +56,7 @@ static struct resource power_supply_resources[] = {
 		.name	= "max8925-power",
 		.name	= "max8925-power",
 		.start	= MAX8925_CHG_IRQ1,
 		.start	= MAX8925_CHG_IRQ1,
 		.end	= MAX8925_CHG_IRQ1_MASK,
 		.end	= MAX8925_CHG_IRQ1_MASK,
-		.flags	= IORESOURCE_IO,
+		.flags	= IORESOURCE_REG,
 	},
 	},
 };
 };
 
 
@@ -113,71 +110,215 @@ static struct mfd_cell onkey_devs[] = {
 	},
 	},
 };
 };
 
 
-#define MAX8925_REG_RESOURCE(_start, _end)	\
-{						\
-	.start	= MAX8925_##_start,		\
-	.end	= MAX8925_##_end,		\
-	.flags	= IORESOURCE_IO,		\
-}
+static struct resource sd1_resources[] __devinitdata = {
+	{0x06, 0x06, "sdv", IORESOURCE_REG, },
+};
 
 
-static struct resource regulator_resources[] = {
-	MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
-	MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
-	MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
-	MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
-	MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
-	MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
-	MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
-	MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
-	MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
-	MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
-	MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
-	MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
-	MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
-	MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
-	MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
-	MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
-	MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
-	MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
-	MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
-	MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
-	MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
-	MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
-};
-
-#define MAX8925_REG_DEVS(_id)						\
-{									\
-	.name		= "max8925-regulator",				\
-	.num_resources	= 1,						\
-	.resources	= &regulator_resources[MAX8925_ID_##_id],	\
-	.id		= MAX8925_ID_##_id,				\
-}
+static struct resource sd2_resources[] __devinitdata = {
+	{0x09, 0x09, "sdv", IORESOURCE_REG, },
+};
+
+static struct resource sd3_resources[] __devinitdata = {
+	{0x0c, 0x0c, "sdv", IORESOURCE_REG, },
+};
+
+static struct resource ldo1_resources[] __devinitdata = {
+	{0x1a, 0x1a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo2_resources[] __devinitdata = {
+	{0x1e, 0x1e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo3_resources[] __devinitdata = {
+	{0x22, 0x22, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo4_resources[] __devinitdata = {
+	{0x26, 0x26, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo5_resources[] __devinitdata = {
+	{0x2a, 0x2a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo6_resources[] __devinitdata = {
+	{0x2e, 0x2e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo7_resources[] __devinitdata = {
+	{0x32, 0x32, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo8_resources[] __devinitdata = {
+	{0x36, 0x36, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo9_resources[] __devinitdata = {
+	{0x3a, 0x3a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo10_resources[] __devinitdata = {
+	{0x3e, 0x3e, "ldov", IORESOURCE_REG, },
+};
 
 
-static struct mfd_cell regulator_devs[] = {
-	MAX8925_REG_DEVS(SD1),
-	MAX8925_REG_DEVS(SD2),
-	MAX8925_REG_DEVS(SD3),
-	MAX8925_REG_DEVS(LDO1),
-	MAX8925_REG_DEVS(LDO2),
-	MAX8925_REG_DEVS(LDO3),
-	MAX8925_REG_DEVS(LDO4),
-	MAX8925_REG_DEVS(LDO5),
-	MAX8925_REG_DEVS(LDO6),
-	MAX8925_REG_DEVS(LDO7),
-	MAX8925_REG_DEVS(LDO8),
-	MAX8925_REG_DEVS(LDO9),
-	MAX8925_REG_DEVS(LDO10),
-	MAX8925_REG_DEVS(LDO11),
-	MAX8925_REG_DEVS(LDO12),
-	MAX8925_REG_DEVS(LDO13),
-	MAX8925_REG_DEVS(LDO14),
-	MAX8925_REG_DEVS(LDO15),
-	MAX8925_REG_DEVS(LDO16),
-	MAX8925_REG_DEVS(LDO17),
-	MAX8925_REG_DEVS(LDO18),
-	MAX8925_REG_DEVS(LDO19),
-	MAX8925_REG_DEVS(LDO20),
+static struct resource ldo11_resources[] __devinitdata = {
+	{0x42, 0x42, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo12_resources[] __devinitdata = {
+	{0x46, 0x46, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo13_resources[] __devinitdata = {
+	{0x4a, 0x4a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo14_resources[] __devinitdata = {
+	{0x4e, 0x4e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo15_resources[] __devinitdata = {
+	{0x52, 0x52, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo16_resources[] __devinitdata = {
+	{0x12, 0x12, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo17_resources[] __devinitdata = {
+	{0x16, 0x16, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo18_resources[] __devinitdata = {
+	{0x74, 0x74, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo19_resources[] __devinitdata = {
+	{0x5e, 0x5e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo20_resources[] __devinitdata = {
+	{0x9e, 0x9e, "ldov", IORESOURCE_REG, },
+};
+
+static struct mfd_cell reg_devs[] __devinitdata = {
+	{
+		.name = "max8925-regulator",
+		.id = 0,
+		.num_resources = ARRAY_SIZE(sd1_resources),
+		.resources = sd1_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 1,
+		.num_resources = ARRAY_SIZE(sd2_resources),
+		.resources = sd2_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 2,
+		.num_resources = ARRAY_SIZE(sd3_resources),
+		.resources = sd3_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 3,
+		.num_resources = ARRAY_SIZE(ldo1_resources),
+		.resources = ldo1_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 4,
+		.num_resources = ARRAY_SIZE(ldo2_resources),
+		.resources = ldo2_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 5,
+		.num_resources = ARRAY_SIZE(ldo3_resources),
+		.resources = ldo3_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 6,
+		.num_resources = ARRAY_SIZE(ldo4_resources),
+		.resources = ldo4_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 7,
+		.num_resources = ARRAY_SIZE(ldo5_resources),
+		.resources = ldo5_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 8,
+		.num_resources = ARRAY_SIZE(ldo6_resources),
+		.resources = ldo6_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 9,
+		.num_resources = ARRAY_SIZE(ldo7_resources),
+		.resources = ldo7_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 10,
+		.num_resources = ARRAY_SIZE(ldo8_resources),
+		.resources = ldo8_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 11,
+		.num_resources = ARRAY_SIZE(ldo9_resources),
+		.resources = ldo9_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 12,
+		.num_resources = ARRAY_SIZE(ldo10_resources),
+		.resources = ldo10_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 13,
+		.num_resources = ARRAY_SIZE(ldo11_resources),
+		.resources = ldo11_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 14,
+		.num_resources = ARRAY_SIZE(ldo12_resources),
+		.resources = ldo12_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 15,
+		.num_resources = ARRAY_SIZE(ldo13_resources),
+		.resources = ldo13_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 16,
+		.num_resources = ARRAY_SIZE(ldo14_resources),
+		.resources = ldo14_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 17,
+		.num_resources = ARRAY_SIZE(ldo15_resources),
+		.resources = ldo15_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 18,
+		.num_resources = ARRAY_SIZE(ldo16_resources),
+		.resources = ldo16_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 19,
+		.num_resources = ARRAY_SIZE(ldo17_resources),
+		.resources = ldo17_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 20,
+		.num_resources = ARRAY_SIZE(ldo18_resources),
+		.resources = ldo18_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 21,
+		.num_resources = ARRAY_SIZE(ldo19_resources),
+		.resources = ldo19_resources,
+	}, {
+		.name = "max8925-regulator",
+		.id = 22,
+		.num_resources = ARRAY_SIZE(ldo20_resources),
+		.resources = ldo20_resources,
+	},
 };
 };
 
 
 enum {
 enum {
@@ -547,7 +688,7 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
 		goto tsc_irq;
 		goto tsc_irq;
 	}
 	}
 
 
-	ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
+	ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT,
 				   "max8925", chip);
 				   "max8925", chip);
 	if (ret) {
 	if (ret) {
 		dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
 		dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
@@ -565,7 +706,7 @@ tsc_irq:
 	chip->tsc_irq = pdata->tsc_irq;
 	chip->tsc_irq = pdata->tsc_irq;
 
 
 	ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
 	ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
-				   flags, "max8925-tsc", chip);
+				   flags | IRQF_ONESHOT, "max8925-tsc", chip);
 	if (ret) {
 	if (ret) {
 		dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
 		dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
 		chip->tsc_irq = 0;
 		chip->tsc_irq = 0;
@@ -573,6 +714,113 @@ tsc_irq:
 	return 0;
 	return 0;
 }
 }
 
 
+static void __devinit init_regulator(struct max8925_chip *chip,
+				     struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	if (!pdata)
+		return;
+	if (pdata->sd1) {
+		reg_devs[0].platform_data = pdata->sd1;
+		reg_devs[0].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->sd2) {
+		reg_devs[1].platform_data = pdata->sd2;
+		reg_devs[1].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->sd3) {
+		reg_devs[2].platform_data = pdata->sd3;
+		reg_devs[2].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo1) {
+		reg_devs[3].platform_data = pdata->ldo1;
+		reg_devs[3].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo2) {
+		reg_devs[4].platform_data = pdata->ldo2;
+		reg_devs[4].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo3) {
+		reg_devs[5].platform_data = pdata->ldo3;
+		reg_devs[5].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo4) {
+		reg_devs[6].platform_data = pdata->ldo4;
+		reg_devs[6].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo5) {
+		reg_devs[7].platform_data = pdata->ldo5;
+		reg_devs[7].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo6) {
+		reg_devs[8].platform_data = pdata->ldo6;
+		reg_devs[8].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo7) {
+		reg_devs[9].platform_data = pdata->ldo7;
+		reg_devs[9].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo8) {
+		reg_devs[10].platform_data = pdata->ldo8;
+		reg_devs[10].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo9) {
+		reg_devs[11].platform_data = pdata->ldo9;
+		reg_devs[11].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo10) {
+		reg_devs[12].platform_data = pdata->ldo10;
+		reg_devs[12].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo11) {
+		reg_devs[13].platform_data = pdata->ldo11;
+		reg_devs[13].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo12) {
+		reg_devs[14].platform_data = pdata->ldo12;
+		reg_devs[14].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo13) {
+		reg_devs[15].platform_data = pdata->ldo13;
+		reg_devs[15].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo14) {
+		reg_devs[16].platform_data = pdata->ldo14;
+		reg_devs[16].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo15) {
+		reg_devs[17].platform_data = pdata->ldo15;
+		reg_devs[17].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo16) {
+		reg_devs[18].platform_data = pdata->ldo16;
+		reg_devs[18].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo17) {
+		reg_devs[19].platform_data = pdata->ldo17;
+		reg_devs[19].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo18) {
+		reg_devs[20].platform_data = pdata->ldo18;
+		reg_devs[20].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo19) {
+		reg_devs[21].platform_data = pdata->ldo19;
+		reg_devs[21].pdata_size = sizeof(struct regulator_init_data);
+	}
+	if (pdata->ldo20) {
+		reg_devs[22].platform_data = pdata->ldo20;
+		reg_devs[22].pdata_size = sizeof(struct regulator_init_data);
+	}
+	ret = mfd_add_devices(chip->dev, 0, reg_devs, ARRAY_SIZE(reg_devs),
+			      NULL, 0, NULL);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add regulator subdev\n");
+		return;
+	}
+}
+
 int __devinit max8925_device_init(struct max8925_chip *chip,
 int __devinit max8925_device_init(struct max8925_chip *chip,
 				  struct max8925_platform_data *pdata)
 				  struct max8925_platform_data *pdata)
 {
 {
@@ -612,24 +860,17 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
 		goto out_dev;
 		goto out_dev;
 	}
 	}
 
 
-	if (pdata) {
-		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
-				      ARRAY_SIZE(regulator_devs),
-				      &regulator_resources[0], 0, NULL);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add regulator subdev\n");
-			goto out_dev;
-		}
-	}
+	init_regulator(chip, pdata);
 
 
 	if (pdata && pdata->backlight) {
 	if (pdata && pdata->backlight) {
-		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
-				      ARRAY_SIZE(backlight_devs),
-				      &backlight_resources[0], 0, NULL);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add backlight subdev\n");
-			goto out_dev;
-		}
+		bk_devs[0].platform_data = &pdata->backlight;
+		bk_devs[0].pdata_size = sizeof(struct max8925_backlight_pdata);
+	}
+	ret = mfd_add_devices(chip->dev, 0, bk_devs, ARRAY_SIZE(bk_devs),
+			      NULL, 0, NULL);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add backlight subdev\n");
+		goto out_dev;
 	}
 	}
 
 
 	if (pdata && pdata->power) {
 	if (pdata && pdata->power) {

+ 0 - 1
drivers/mfd/mc13xxx-core.c

@@ -676,7 +676,6 @@ int mc13xxx_common_init(struct mc13xxx *mc13xxx,
 err_mask:
 err_mask:
 err_revision:
 err_revision:
 		mc13xxx_unlock(mc13xxx);
 		mc13xxx_unlock(mc13xxx);
-		kfree(mc13xxx);
 		return ret;
 		return ret;
 	}
 	}
 
 

+ 15 - 223
drivers/mfd/omap-usb-host.c

@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
@@ -36,63 +35,6 @@
 
 
 /* OMAP USBHOST Register addresses  */
 /* OMAP USBHOST Register addresses  */
 
 
-/* TLL Register Set */
-#define	OMAP_USBTLL_REVISION				(0x00)
-#define	OMAP_USBTLL_SYSCONFIG				(0x10)
-#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_USBTLL_SYSSTATUS				(0x14)
-#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
-
-#define	OMAP_USBTLL_IRQSTATUS				(0x18)
-#define	OMAP_USBTLL_IRQENABLE				(0x1C)
-
-#define	OMAP_TLL_SHARED_CONF				(0x30)
-#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
-#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
-#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
-#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
-#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
-
-#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
-#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
-#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
-#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
-#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
-#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
-#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
-#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
-
-#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0		0x0
-#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM		0x1
-#define OMAP_TLL_FSLSMODE_3PIN_PHY			0x2
-#define OMAP_TLL_FSLSMODE_4PIN_PHY			0x3
-#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0		0x4
-#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM		0x5
-#define OMAP_TLL_FSLSMODE_3PIN_TLL			0x6
-#define OMAP_TLL_FSLSMODE_4PIN_TLL			0x7
-#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0		0xA
-#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM		0xB
-
-#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
-#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
-#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
-#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
-
-#define OMAP_TLL_CHANNEL_COUNT				3
-#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
-#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
-#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
-
 /* UHH Register Set */
 /* UHH Register Set */
 #define	OMAP_UHH_REVISION				(0x00)
 #define	OMAP_UHH_REVISION				(0x00)
 #define	OMAP_UHH_SYSCONFIG				(0x10)
 #define	OMAP_UHH_SYSCONFIG				(0x10)
@@ -132,8 +74,6 @@
 #define OMAP4_P2_MODE_TLL				(1 << 18)
 #define OMAP4_P2_MODE_TLL				(1 << 18)
 #define OMAP4_P2_MODE_HSIC				(3 << 18)
 #define OMAP4_P2_MODE_HSIC				(3 << 18)
 
 
-#define OMAP_REV2_TLL_CHANNEL_COUNT			2
-
 #define	OMAP_UHH_DEBUG_CSR				(0x44)
 #define	OMAP_UHH_DEBUG_CSR				(0x44)
 
 
 /* Values of UHH_REVISION - Note: these are not given in the TRM */
 /* Values of UHH_REVISION - Note: these are not given in the TRM */
@@ -153,15 +93,12 @@ struct usbhs_hcd_omap {
 	struct clk			*xclk60mhsp2_ck;
 	struct clk			*xclk60mhsp2_ck;
 	struct clk			*utmi_p1_fck;
 	struct clk			*utmi_p1_fck;
 	struct clk			*usbhost_p1_fck;
 	struct clk			*usbhost_p1_fck;
-	struct clk			*usbtll_p1_fck;
 	struct clk			*utmi_p2_fck;
 	struct clk			*utmi_p2_fck;
 	struct clk			*usbhost_p2_fck;
 	struct clk			*usbhost_p2_fck;
-	struct clk			*usbtll_p2_fck;
 	struct clk			*init_60m_fclk;
 	struct clk			*init_60m_fclk;
 	struct clk			*ehci_logic_fck;
 	struct clk			*ehci_logic_fck;
 
 
 	void __iomem			*uhh_base;
 	void __iomem			*uhh_base;
-	void __iomem			*tll_base;
 
 
 	struct usbhs_omap_platform_data	platdata;
 	struct usbhs_omap_platform_data	platdata;
 
 
@@ -336,93 +273,6 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
 	}
 	}
 }
 }
 
 
-/*
- * convert the port-mode enum to a value we can use in the FSLSMODE
- * field of USBTLL_CHANNEL_CONF
- */
-static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
-{
-	switch (mode) {
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
-
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-		return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
-
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-		return OMAP_TLL_FSLSMODE_3PIN_PHY;
-
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-		return OMAP_TLL_FSLSMODE_4PIN_PHY;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-		return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
-
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		return OMAP_TLL_FSLSMODE_3PIN_TLL;
-
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		return OMAP_TLL_FSLSMODE_4PIN_TLL;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-		return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
-	default:
-		pr_warning("Invalid port mode, using default\n");
-		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
-	}
-}
-
-static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
-{
-	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
-	unsigned			reg;
-	int				i;
-
-	/* Program Common TLL register */
-	reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF);
-	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
-		| OMAP_TLL_SHARED_CONF_USB_DIVRATION);
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
-
-	usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-	/* Enable channels now */
-	for (i = 0; i < tll_channel_count; i++) {
-		reg = usbhs_read(omap->tll_base,
-				OMAP_TLL_CHANNEL_CONF(i));
-
-		if (is_ohci_port(pdata->port_mode[i])) {
-			reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
-				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
-			reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
-		} else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) {
-
-			/* Disable AutoIdle, BitStuffing and use SDR Mode */
-			reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
-				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
-				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
-
-		} else
-			continue;
-
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-		usbhs_write(omap->tll_base,
-				OMAP_TLL_CHANNEL_CONF(i), reg);
-
-		usbhs_writeb(omap->tll_base,
-				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
-	}
-}
-
 static int usbhs_runtime_resume(struct device *dev)
 static int usbhs_runtime_resume(struct device *dev)
 {
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
@@ -436,19 +286,17 @@ static int usbhs_runtime_resume(struct device *dev)
 		return  -ENODEV;
 		return  -ENODEV;
 	}
 	}
 
 
+	omap_tll_enable();
 	spin_lock_irqsave(&omap->lock, flags);
 	spin_lock_irqsave(&omap->lock, flags);
 
 
 	if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
 	if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
 		clk_enable(omap->ehci_logic_fck);
 		clk_enable(omap->ehci_logic_fck);
 
 
-	if (is_ehci_tll_mode(pdata->port_mode[0])) {
+	if (is_ehci_tll_mode(pdata->port_mode[0]))
 		clk_enable(omap->usbhost_p1_fck);
 		clk_enable(omap->usbhost_p1_fck);
-		clk_enable(omap->usbtll_p1_fck);
-	}
-	if (is_ehci_tll_mode(pdata->port_mode[1])) {
+	if (is_ehci_tll_mode(pdata->port_mode[1]))
 		clk_enable(omap->usbhost_p2_fck);
 		clk_enable(omap->usbhost_p2_fck);
-		clk_enable(omap->usbtll_p2_fck);
-	}
+
 	clk_enable(omap->utmi_p1_fck);
 	clk_enable(omap->utmi_p1_fck);
 	clk_enable(omap->utmi_p2_fck);
 	clk_enable(omap->utmi_p2_fck);
 
 
@@ -472,14 +320,11 @@ static int usbhs_runtime_suspend(struct device *dev)
 
 
 	spin_lock_irqsave(&omap->lock, flags);
 	spin_lock_irqsave(&omap->lock, flags);
 
 
-	if (is_ehci_tll_mode(pdata->port_mode[0])) {
+	if (is_ehci_tll_mode(pdata->port_mode[0]))
 		clk_disable(omap->usbhost_p1_fck);
 		clk_disable(omap->usbhost_p1_fck);
-		clk_disable(omap->usbtll_p1_fck);
-	}
-	if (is_ehci_tll_mode(pdata->port_mode[1])) {
+	if (is_ehci_tll_mode(pdata->port_mode[1]))
 		clk_disable(omap->usbhost_p2_fck);
 		clk_disable(omap->usbhost_p2_fck);
-		clk_disable(omap->usbtll_p2_fck);
-	}
+
 	clk_disable(omap->utmi_p2_fck);
 	clk_disable(omap->utmi_p2_fck);
 	clk_disable(omap->utmi_p1_fck);
 	clk_disable(omap->utmi_p1_fck);
 
 
@@ -487,6 +332,7 @@ static int usbhs_runtime_suspend(struct device *dev)
 		clk_disable(omap->ehci_logic_fck);
 		clk_disable(omap->ehci_logic_fck);
 
 
 	spin_unlock_irqrestore(&omap->lock, flags);
 	spin_unlock_irqrestore(&omap->lock, flags);
+	omap_tll_disable();
 
 
 	return 0;
 	return 0;
 }
 }
@@ -500,8 +346,6 @@ static void omap_usbhs_init(struct device *dev)
 
 
 	dev_dbg(dev, "starting TI HSUSB Controller\n");
 	dev_dbg(dev, "starting TI HSUSB Controller\n");
 
 
-	pm_runtime_get_sync(dev);
-
 	if (pdata->ehci_data->phy_reset) {
 	if (pdata->ehci_data->phy_reset) {
 		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
 		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
 			gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
 			gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
@@ -515,6 +359,7 @@ static void omap_usbhs_init(struct device *dev)
 		udelay(10);
 		udelay(10);
 	}
 	}
 
 
+	pm_runtime_get_sync(dev);
 	spin_lock_irqsave(&omap->lock, flags);
 	spin_lock_irqsave(&omap->lock, flags);
 	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
 	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
 	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
 	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
@@ -580,22 +425,9 @@ static void omap_usbhs_init(struct device *dev)
 	usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
 	usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
 	dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
 	dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
 
 
-	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
-		is_ehci_tll_mode(pdata->port_mode[1]) ||
-		is_ehci_tll_mode(pdata->port_mode[2]) ||
-		(is_ohci_port(pdata->port_mode[0])) ||
-		(is_ohci_port(pdata->port_mode[1])) ||
-		(is_ohci_port(pdata->port_mode[2]))) {
-
-		/* Enable UTMI mode for required TLL channels */
-		if (is_omap_usbhs_rev2(omap))
-			usbhs_omap_tll_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT);
-		else
-			usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
-	}
-
 	spin_unlock_irqrestore(&omap->lock, flags);
 	spin_unlock_irqrestore(&omap->lock, flags);
 
 
+	pm_runtime_put_sync(dev);
 	if (pdata->ehci_data->phy_reset) {
 	if (pdata->ehci_data->phy_reset) {
 		/* Hold the PHY in RESET for enough time till
 		/* Hold the PHY in RESET for enough time till
 		 * PHY is settled and ready
 		 * PHY is settled and ready
@@ -610,8 +442,6 @@ static void omap_usbhs_init(struct device *dev)
 			gpio_set_value_cansleep
 			gpio_set_value_cansleep
 				(pdata->ehci_data->reset_gpio_port[1], 1);
 				(pdata->ehci_data->reset_gpio_port[1], 1);
 	}
 	}
-
-	pm_runtime_put_sync(dev);
 }
 }
 
 
 static void omap_usbhs_deinit(struct device *dev)
 static void omap_usbhs_deinit(struct device *dev)
@@ -714,32 +544,18 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 		goto err_xclk60mhsp2_ck;
 		goto err_xclk60mhsp2_ck;
 	}
 	}
 
 
-	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
-	if (IS_ERR(omap->usbtll_p1_fck)) {
-		ret = PTR_ERR(omap->usbtll_p1_fck);
-		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
-		goto err_usbhost_p1_fck;
-	}
-
 	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
 	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
 	if (IS_ERR(omap->usbhost_p2_fck)) {
 	if (IS_ERR(omap->usbhost_p2_fck)) {
 		ret = PTR_ERR(omap->usbhost_p2_fck);
 		ret = PTR_ERR(omap->usbhost_p2_fck);
 		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
 		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
-		goto err_usbtll_p1_fck;
-	}
-
-	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
-	if (IS_ERR(omap->usbtll_p2_fck)) {
-		ret = PTR_ERR(omap->usbtll_p2_fck);
-		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
-		goto err_usbhost_p2_fck;
+		goto err_usbhost_p1_fck;
 	}
 	}
 
 
 	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
 	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
 	if (IS_ERR(omap->init_60m_fclk)) {
 	if (IS_ERR(omap->init_60m_fclk)) {
 		ret = PTR_ERR(omap->init_60m_fclk);
 		ret = PTR_ERR(omap->init_60m_fclk);
 		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
 		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
-		goto err_usbtll_p2_fck;
+		goto err_usbhost_p2_fck;
 	}
 	}
 
 
 	if (is_ehci_phy_mode(pdata->port_mode[0])) {
 	if (is_ehci_phy_mode(pdata->port_mode[0])) {
@@ -785,20 +601,6 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 		goto err_init_60m_fclk;
 		goto err_init_60m_fclk;
 	}
 	}
 
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
-	if (!res) {
-		dev_err(dev, "UHH EHCI get resource failed\n");
-		ret = -ENODEV;
-		goto err_tll;
-	}
-
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll;
-	}
-
 	platform_set_drvdata(pdev, omap);
 	platform_set_drvdata(pdev, omap);
 
 
 	omap_usbhs_init(dev);
 	omap_usbhs_init(dev);
@@ -812,23 +614,14 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 
 
 err_alloc:
 err_alloc:
 	omap_usbhs_deinit(&pdev->dev);
 	omap_usbhs_deinit(&pdev->dev);
-	iounmap(omap->tll_base);
-
-err_tll:
 	iounmap(omap->uhh_base);
 	iounmap(omap->uhh_base);
 
 
 err_init_60m_fclk:
 err_init_60m_fclk:
 	clk_put(omap->init_60m_fclk);
 	clk_put(omap->init_60m_fclk);
 
 
-err_usbtll_p2_fck:
-	clk_put(omap->usbtll_p2_fck);
-
 err_usbhost_p2_fck:
 err_usbhost_p2_fck:
 	clk_put(omap->usbhost_p2_fck);
 	clk_put(omap->usbhost_p2_fck);
 
 
-err_usbtll_p1_fck:
-	clk_put(omap->usbtll_p1_fck);
-
 err_usbhost_p1_fck:
 err_usbhost_p1_fck:
 	clk_put(omap->usbhost_p1_fck);
 	clk_put(omap->usbhost_p1_fck);
 
 
@@ -864,12 +657,9 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 
 
 	omap_usbhs_deinit(&pdev->dev);
 	omap_usbhs_deinit(&pdev->dev);
-	iounmap(omap->tll_base);
 	iounmap(omap->uhh_base);
 	iounmap(omap->uhh_base);
 	clk_put(omap->init_60m_fclk);
 	clk_put(omap->init_60m_fclk);
-	clk_put(omap->usbtll_p2_fck);
 	clk_put(omap->usbhost_p2_fck);
 	clk_put(omap->usbhost_p2_fck);
-	clk_put(omap->usbtll_p1_fck);
 	clk_put(omap->usbhost_p1_fck);
 	clk_put(omap->usbhost_p1_fck);
 	clk_put(omap->xclk60mhsp2_ck);
 	clk_put(omap->xclk60mhsp2_ck);
 	clk_put(omap->utmi_p2_fck);
 	clk_put(omap->utmi_p2_fck);
@@ -910,8 +700,10 @@ static int __init omap_usbhs_drvinit(void)
  * init before ehci and ohci drivers;
  * init before ehci and ohci drivers;
  * The usbhs core driver should be initialized much before
  * The usbhs core driver should be initialized much before
  * the omap ehci and ohci probe functions are called.
  * the omap ehci and ohci probe functions are called.
+ * This usbhs core driver should be initialized after
+ * usb tll driver
  */
  */
-fs_initcall(omap_usbhs_drvinit);
+fs_initcall_sync(omap_usbhs_drvinit);
 
 
 static void __exit omap_usbhs_drvexit(void)
 static void __exit omap_usbhs_drvexit(void)
 {
 {

+ 471 - 0
drivers/mfd/omap-usb-tll.c

@@ -0,0 +1,471 @@
+/**
+ * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/usb.h>
+#include <linux/pm_runtime.h>
+
+#define USBTLL_DRIVER_NAME	"usbhs_tll"
+
+/* TLL Register Set */
+#define	OMAP_USBTLL_REVISION				(0x00)
+#define	OMAP_USBTLL_SYSCONFIG				(0x10)
+#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
+#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
+#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
+#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define	OMAP_USBTLL_SYSSTATUS				(0x14)
+#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
+
+#define	OMAP_USBTLL_IRQSTATUS				(0x18)
+#define	OMAP_USBTLL_IRQENABLE				(0x1C)
+
+#define	OMAP_TLL_SHARED_CONF				(0x30)
+#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
+#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
+#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
+#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
+#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
+
+#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
+#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
+#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
+#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
+#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
+#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
+#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
+#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
+
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0		0x0
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM		0x1
+#define OMAP_TLL_FSLSMODE_3PIN_PHY			0x2
+#define OMAP_TLL_FSLSMODE_4PIN_PHY			0x3
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0		0x4
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM		0x5
+#define OMAP_TLL_FSLSMODE_3PIN_TLL			0x6
+#define OMAP_TLL_FSLSMODE_4PIN_TLL			0x7
+#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0		0xA
+#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM		0xB
+
+#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
+#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
+#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
+#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
+
+#define OMAP_REV2_TLL_CHANNEL_COUNT			2
+#define OMAP_TLL_CHANNEL_COUNT				3
+#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
+#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
+#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
+
+/* Values of USBTLL_REVISION - Note: these are not given in the TRM */
+#define OMAP_USBTLL_REV1		0x00000015	/* OMAP3 */
+#define OMAP_USBTLL_REV2		0x00000018	/* OMAP 3630 */
+#define OMAP_USBTLL_REV3		0x00000004	/* OMAP4 */
+
+#define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
+
+struct usbtll_omap {
+	struct clk				*usbtll_p1_fck;
+	struct clk				*usbtll_p2_fck;
+	struct usbtll_omap_platform_data	platdata;
+	/* secure the register updates */
+	spinlock_t				lock;
+};
+
+/*-------------------------------------------------------------------------*/
+
+const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
+struct platform_device	*tll_pdev;
+
+/*-------------------------------------------------------------------------*/
+
+static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 usbtll_read(void __iomem *base, u32 reg)
+{
+	return __raw_readl(base + reg);
+}
+
+static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
+{
+	__raw_writeb(val, base + reg);
+}
+
+static inline u8 usbtll_readb(void __iomem *base, u8 reg)
+{
+	return __raw_readb(base + reg);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
+{
+	switch (pmode) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * convert the port-mode enum to a value we can use in the FSLSMODE
+ * field of USBTLL_CHANNEL_CONF
+ */
+static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
+{
+	switch (mode) {
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
+	default:
+		pr_warn("Invalid port mode, using default\n");
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+	}
+}
+
+/**
+ * usbtll_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller.
+ */
+static int __devinit usbtll_omap_probe(struct platform_device *pdev)
+{
+	struct device				*dev =  &pdev->dev;
+	struct usbtll_omap_platform_data	*pdata = dev->platform_data;
+	void __iomem				*base;
+	struct resource				*res;
+	struct usbtll_omap			*tll;
+	unsigned				reg;
+	unsigned long				flags;
+	int					ret = 0;
+	int					i, ver, count;
+
+	dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
+
+	tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL);
+	if (!tll) {
+		dev_err(dev, "Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	spin_lock_init(&tll->lock);
+
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
+		tll->platdata.port_mode[i] = pdata->port_mode[i];
+
+	tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
+	if (IS_ERR(tll->usbtll_p1_fck)) {
+		ret = PTR_ERR(tll->usbtll_p1_fck);
+		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
+		goto err_tll;
+	}
+
+	tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
+	if (IS_ERR(tll->usbtll_p2_fck)) {
+		ret = PTR_ERR(tll->usbtll_p2_fck);
+		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
+		goto err_usbtll_p1_fck;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "usb tll get resource failed\n");
+		ret = -ENODEV;
+		goto err_usbtll_p2_fck;
+	}
+
+	base = ioremap(res->start, resource_size(res));
+	if (!base) {
+		dev_err(dev, "TLL ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_usbtll_p2_fck;
+	}
+
+	platform_set_drvdata(pdev, tll);
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	spin_lock_irqsave(&tll->lock, flags);
+
+	ver =  usbtll_read(base, OMAP_USBTLL_REVISION);
+	switch (ver) {
+	case OMAP_USBTLL_REV1:
+	case OMAP_USBTLL_REV2:
+		count = OMAP_TLL_CHANNEL_COUNT;
+		break;
+	case OMAP_USBTLL_REV3:
+		count = OMAP_REV2_TLL_CHANNEL_COUNT;
+		break;
+	default:
+		dev_err(dev, "TLL version failed\n");
+		ret = -ENODEV;
+		goto err_ioremap;
+	}
+
+	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+	    is_ehci_tll_mode(pdata->port_mode[1]) ||
+	    is_ehci_tll_mode(pdata->port_mode[2]) ||
+	    is_ohci_port(pdata->port_mode[0]) ||
+	    is_ohci_port(pdata->port_mode[1]) ||
+	    is_ohci_port(pdata->port_mode[2])) {
+
+		/* Program Common TLL register */
+		reg = usbtll_read(base, OMAP_TLL_SHARED_CONF);
+		reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
+			| OMAP_TLL_SHARED_CONF_USB_DIVRATION);
+		reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
+		reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
+
+		usbtll_write(base, OMAP_TLL_SHARED_CONF, reg);
+
+		/* Enable channels now */
+		for (i = 0; i < count; i++) {
+			reg = usbtll_read(base,	OMAP_TLL_CHANNEL_CONF(i));
+
+			if (is_ohci_port(pdata->port_mode[i])) {
+				reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
+				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
+				reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
+			} else if (pdata->port_mode[i] ==
+					OMAP_EHCI_PORT_MODE_TLL) {
+				/*
+				 * Disable AutoIdle, BitStuffing
+				 * and use SDR Mode
+				 */
+				reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
+					| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+					| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+			} else {
+				continue;
+			}
+			reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
+			usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg);
+
+			usbtll_writeb(base,
+				      OMAP_TLL_ULPI_SCRATCH_REGISTER(i),
+				      0xbe);
+		}
+	}
+
+err_ioremap:
+	spin_unlock_irqrestore(&tll->lock, flags);
+	iounmap(base);
+	pm_runtime_put_sync(dev);
+	tll_pdev = pdev;
+	if (!ret)
+		goto end;
+	pm_runtime_disable(dev);
+
+err_usbtll_p2_fck:
+	clk_put(tll->usbtll_p2_fck);
+
+err_usbtll_p1_fck:
+	clk_put(tll->usbtll_p1_fck);
+
+err_tll:
+	kfree(tll);
+
+end:
+	return ret;
+}
+
+/**
+ * usbtll_omap_remove - shutdown processing for UHH & TLL HCDs
+ * @pdev: USB Host Controller being removed
+ *
+ * Reverses the effect of usbtll_omap_probe().
+ */
+static int __devexit usbtll_omap_remove(struct platform_device *pdev)
+{
+	struct usbtll_omap *tll = platform_get_drvdata(pdev);
+
+	clk_put(tll->usbtll_p2_fck);
+	clk_put(tll->usbtll_p1_fck);
+	pm_runtime_disable(&pdev->dev);
+	kfree(tll);
+	return 0;
+}
+
+static int usbtll_runtime_resume(struct device *dev)
+{
+	struct usbtll_omap			*tll = dev_get_drvdata(dev);
+	struct usbtll_omap_platform_data	*pdata = &tll->platdata;
+	unsigned long				flags;
+
+	dev_dbg(dev, "usbtll_runtime_resume\n");
+
+	if (!pdata) {
+		dev_dbg(dev, "missing platform_data\n");
+		return  -ENODEV;
+	}
+
+	spin_lock_irqsave(&tll->lock, flags);
+
+	if (is_ehci_tll_mode(pdata->port_mode[0]))
+		clk_enable(tll->usbtll_p1_fck);
+
+	if (is_ehci_tll_mode(pdata->port_mode[1]))
+		clk_enable(tll->usbtll_p2_fck);
+
+	spin_unlock_irqrestore(&tll->lock, flags);
+
+	return 0;
+}
+
+static int usbtll_runtime_suspend(struct device *dev)
+{
+	struct usbtll_omap			*tll = dev_get_drvdata(dev);
+	struct usbtll_omap_platform_data	*pdata = &tll->platdata;
+	unsigned long				flags;
+
+	dev_dbg(dev, "usbtll_runtime_suspend\n");
+
+	if (!pdata) {
+		dev_dbg(dev, "missing platform_data\n");
+		return  -ENODEV;
+	}
+
+	spin_lock_irqsave(&tll->lock, flags);
+
+	if (is_ehci_tll_mode(pdata->port_mode[0]))
+		clk_disable(tll->usbtll_p1_fck);
+
+	if (is_ehci_tll_mode(pdata->port_mode[1]))
+		clk_disable(tll->usbtll_p2_fck);
+
+	spin_unlock_irqrestore(&tll->lock, flags);
+
+	return 0;
+}
+
+static const struct dev_pm_ops usbtllomap_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(usbtll_runtime_suspend,
+			   usbtll_runtime_resume,
+			   NULL)
+};
+
+static struct platform_driver usbtll_omap_driver = {
+	.driver = {
+		.name		= (char *)usbtll_driver_name,
+		.owner		= THIS_MODULE,
+		.pm		= &usbtllomap_dev_pm_ops,
+	},
+	.probe		= usbtll_omap_probe,
+	.remove		= __devexit_p(usbtll_omap_remove),
+};
+
+int omap_tll_enable(void)
+{
+	if (!tll_pdev) {
+		pr_err("missing omap usbhs tll platform_data\n");
+		return  -ENODEV;
+	}
+	return pm_runtime_get_sync(&tll_pdev->dev);
+}
+EXPORT_SYMBOL_GPL(omap_tll_enable);
+
+int omap_tll_disable(void)
+{
+	if (!tll_pdev) {
+		pr_err("missing omap usbhs tll platform_data\n");
+		return  -ENODEV;
+	}
+	return pm_runtime_put_sync(&tll_pdev->dev);
+}
+EXPORT_SYMBOL_GPL(omap_tll_disable);
+
+MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
+MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers");
+
+static int __init omap_usbtll_drvinit(void)
+{
+	return platform_driver_register(&usbtll_omap_driver);
+}
+
+/*
+ * init before usbhs core driver;
+ * The usbtll driver should be initialized before
+ * the usbhs core driver probe function is called.
+ */
+fs_initcall(omap_usbtll_drvinit);
+
+static void __exit omap_usbtll_drvexit(void)
+{
+	platform_driver_unregister(&usbtll_omap_driver);
+}
+module_exit(omap_usbtll_drvexit);

+ 77 - 72
drivers/mfd/palmas.c

@@ -23,60 +23,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/palmas.h>
 #include <linux/mfd/palmas.h>
-
-static const struct resource gpadc_resource[] = {
-	{
-		.name = "EOC_SW",
-		.start = PALMAS_GPADC_EOC_SW_IRQ,
-		.end = PALMAS_GPADC_EOC_SW_IRQ,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static const struct resource usb_resource[] = {
-	{
-		.name = "ID",
-		.start = PALMAS_ID_OTG_IRQ,
-		.end = PALMAS_ID_OTG_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "ID_WAKEUP",
-		.start = PALMAS_ID_IRQ,
-		.end = PALMAS_ID_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBUS",
-		.start = PALMAS_VBUS_OTG_IRQ,
-		.end = PALMAS_VBUS_OTG_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBUS_WAKEUP",
-		.start = PALMAS_VBUS_IRQ,
-		.end = PALMAS_VBUS_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static const struct resource rtc_resource[] = {
-	{
-		.name = "RTC_ALARM",
-		.start = PALMAS_RTC_ALARM_IRQ,
-		.end = PALMAS_RTC_ALARM_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static const struct resource pwron_resource[] = {
-	{
-		.name = "PWRON_BUTTON",
-		.start = PALMAS_PWRON_IRQ,
-		.end = PALMAS_PWRON_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
+#include <linux/of_platform.h>
 
 
 enum palmas_ids {
 enum palmas_ids {
 	PALMAS_PMIC_ID,
 	PALMAS_PMIC_ID,
@@ -111,20 +58,14 @@ static const struct mfd_cell palmas_children[] = {
 	},
 	},
 	{
 	{
 		.name = "palmas-rtc",
 		.name = "palmas-rtc",
-		.num_resources = ARRAY_SIZE(rtc_resource),
-		.resources = rtc_resource,
 		.id = PALMAS_RTC_ID,
 		.id = PALMAS_RTC_ID,
 	},
 	},
 	{
 	{
 		.name = "palmas-pwrbutton",
 		.name = "palmas-pwrbutton",
-		.num_resources = ARRAY_SIZE(pwron_resource),
-		.resources = pwron_resource,
 		.id = PALMAS_PWRBUTTON_ID,
 		.id = PALMAS_PWRBUTTON_ID,
 	},
 	},
 	{
 	{
 		.name = "palmas-gpadc",
 		.name = "palmas-gpadc",
-		.num_resources = ARRAY_SIZE(gpadc_resource),
-		.resources = gpadc_resource,
 		.id = PALMAS_GPADC_ID,
 		.id = PALMAS_GPADC_ID,
 	},
 	},
 	{
 	{
@@ -141,8 +82,6 @@ static const struct mfd_cell palmas_children[] = {
 	},
 	},
 	{
 	{
 		.name = "palmas-usb",
 		.name = "palmas-usb",
-		.num_resources = ARRAY_SIZE(usb_resource),
-		.resources = usb_resource,
 		.id = PALMAS_USB_ID,
 		.id = PALMAS_USB_ID,
 	}
 	}
 };
 };
@@ -308,17 +247,56 @@ static struct regmap_irq_chip palmas_irq_chip = {
 			PALMAS_INT1_MASK),
 			PALMAS_INT1_MASK),
 };
 };
 
 
+static void __devinit palmas_dt_to_pdata(struct device_node *node,
+		struct palmas_platform_data *pdata)
+{
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "ti,mux_pad1", &prop);
+	if (!ret) {
+		pdata->mux_from_pdata = 1;
+		pdata->pad1 = prop;
+	}
+
+	ret = of_property_read_u32(node, "ti,mux_pad2", &prop);
+	if (!ret) {
+		pdata->mux_from_pdata = 1;
+		pdata->pad2 = prop;
+	}
+
+	/* The default for this register is all masked */
+	ret = of_property_read_u32(node, "ti,power_ctrl", &prop);
+	if (!ret)
+		pdata->power_ctrl = prop;
+	else
+		pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK |
+					PALMAS_POWER_CTRL_ENABLE1_MASK |
+					PALMAS_POWER_CTRL_ENABLE2_MASK;
+}
+
 static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 			    const struct i2c_device_id *id)
 {
 {
 	struct palmas *palmas;
 	struct palmas *palmas;
 	struct palmas_platform_data *pdata;
 	struct palmas_platform_data *pdata;
+	struct device_node *node = i2c->dev.of_node;
 	int ret = 0, i;
 	int ret = 0, i;
 	unsigned int reg, addr;
 	unsigned int reg, addr;
 	int slave;
 	int slave;
 	struct mfd_cell *children;
 	struct mfd_cell *children;
 
 
 	pdata = dev_get_platdata(&i2c->dev);
 	pdata = dev_get_platdata(&i2c->dev);
+
+	if (node && !pdata) {
+		pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+
+		if (!pdata)
+			return -ENOMEM;
+
+		palmas_dt_to_pdata(node, pdata);
+	}
+
 	if (!pdata)
 	if (!pdata)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -364,7 +342,7 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 	regmap_write(palmas->regmap[slave], addr, reg);
 	regmap_write(palmas->regmap[slave], addr, reg);
 
 
 	ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
 	ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
-			IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip,
+			IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
 			&palmas->irq_data);
 			&palmas->irq_data);
 	if (ret < 0)
 	if (ret < 0)
 		goto err;
 		goto err;
@@ -377,11 +355,11 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 		reg = pdata->pad1;
 		reg = pdata->pad1;
 		ret = regmap_write(palmas->regmap[slave], addr, reg);
 		ret = regmap_write(palmas->regmap[slave], addr, reg);
 		if (ret)
 		if (ret)
-			goto err;
+			goto err_irq;
 	} else {
 	} else {
 		ret = regmap_read(palmas->regmap[slave], addr, &reg);
 		ret = regmap_read(palmas->regmap[slave], addr, &reg);
 		if (ret)
 		if (ret)
-			goto err;
+			goto err_irq;
 	}
 	}
 
 
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0))
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0))
@@ -412,11 +390,11 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 		reg = pdata->pad2;
 		reg = pdata->pad2;
 		ret = regmap_write(palmas->regmap[slave], addr, reg);
 		ret = regmap_write(palmas->regmap[slave], addr, reg);
 		if (ret)
 		if (ret)
-			goto err;
+			goto err_irq;
 	} else {
 	} else {
 		ret = regmap_read(palmas->regmap[slave], addr, &reg);
 		ret = regmap_read(palmas->regmap[slave], addr, &reg);
 		if (ret)
 		if (ret)
-			goto err;
+			goto err_irq;
 	}
 	}
 
 
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4))
 	if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4))
@@ -439,18 +417,43 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 
 
 	ret = regmap_write(palmas->regmap[slave], addr, reg);
 	ret = regmap_write(palmas->regmap[slave], addr, reg);
 	if (ret)
 	if (ret)
-		goto err;
+		goto err_irq;
+
+	/*
+	 * If we are probing with DT do this the DT way and return here
+	 * otherwise continue and add devices using mfd helpers.
+	 */
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
+		if (ret < 0)
+			goto err_irq;
+		else
+			return ret;
+	}
 
 
 	children = kmemdup(palmas_children, sizeof(palmas_children),
 	children = kmemdup(palmas_children, sizeof(palmas_children),
 			   GFP_KERNEL);
 			   GFP_KERNEL);
 	if (!children) {
 	if (!children) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		goto err;
+		goto err_irq;
 	}
 	}
 
 
 	children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
 	children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
 	children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
 	children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
 
 
+	children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata;
+	children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata);
+
+	children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata;
+	children[PALMAS_RESOURCE_ID].pdata_size =
+			sizeof(*pdata->resource_pdata);
+
+	children[PALMAS_USB_ID].platform_data = pdata->usb_pdata;
+	children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata);
+
+	children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata;
+	children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata);
+
 	ret = mfd_add_devices(palmas->dev, -1,
 	ret = mfd_add_devices(palmas->dev, -1,
 			      children, ARRAY_SIZE(palmas_children),
 			      children, ARRAY_SIZE(palmas_children),
 			      NULL, regmap_irq_chip_get_base(palmas->irq_data),
 			      NULL, regmap_irq_chip_get_base(palmas->irq_data),
@@ -458,13 +461,15 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 	kfree(children);
 	kfree(children);
 
 
 	if (ret < 0)
 	if (ret < 0)
-		goto err;
+		goto err_devices;
 
 
 	return ret;
 	return ret;
 
 
-err:
+err_devices:
 	mfd_remove_devices(palmas->dev);
 	mfd_remove_devices(palmas->dev);
-	kfree(palmas);
+err_irq:
+	regmap_del_irq_chip(palmas->irq, palmas->irq_data);
+err:
 	return ret;
 	return ret;
 }
 }
 
 

+ 1 - 1
drivers/mfd/rc5t583-irq.c

@@ -255,7 +255,7 @@ static irqreturn_t rc5t583_irq(int irq, void *data)
 {
 {
 	struct rc5t583 *rc5t583 = data;
 	struct rc5t583 *rc5t583 = data;
 	uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
 	uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
-	uint8_t master_int;
+	uint8_t master_int = 0;
 	int i;
 	int i;
 	int ret;
 	int ret;
 	unsigned int rtc_int_sts = 0;
 	unsigned int rtc_int_sts = 0;

+ 1 - 1
drivers/mfd/rc5t583.c

@@ -85,7 +85,7 @@ static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
 	int id, int ext_pwr, int slots)
 	int id, int ext_pwr, int slots)
 {
 {
 	int ret;
 	int ret;
-	uint8_t sleepseq_val;
+	uint8_t sleepseq_val = 0;
 	unsigned int en_bit;
 	unsigned int en_bit;
 	unsigned int slot_bit;
 	unsigned int slot_bit;
 
 

+ 113 - 0
drivers/mfd/smsc-ece1099.c

@@ -0,0 +1,113 @@
+/*
+ * TI SMSC MFD Driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.com>
+ *
+ *  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;  GPL v2.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/smsc.h>
+#include <linux/of_platform.h>
+
+static struct regmap_config smsc_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = SMSC_VEN_ID_H,
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int smsc_i2c_probe(struct i2c_client *i2c,
+			const struct i2c_device_id *id)
+{
+	struct smsc *smsc;
+	int devid, rev, venid_l, venid_h;
+	int ret = 0;
+
+	smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
+				GFP_KERNEL);
+	if (!smsc) {
+		dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
+	if (IS_ERR(smsc->regmap)) {
+		ret = PTR_ERR(smsc->regmap);
+		goto err;
+	}
+
+	i2c_set_clientdata(i2c, smsc);
+	smsc->dev = &i2c->dev;
+
+#ifdef CONFIG_OF
+	of_property_read_u32(i2c->dev.of_node, "clock", &smsc->clk);
+#endif
+
+	regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
+	regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
+	regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
+	regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
+
+	dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
+		devid, rev, (venid_h << 8) | venid_l);
+
+	ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
+	if (ret)
+		goto err;
+
+#ifdef CONFIG_OF
+	if (i2c->dev.of_node)
+		ret = of_platform_populate(i2c->dev.of_node,
+					   NULL, NULL, &i2c->dev);
+#endif
+
+err:
+	return ret;
+}
+
+static int smsc_i2c_remove(struct i2c_client *i2c)
+{
+	struct smsc *smsc = i2c_get_clientdata(i2c);
+
+	mfd_remove_devices(smsc->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id smsc_i2c_id[] = {
+	{ "smscece1099", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, smsc_i2c_id);
+
+static struct i2c_driver smsc_i2c_driver = {
+	.driver = {
+		   .name = "smsc",
+		   .owner = THIS_MODULE,
+	},
+	.probe = smsc_i2c_probe,
+	.remove = smsc_i2c_remove,
+	.id_table = smsc_i2c_id,
+};
+
+module_i2c_driver(smsc_i2c_driver);
+
+MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
+MODULE_DESCRIPTION("SMSC chip multi-function driver");
+MODULE_LICENSE("GPL v2");

+ 176 - 0
drivers/mfd/syscon.c

@@ -0,0 +1,176 @@
+/*
+ * System Control Driver
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.org>
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct platform_driver syscon_driver;
+
+struct syscon {
+	struct device *dev;
+	void __iomem *base;
+	struct regmap *regmap;
+};
+
+static int syscon_match(struct device *dev, void *data)
+{
+	struct syscon *syscon = dev_get_drvdata(dev);
+	struct device_node *dn = data;
+
+	return (syscon->dev->of_node == dn) ? 1 : 0;
+}
+
+struct regmap *syscon_node_to_regmap(struct device_node *np)
+{
+	struct syscon *syscon;
+	struct device *dev;
+
+	dev = driver_find_device(&syscon_driver.driver, NULL, np,
+				 syscon_match);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	syscon = dev_get_drvdata(dev);
+
+	return syscon->regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
+
+struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
+{
+	struct device_node *syscon_np;
+	struct regmap *regmap;
+
+	syscon_np = of_find_compatible_node(NULL, NULL, s);
+	if (!syscon_np)
+		return ERR_PTR(-ENODEV);
+
+	regmap = syscon_node_to_regmap(syscon_np);
+	of_node_put(syscon_np);
+
+	return regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
+
+struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
+					const char *property)
+{
+	struct device_node *syscon_np;
+	struct regmap *regmap;
+
+	syscon_np = of_parse_phandle(np, property, 0);
+	if (!syscon_np)
+		return ERR_PTR(-ENODEV);
+
+	regmap = syscon_node_to_regmap(syscon_np);
+	of_node_put(syscon_np);
+
+	return regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
+
+static const struct of_device_id of_syscon_match[] = {
+	{ .compatible = "syscon", },
+	{ },
+};
+
+static struct regmap_config syscon_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int __devinit syscon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct syscon *syscon;
+	struct resource res;
+	int ret;
+
+	if (!np)
+		return -ENOENT;
+
+	syscon = devm_kzalloc(dev, sizeof(struct syscon),
+			    GFP_KERNEL);
+	if (!syscon)
+		return -ENOMEM;
+
+	syscon->base = of_iomap(np, 0);
+	if (!syscon->base)
+		return -EADDRNOTAVAIL;
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return ret;
+
+	syscon_regmap_config.max_register = res.end - res.start - 3;
+	syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
+					&syscon_regmap_config);
+	if (IS_ERR(syscon->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(syscon->regmap);
+	}
+
+	syscon->dev = dev;
+	platform_set_drvdata(pdev, syscon);
+
+	dev_info(dev, "syscon regmap start 0x%x end 0x%x registered\n",
+		res.start, res.end);
+
+	return 0;
+}
+
+static int __devexit syscon_remove(struct platform_device *pdev)
+{
+	struct syscon *syscon;
+
+	syscon = platform_get_drvdata(pdev);
+	iounmap(syscon->base);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver syscon_driver = {
+	.driver = {
+		.name = "syscon",
+		.owner = THIS_MODULE,
+		.of_match_table = of_syscon_match,
+	},
+	.probe		= syscon_probe,
+	.remove		= __devexit_p(syscon_remove),
+};
+
+static int __init syscon_init(void)
+{
+	return platform_driver_register(&syscon_driver);
+}
+postcore_initcall(syscon_init);
+
+static void __exit syscon_exit(void)
+{
+	platform_driver_unregister(&syscon_driver);
+}
+module_exit(syscon_exit);
+
+MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
+MODULE_DESCRIPTION("System Control driver");
+MODULE_LICENSE("GPL v2");

+ 85 - 27
drivers/mfd/tc3589x.c

@@ -9,8 +9,10 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tc3589x.h>
 #include <linux/mfd/tc3589x.h>
 
 
@@ -145,6 +147,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = {
 		.name		= "tc3589x-gpio",
 		.name		= "tc3589x-gpio",
 		.num_resources	= ARRAY_SIZE(gpio_resources),
 		.num_resources	= ARRAY_SIZE(gpio_resources),
 		.resources	= &gpio_resources[0],
 		.resources	= &gpio_resources[0],
+		.of_compatible	= "tc3589x-gpio",
 	},
 	},
 };
 };
 
 
@@ -153,6 +156,7 @@ static struct mfd_cell tc3589x_dev_keypad[] = {
 		.name           = "tc3589x-keypad",
 		.name           = "tc3589x-keypad",
 		.num_resources  = ARRAY_SIZE(keypad_resources),
 		.num_resources  = ARRAY_SIZE(keypad_resources),
 		.resources      = &keypad_resources[0],
 		.resources      = &keypad_resources[0],
+		.of_compatible	= "tc3589x-keypad",
 	},
 	},
 };
 };
 
 
@@ -168,8 +172,9 @@ again:
 
 
 	while (status) {
 	while (status) {
 		int bit = __ffs(status);
 		int bit = __ffs(status);
+		int virq = irq_create_mapping(tc3589x->domain, bit);
 
 
-		handle_nested_irq(tc3589x->irq_base + bit);
+		handle_nested_irq(virq);
 		status &= ~(1 << bit);
 		status &= ~(1 << bit);
 	}
 	}
 
 
@@ -186,38 +191,60 @@ again:
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static int tc3589x_irq_init(struct tc3589x *tc3589x)
+static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hwirq)
 {
 {
-	int base = tc3589x->irq_base;
-	int irq;
+	struct tc3589x *tc3589x = d->host_data;
 
 
-	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
-		irq_set_chip_data(irq, tc3589x);
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-					 handle_edge_irq);
-		irq_set_nested_thread(irq, 1);
+	irq_set_chip_data(virq, tc3589x);
+	irq_set_chip_and_handler(virq, &dummy_irq_chip,
+				handle_edge_irq);
+	irq_set_nested_thread(virq, 1);
 #ifdef CONFIG_ARM
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
+	set_irq_flags(virq, IRQF_VALID);
 #else
 #else
-		irq_set_noprobe(irq);
+	irq_set_noprobe(virq);
 #endif
 #endif
-	}
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static void tc3589x_irq_remove(struct tc3589x *tc3589x)
+static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
 {
 {
-	int base = tc3589x->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
 #ifdef CONFIG_ARM
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
+	set_irq_flags(virq, 0);
 #endif
 #endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
+	irq_set_chip_and_handler(virq, NULL, NULL);
+	irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops tc3589x_irq_ops = {
+        .map    = tc3589x_irq_map,
+	.unmap  = tc3589x_irq_unmap,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
+{
+	int base = tc3589x->irq_base;
+
+	if (base) {
+		tc3589x->domain = irq_domain_add_legacy(
+			NULL, TC3589x_NR_INTERNAL_IRQS, base,
+			0, &tc3589x_irq_ops, tc3589x);
+	}
+	else {
+		tc3589x->domain = irq_domain_add_linear(
+			np, TC3589x_NR_INTERNAL_IRQS,
+			&tc3589x_irq_ops, tc3589x);
 	}
 	}
+
+	if (!tc3589x->domain) {
+		dev_err(tc3589x->dev, "Failed to create irqdomain\n");
+		return -ENOSYS;
+	}
+
+	return 0;
 }
 }
 
 
 static int tc3589x_chip_init(struct tc3589x *tc3589x)
 static int tc3589x_chip_init(struct tc3589x *tc3589x)
@@ -263,7 +290,7 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
 	if (blocks & TC3589x_BLOCK_GPIO) {
 	if (blocks & TC3589x_BLOCK_GPIO) {
 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
 				      ARRAY_SIZE(tc3589x_dev_gpio), NULL,
 				      ARRAY_SIZE(tc3589x_dev_gpio), NULL,
-				      tc3589x->irq_base, NULL);
+				      tc3589x->irq_base, tc3589x->domain);
 		if (ret) {
 		if (ret) {
 			dev_err(tc3589x->dev, "failed to add gpio child\n");
 			dev_err(tc3589x->dev, "failed to add gpio child\n");
 			return ret;
 			return ret;
@@ -274,7 +301,7 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
 	if (blocks & TC3589x_BLOCK_KEYPAD) {
 	if (blocks & TC3589x_BLOCK_KEYPAD) {
 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
 				      ARRAY_SIZE(tc3589x_dev_keypad), NULL,
 				      ARRAY_SIZE(tc3589x_dev_keypad), NULL,
-				      tc3589x->irq_base, NULL);
+				      tc3589x->irq_base, tc3589x->domain);
 		if (ret) {
 		if (ret) {
 			dev_err(tc3589x->dev, "failed to keypad child\n");
 			dev_err(tc3589x->dev, "failed to keypad child\n");
 			return ret;
 			return ret;
@@ -285,13 +312,47 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
 	return ret;
 	return ret;
 }
 }
 
 
+static int tc3589x_of_probe(struct device_node *np,
+			struct tc3589x_platform_data *pdata)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (!strcmp(child->name, "tc3589x_gpio")) {
+			pdata->block |= TC3589x_BLOCK_GPIO;
+		}
+		if (!strcmp(child->name, "tc3589x_keypad")) {
+			pdata->block |= TC3589x_BLOCK_KEYPAD;
+		}
+	}
+
+	return 0;
+}
+
 static int __devinit tc3589x_probe(struct i2c_client *i2c,
 static int __devinit tc3589x_probe(struct i2c_client *i2c,
 				   const struct i2c_device_id *id)
 				   const struct i2c_device_id *id)
 {
 {
 	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
 	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+	struct device_node *np = i2c->dev.of_node;
 	struct tc3589x *tc3589x;
 	struct tc3589x *tc3589x;
 	int ret;
 	int ret;
 
 
+	if (!pdata) {
+		if (np) {
+			pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+			if (!pdata)
+				return -ENOMEM;
+
+			ret = tc3589x_of_probe(np, pdata);
+			if (ret)
+				return ret;
+		}
+		else {
+			dev_err(&i2c->dev, "No platform data or DT found\n");
+			return -EINVAL;
+		}
+	}
+
 	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
 	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
 				     | I2C_FUNC_SMBUS_I2C_BLOCK))
 				     | I2C_FUNC_SMBUS_I2C_BLOCK))
 		return -EIO;
 		return -EIO;
@@ -314,7 +375,7 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
 	if (ret)
 	if (ret)
 		goto out_free;
 		goto out_free;
 
 
-	ret = tc3589x_irq_init(tc3589x);
+	ret = tc3589x_irq_init(tc3589x, np);
 	if (ret)
 	if (ret)
 		goto out_free;
 		goto out_free;
 
 
@@ -323,7 +384,7 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
 				   "tc3589x", tc3589x);
 				   "tc3589x", tc3589x);
 	if (ret) {
 	if (ret) {
 		dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
 		dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
-		goto out_removeirq;
+		goto out_free;
 	}
 	}
 
 
 	ret = tc3589x_device_init(tc3589x);
 	ret = tc3589x_device_init(tc3589x);
@@ -336,8 +397,6 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
 
 
 out_freeirq:
 out_freeirq:
 	free_irq(tc3589x->i2c->irq, tc3589x);
 	free_irq(tc3589x->i2c->irq, tc3589x);
-out_removeirq:
-	tc3589x_irq_remove(tc3589x);
 out_free:
 out_free:
 	kfree(tc3589x);
 	kfree(tc3589x);
 	return ret;
 	return ret;
@@ -350,7 +409,6 @@ static int __devexit tc3589x_remove(struct i2c_client *client)
 	mfd_remove_devices(tc3589x->dev);
 	mfd_remove_devices(tc3589x->dev);
 
 
 	free_irq(tc3589x->i2c->irq, tc3589x);
 	free_irq(tc3589x->i2c->irq, tc3589x);
-	tc3589x_irq_remove(tc3589x);
 
 
 	kfree(tc3589x);
 	kfree(tc3589x);
 
 

+ 1 - 1
drivers/mfd/tps65090.c

@@ -236,7 +236,7 @@ static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
 
 
 static bool is_volatile_reg(struct device *dev, unsigned int reg)
 static bool is_volatile_reg(struct device *dev, unsigned int reg)
 {
 {
-	if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS))
+	if (reg == TPS65090_INT_STS)
 		return true;
 		return true;
 	else
 	else
 		return false;
 		return false;

+ 3 - 0
drivers/mfd/tps65217.c

@@ -34,6 +34,9 @@ static struct mfd_cell tps65217s[] = {
 	{
 	{
 		.name = "tps65217-pmic",
 		.name = "tps65217-pmic",
 	},
 	},
+	{
+		.name = "tps65217-bl",
+	},
 };
 };
 
 
 /**
 /**

+ 19 - 0
drivers/mfd/tps6586x.c

@@ -30,6 +30,10 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
 #include <linux/mfd/tps6586x.h>
 
 
+#define TPS6586X_SUPPLYENE	0x14
+#define EXITSLREQ_BIT		BIT(1)
+#define SLEEP_MODE_BIT		BIT(3)
+
 /* interrupt control registers */
 /* interrupt control registers */
 #define TPS6586X_INT_ACK1	0xb5
 #define TPS6586X_INT_ACK1	0xb5
 #define TPS6586X_INT_ACK2	0xb6
 #define TPS6586X_INT_ACK2	0xb6
@@ -422,6 +426,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
 	pdata->subdevs = devs;
 	pdata->subdevs = devs;
 	pdata->gpio_base = -1;
 	pdata->gpio_base = -1;
 	pdata->irq_base = -1;
 	pdata->irq_base = -1;
+	pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
 
 
 	return pdata;
 	return pdata;
 }
 }
@@ -454,6 +459,15 @@ static const struct regmap_config tps6586x_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 	.cache_type = REGCACHE_RBTREE,
 };
 };
 
 
+static struct device *tps6586x_dev;
+static void tps6586x_power_off(void)
+{
+	if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
+		return;
+
+	tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+}
+
 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 					const struct i2c_device_id *id)
 {
 {
@@ -519,6 +533,11 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
 		goto err_add_devs;
 		goto err_add_devs;
 	}
 	}
 
 
+	if (pdata->pm_off && !pm_power_off) {
+		tps6586x_dev = &client->dev;
+		pm_power_off = tps6586x_power_off;
+	}
+
 	return 0;
 	return 0;
 
 
 err_add_devs:
 err_add_devs:

+ 32 - 0
drivers/mfd/tps65910.c

@@ -24,6 +24,14 @@
 #include <linux/mfd/tps65910.h>
 #include <linux/mfd/tps65910.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
 
 
+static struct resource rtc_resources[] = {
+	{
+		.start  = TPS65910_IRQ_RTC_ALARM,
+		.end    = TPS65910_IRQ_RTC_ALARM,
+		.flags  = IORESOURCE_IRQ,
+	}
+};
+
 static struct mfd_cell tps65910s[] = {
 static struct mfd_cell tps65910s[] = {
 	{
 	{
 		.name = "tps65910-gpio",
 		.name = "tps65910-gpio",
@@ -33,6 +41,8 @@ static struct mfd_cell tps65910s[] = {
 	},
 	},
 	{
 	{
 		.name = "tps65910-rtc",
 		.name = "tps65910-rtc",
+		.num_resources = ARRAY_SIZE(rtc_resources),
+		.resources = &rtc_resources[0],
 	},
 	},
 	{
 	{
 		.name = "tps65910-power",
 		.name = "tps65910-power",
@@ -198,6 +208,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
 
 
 	board_info->irq = client->irq;
 	board_info->irq = client->irq;
 	board_info->irq_base = -1;
 	board_info->irq_base = -1;
+	board_info->pm_off = of_property_read_bool(np,
+			"ti,system-power-controller");
 
 
 	return board_info;
 	return board_info;
 }
 }
@@ -210,6 +222,21 @@ struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
 }
 }
 #endif
 #endif
 
 
+static struct i2c_client *tps65910_i2c_client;
+static void tps65910_power_off(void)
+{
+	struct tps65910 *tps65910;
+
+	tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev);
+
+	if (tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
+			DEVCTRL_PWR_OFF_MASK) < 0)
+		return;
+
+	tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
+			DEVCTRL_DEV_ON_MASK);
+}
+
 static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 					const struct i2c_device_id *id)
 					const struct i2c_device_id *id)
 {
 {
@@ -267,6 +294,11 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 	tps65910_ck32k_init(tps65910, pmic_plat_data);
 	tps65910_ck32k_init(tps65910, pmic_plat_data);
 	tps65910_sleepinit(tps65910, pmic_plat_data);
 	tps65910_sleepinit(tps65910, pmic_plat_data);
 
 
+	if (pmic_plat_data->pm_off && !pm_power_off) {
+		tps65910_i2c_client = i2c;
+		pm_power_off = tps65910_power_off;
+	}
+
 	return ret;
 	return ret;
 }
 }
 
 

+ 64 - 92
drivers/mfd/twl-core.c

@@ -63,70 +63,6 @@
 
 
 #define DRIVER_NAME			"twl"
 #define DRIVER_NAME			"twl"
 
 
-#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
-#define twl_has_keypad()	true
-#else
-#define twl_has_keypad()	false
-#endif
-
-#if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
-#define twl_has_gpio()	true
-#else
-#define twl_has_gpio()	false
-#endif
-
-#if defined(CONFIG_REGULATOR_TWL4030) \
-	|| defined(CONFIG_REGULATOR_TWL4030_MODULE)
-#define twl_has_regulator()	true
-#else
-#define twl_has_regulator()	false
-#endif
-
-#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
-#define twl_has_madc()	true
-#else
-#define twl_has_madc()	false
-#endif
-
-#ifdef CONFIG_TWL4030_POWER
-#define twl_has_power()        true
-#else
-#define twl_has_power()        false
-#endif
-
-#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
-#define twl_has_rtc()	true
-#else
-#define twl_has_rtc()	false
-#endif
-
-#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) ||\
-	defined(CONFIG_TWL6030_USB) || defined(CONFIG_TWL6030_USB_MODULE)
-#define twl_has_usb()	true
-#else
-#define twl_has_usb()	false
-#endif
-
-#if defined(CONFIG_TWL4030_WATCHDOG) || \
-	defined(CONFIG_TWL4030_WATCHDOG_MODULE)
-#define twl_has_watchdog()        true
-#else
-#define twl_has_watchdog()        false
-#endif
-
-#if defined(CONFIG_MFD_TWL4030_AUDIO) || \
-	defined(CONFIG_MFD_TWL4030_AUDIO_MODULE)
-#define twl_has_codec()	true
-#else
-#define twl_has_codec()	false
-#endif
-
-#if defined(CONFIG_CHARGER_TWL4030) || defined(CONFIG_CHARGER_TWL4030_MODULE)
-#define twl_has_bci()	true
-#else
-#define twl_has_bci()	false
-#endif
-
 /* Triton Core internal information (BEGIN) */
 /* Triton Core internal information (BEGIN) */
 
 
 /* Last - for index max*/
 /* Last - for index max*/
@@ -134,13 +70,6 @@
 
 
 #define TWL_NUM_SLAVES		4
 #define TWL_NUM_SLAVES		4
 
 
-#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
-	|| defined(CONFIG_INPUT_TWL4030_PWRBUTTON_MODULE)
-#define twl_has_pwrbutton()	true
-#else
-#define twl_has_pwrbutton()	false
-#endif
-
 #define SUB_CHIP_ID0 0
 #define SUB_CHIP_ID0 0
 #define SUB_CHIP_ID1 1
 #define SUB_CHIP_ID1 1
 #define SUB_CHIP_ID2 2
 #define SUB_CHIP_ID2 2
@@ -552,6 +481,38 @@ int twl_get_version(void)
 }
 }
 EXPORT_SYMBOL_GPL(twl_get_version);
 EXPORT_SYMBOL_GPL(twl_get_version);
 
 
+/**
+ * twl_get_hfclk_rate - API to get TWL external HFCLK clock rate.
+ *
+ * Api to get the TWL HFCLK rate based on BOOT_CFG register.
+ */
+int twl_get_hfclk_rate(void)
+{
+	u8 ctrl;
+	int rate;
+
+	twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &ctrl, R_CFG_BOOT);
+
+	switch (ctrl & 0x3) {
+	case HFCLK_FREQ_19p2_MHZ:
+		rate = 19200000;
+		break;
+	case HFCLK_FREQ_26_MHZ:
+		rate = 26000000;
+		break;
+	case HFCLK_FREQ_38p4_MHZ:
+		rate = 38400000;
+		break;
+	default:
+		pr_err("TWL4030: HFCLK is not configured\n");
+		rate = -EINVAL;
+		break;
+	}
+
+	return rate;
+}
+EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
+
 static struct device *
 static struct device *
 add_numbered_child(unsigned chip, const char *name, int num,
 add_numbered_child(unsigned chip, const char *name, int num,
 		void *pdata, unsigned pdata_len,
 		void *pdata, unsigned pdata_len,
@@ -669,7 +630,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	struct device	*child;
 	struct device	*child;
 	unsigned sub_chip_id;
 	unsigned sub_chip_id;
 
 
-	if (twl_has_gpio() && pdata->gpio) {
+	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
 		child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
 		child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
 				pdata->gpio, sizeof(*pdata->gpio),
 				pdata->gpio, sizeof(*pdata->gpio),
 				false, irq_base + GPIO_INTR_OFFSET, 0);
 				false, irq_base + GPIO_INTR_OFFSET, 0);
@@ -677,7 +638,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_keypad() && pdata->keypad) {
+	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
 		child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
 		child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
 				pdata->keypad, sizeof(*pdata->keypad),
 				pdata->keypad, sizeof(*pdata->keypad),
 				true, irq_base + KEYPAD_INTR_OFFSET, 0);
 				true, irq_base + KEYPAD_INTR_OFFSET, 0);
@@ -685,7 +646,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_madc() && pdata->madc) {
+	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc) {
 		child = add_child(2, "twl4030_madc",
 		child = add_child(2, "twl4030_madc",
 				pdata->madc, sizeof(*pdata->madc),
 				pdata->madc, sizeof(*pdata->madc),
 				true, irq_base + MADC_INTR_OFFSET, 0);
 				true, irq_base + MADC_INTR_OFFSET, 0);
@@ -693,7 +654,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_rtc()) {
+	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
 		/*
 		/*
 		 * REVISIT platform_data here currently might expose the
 		 * REVISIT platform_data here currently might expose the
 		 * "msecure" line ... but for now we just expect board
 		 * "msecure" line ... but for now we just expect board
@@ -709,7 +670,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_usb() && pdata->usb && twl_class_is_4030()) {
+	if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
+		child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+				  false, 0, 0);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+
+	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
+	    twl_class_is_4030()) {
 
 
 		static struct regulator_consumer_supply usb1v5 = {
 		static struct regulator_consumer_supply usb1v5 = {
 			.supply =	"usb1v5",
 			.supply =	"usb1v5",
@@ -723,7 +692,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 		};
 		};
 
 
 	/* First add the regulators so that they can be used by transceiver */
 	/* First add the regulators so that they can be used by transceiver */
-		if (twl_has_regulator()) {
+		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
 			/* this is a template that gets copied */
 			/* this is a template that gets copied */
 			struct regulator_init_data usb_fixed = {
 			struct regulator_init_data usb_fixed = {
 				.constraints.valid_modes_mask =
 				.constraints.valid_modes_mask =
@@ -765,18 +734,19 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 
 
 		/* we need to connect regulators to this transceiver */
 		/* we need to connect regulators to this transceiver */
-		if (twl_has_regulator() && child) {
+		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
 			usb1v5.dev_name = dev_name(child);
 			usb1v5.dev_name = dev_name(child);
 			usb1v8.dev_name = dev_name(child);
 			usb1v8.dev_name = dev_name(child);
 			usb3v1[0].dev_name = dev_name(child);
 			usb3v1[0].dev_name = dev_name(child);
 		}
 		}
 	}
 	}
-	if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
+	if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
+	    twl_class_is_6030()) {
 
 
 		static struct regulator_consumer_supply usb3v3;
 		static struct regulator_consumer_supply usb3v3;
 		int regulator;
 		int regulator;
 
 
-		if (twl_has_regulator()) {
+		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
 			/* this is a template that gets copied */
 			/* this is a template that gets copied */
 			struct regulator_init_data usb_fixed = {
 			struct regulator_init_data usb_fixed = {
 				.constraints.valid_modes_mask =
 				.constraints.valid_modes_mask =
@@ -813,9 +783,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 		if (IS_ERR(child))
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 		/* we need to connect regulators to this transceiver */
 		/* we need to connect regulators to this transceiver */
-		if (twl_has_regulator() && child)
+		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
 			usb3v3.dev_name = dev_name(child);
 			usb3v3.dev_name = dev_name(child);
-	} else if (twl_has_regulator() && twl_class_is_6030()) {
+	} else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
+		   twl_class_is_6030()) {
 		if (features & TWL6025_SUBCLASS)
 		if (features & TWL6025_SUBCLASS)
 			child = add_regulator(TWL6025_REG_LDOUSB,
 			child = add_regulator(TWL6025_REG_LDOUSB,
 						pdata->ldousb, features);
 						pdata->ldousb, features);
@@ -827,20 +798,21 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 					return PTR_ERR(child);
 					return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_watchdog() && twl_class_is_4030()) {
+	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
 		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
 		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
 		if (IS_ERR(child))
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_pwrbutton() && twl_class_is_4030()) {
+	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
 		child = add_child(1, "twl4030_pwrbutton",
 		child = add_child(1, "twl4030_pwrbutton",
 				NULL, 0, true, irq_base + 8 + 0, 0);
 				NULL, 0, true, irq_base + 8 + 0, 0);
 		if (IS_ERR(child))
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 			return PTR_ERR(child);
 	}
 	}
 
 
-	if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
+	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
+	    twl_class_is_4030()) {
 		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
 		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
 		child = add_child(sub_chip_id, "twl4030-audio",
 		child = add_child(sub_chip_id, "twl4030-audio",
 				pdata->audio, sizeof(*pdata->audio),
 				pdata->audio, sizeof(*pdata->audio),
@@ -850,7 +822,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 	}
 
 
 	/* twl4030 regulators */
 	/* twl4030 regulators */
-	if (twl_has_regulator() && twl_class_is_4030()) {
+	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
 		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
 		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
 					features);
 					features);
 		if (IS_ERR(child))
 		if (IS_ERR(child))
@@ -905,7 +877,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 	}
 
 
 	/* maybe add LDOs that are omitted on cost-reduced parts */
 	/* maybe add LDOs that are omitted on cost-reduced parts */
-	if (twl_has_regulator() && !(features & TPS_SUBSET)
+	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
 	  && twl_class_is_4030()) {
 	  && twl_class_is_4030()) {
 		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
 		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
 					features);
 					features);
@@ -939,7 +911,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 	}
 
 
 	/* twl6030 regulators */
 	/* twl6030 regulators */
-	if (twl_has_regulator() && twl_class_is_6030() &&
+	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
 			!(features & TWL6025_SUBCLASS)) {
 			!(features & TWL6025_SUBCLASS)) {
 		child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
 		child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
 					features);
 					features);
@@ -1013,7 +985,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 	}
 
 
 	/* 6030 and 6025 share this regulator */
 	/* 6030 and 6025 share this regulator */
-	if (twl_has_regulator() && twl_class_is_6030()) {
+	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
 		child = add_regulator(TWL6030_REG_VANA, pdata->vana,
 		child = add_regulator(TWL6030_REG_VANA, pdata->vana,
 					features);
 					features);
 		if (IS_ERR(child))
 		if (IS_ERR(child))
@@ -1021,7 +993,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 	}
 
 
 	/* twl6025 regulators */
 	/* twl6025 regulators */
-	if (twl_has_regulator() && twl_class_is_6030() &&
+	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
 			(features & TWL6025_SUBCLASS)) {
 			(features & TWL6025_SUBCLASS)) {
 		child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
 		child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
 					features);
 					features);
@@ -1080,7 +1052,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
 
 	}
 	}
 
 
-	if (twl_has_bci() && pdata->bci &&
+	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
 			!(features & (TPS_SUBSET | TWL5031))) {
 			!(features & (TPS_SUBSET | TWL5031))) {
 		child = add_child(3, "twl4030_bci",
 		child = add_child(3, "twl4030_bci",
 				pdata->bci, sizeof(*pdata->bci), false,
 				pdata->bci, sizeof(*pdata->bci), false,
@@ -1295,7 +1267,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 	}
 
 
 	/* load power event scripts */
 	/* load power event scripts */
-	if (twl_has_power() && pdata->power)
+	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power)
 		twl4030_power_init(pdata->power);
 		twl4030_power_init(pdata->power);
 
 
 	/* Maybe init the T2 Interrupt subsystem */
 	/* Maybe init the T2 Interrupt subsystem */

+ 70 - 35
drivers/mfd/twl4030-audio.c

@@ -28,6 +28,8 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/i2c/twl.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl4030-audio.h>
 #include <linux/mfd/twl4030-audio.h>
@@ -156,47 +158,70 @@ unsigned int twl4030_audio_get_mclk(void)
 }
 }
 EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
 EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
 
 
+static bool twl4030_audio_has_codec(struct twl4030_audio_data *pdata,
+			      struct device_node *node)
+{
+	if (pdata && pdata->codec)
+		return true;
+
+	if (of_find_node_by_name(node, "codec"))
+		return true;
+
+	return false;
+}
+
+static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
+			      struct device_node *node)
+{
+	int vibra;
+
+	if (pdata && pdata->vibra)
+		return true;
+
+	if (!of_property_read_u32(node, "ti,enable-vibra", &vibra) && vibra)
+		return true;
+
+	return false;
+}
+
 static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 {
 {
 	struct twl4030_audio *audio;
 	struct twl4030_audio *audio;
 	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
 	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
 	struct mfd_cell *cell = NULL;
 	struct mfd_cell *cell = NULL;
 	int ret, childs = 0;
 	int ret, childs = 0;
 	u8 val;
 	u8 val;
 
 
-	if (!pdata) {
+	if (!pdata && !node) {
 		dev_err(&pdev->dev, "Platform data is missing\n");
 		dev_err(&pdev->dev, "Platform data is missing\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	audio = devm_kzalloc(&pdev->dev, sizeof(struct twl4030_audio),
+			     GFP_KERNEL);
+	if (!audio)
+		return -ENOMEM;
+
+	mutex_init(&audio->mutex);
+	audio->audio_mclk = twl_get_hfclk_rate();
+
 	/* Configure APLL_INFREQ and disable APLL if enabled */
 	/* Configure APLL_INFREQ and disable APLL if enabled */
-	val = 0;
-	switch (pdata->audio_mclk) {
+	switch (audio->audio_mclk) {
 	case 19200000:
 	case 19200000:
-		val |= TWL4030_APLL_INFREQ_19200KHZ;
+		val = TWL4030_APLL_INFREQ_19200KHZ;
 		break;
 		break;
 	case 26000000:
 	case 26000000:
-		val |= TWL4030_APLL_INFREQ_26000KHZ;
+		val = TWL4030_APLL_INFREQ_26000KHZ;
 		break;
 		break;
 	case 38400000:
 	case 38400000:
-		val |= TWL4030_APLL_INFREQ_38400KHZ;
+		val = TWL4030_APLL_INFREQ_38400KHZ;
 		break;
 		break;
 	default:
 	default:
 		dev_err(&pdev->dev, "Invalid audio_mclk\n");
 		dev_err(&pdev->dev, "Invalid audio_mclk\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-					val, TWL4030_REG_APLL_CTL);
-
-	audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
-	if (!audio)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, audio);
-
-	twl4030_audio_dev = pdev;
-	mutex_init(&audio->mutex);
-	audio->audio_mclk = pdata->audio_mclk;
+	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, val, TWL4030_REG_APLL_CTL);
 
 
 	/* Codec power */
 	/* Codec power */
 	audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
 	audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
@@ -206,21 +231,28 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 	audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
 	audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
 	audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
 	audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
 
 
-	if (pdata->codec) {
+	if (twl4030_audio_has_codec(pdata, node)) {
 		cell = &audio->cells[childs];
 		cell = &audio->cells[childs];
 		cell->name = "twl4030-codec";
 		cell->name = "twl4030-codec";
-		cell->platform_data = pdata->codec;
-		cell->pdata_size = sizeof(*pdata->codec);
+		if (pdata) {
+			cell->platform_data = pdata->codec;
+			cell->pdata_size = sizeof(*pdata->codec);
+		}
 		childs++;
 		childs++;
 	}
 	}
-	if (pdata->vibra) {
+	if (twl4030_audio_has_vibra(pdata, node)) {
 		cell = &audio->cells[childs];
 		cell = &audio->cells[childs];
 		cell->name = "twl4030-vibra";
 		cell->name = "twl4030-vibra";
-		cell->platform_data = pdata->vibra;
-		cell->pdata_size = sizeof(*pdata->vibra);
+		if (pdata) {
+			cell->platform_data = pdata->vibra;
+			cell->pdata_size = sizeof(*pdata->vibra);
+		}
 		childs++;
 		childs++;
 	}
 	}
 
 
+	platform_set_drvdata(pdev, audio);
+	twl4030_audio_dev = pdev;
+
 	if (childs)
 	if (childs)
 		ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
 		ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
 				      childs, NULL, 0, NULL);
 				      childs, NULL, 0, NULL);
@@ -229,39 +261,42 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		ret = -ENODEV;
 	}
 	}
 
 
-	if (!ret)
-		return 0;
+	if (ret) {
+		platform_set_drvdata(pdev, NULL);
+		twl4030_audio_dev = NULL;
+	}
 
 
-	platform_set_drvdata(pdev, NULL);
-	kfree(audio);
-	twl4030_audio_dev = NULL;
 	return ret;
 	return ret;
 }
 }
 
 
 static int __devexit twl4030_audio_remove(struct platform_device *pdev)
 static int __devexit twl4030_audio_remove(struct platform_device *pdev)
 {
 {
-	struct twl4030_audio *audio = platform_get_drvdata(pdev);
-
 	mfd_remove_devices(&pdev->dev);
 	mfd_remove_devices(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
-	kfree(audio);
 	twl4030_audio_dev = NULL;
 	twl4030_audio_dev = NULL;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-MODULE_ALIAS("platform:twl4030-audio");
+static const struct of_device_id twl4030_audio_of_match[] = {
+	{.compatible = "ti,twl4030-audio", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, twl4030_audio_of_match);
 
 
 static struct platform_driver twl4030_audio_driver = {
 static struct platform_driver twl4030_audio_driver = {
-	.probe		= twl4030_audio_probe,
-	.remove		= __devexit_p(twl4030_audio_remove),
 	.driver		= {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.name	= "twl4030-audio",
 		.name	= "twl4030-audio",
+		.of_match_table = twl4030_audio_of_match,
 	},
 	},
+	.probe		= twl4030_audio_probe,
+	.remove		= __devexit_p(twl4030_audio_remove),
 };
 };
 
 
 module_platform_driver(twl4030_audio_driver);
 module_platform_driver(twl4030_audio_driver);
 
 
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("TWL4030 audio block MFD driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030-audio");

+ 16 - 1
drivers/mfd/twl6040-core.c

@@ -584,7 +584,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
 		goto irq_init_err;
 		goto irq_init_err;
 
 
 	ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
 	ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
-				   NULL, twl6040_naudint_handler, 0,
+				   NULL, twl6040_naudint_handler, IRQF_ONESHOT,
 				   "twl6040_irq_ready", twl6040);
 				   "twl6040_irq_ready", twl6040);
 	if (ret) {
 	if (ret) {
 		dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
 		dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
@@ -631,6 +631,21 @@ static int __devinit twl6040_probe(struct i2c_client *client,
 		children++;
 		children++;
 	}
 	}
 
 
+	/*
+	 * Enable the GPO driver in the following cases:
+	 * DT booted kernel or legacy boot with valid gpo platform_data
+	 */
+	if (!pdata || (pdata && pdata->gpo)) {
+		cell = &twl6040->cells[children];
+		cell->name = "twl6040-gpo";
+
+		if (pdata) {
+			cell->platform_data = pdata->gpo;
+			cell->pdata_size = sizeof(*pdata->gpo);
+		}
+		children++;
+	}
+
 	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
 	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
 			      NULL, 0, NULL);
 			      NULL, 0, NULL);
 	if (ret)
 	if (ret)

+ 95 - 1
drivers/mfd/wm5110-tables.c

@@ -133,15 +133,109 @@ static const struct reg_default wm5110_reva_patch[] = {
 	{ 0x209, 0x002A },
 	{ 0x209, 0x002A },
 };
 };
 
 
+static const struct reg_default wm5110_revb_patch[] = {
+	{ 0x80, 0x3 },
+	{ 0x36e, 0x0210 },
+	{ 0x370, 0x0210 },
+	{ 0x372, 0x0210 },
+	{ 0x374, 0x0210 },
+	{ 0x376, 0x0210 },
+	{ 0x378, 0x0210 },
+	{ 0x36d, 0x0028 },
+	{ 0x36f, 0x0028 },
+	{ 0x371, 0x0028 },
+	{ 0x373, 0x0028 },
+	{ 0x375, 0x0028 },
+	{ 0x377, 0x0028 },
+	{ 0x280, 0x2002 },
+	{ 0x44, 0x20 },
+	{ 0x45, 0x40 },
+	{ 0x46, 0x60 },
+	{ 0x47, 0x80 },
+	{ 0x48, 0xa0 },
+	{ 0x51, 0x13 },
+	{ 0x52, 0x33 },
+	{ 0x53, 0x53 },
+	{ 0x54, 0x73 },
+	{ 0x55, 0x93 },
+	{ 0x56, 0xb3 },
+	{ 0xc30, 0x3e3e },
+	{ 0xc31, 0x3e },
+	{ 0xc32, 0x3e3e },
+	{ 0xc33, 0x3e3e },
+	{ 0xc34, 0x3e3e },
+	{ 0xc35, 0x3e3e },
+	{ 0xc36, 0x3e3e },
+	{ 0xc37, 0x3e3e },
+	{ 0xc38, 0x3e3e },
+	{ 0xc39, 0x3e3e },
+	{ 0xc3a, 0x3e3e },
+	{ 0xc3b, 0x3e3e },
+	{ 0xc3c, 0x3e },
+	{ 0x201, 0x18a5 },
+	{ 0x202, 0x4100 },
+	{ 0x460, 0x0c40 },
+	{ 0x461, 0x8000 },
+	{ 0x462, 0x0c41 },
+	{ 0x463, 0x4820 },
+	{ 0x464, 0x0c41 },
+	{ 0x465, 0x4040 },
+	{ 0x466, 0x0841 },
+	{ 0x467, 0x3940 },
+	{ 0x468, 0x0841 },
+	{ 0x469, 0x2030 },
+	{ 0x46a, 0x0842 },
+	{ 0x46b, 0x1990 },
+	{ 0x46c, 0x08c2 },
+	{ 0x46d, 0x1450 },
+	{ 0x46e, 0x08c6 },
+	{ 0x46f, 0x1020 },
+	{ 0x470, 0x08c6 },
+	{ 0x471, 0x0cd0 },
+	{ 0x472, 0x08c6 },
+	{ 0x473, 0x0a30 },
+	{ 0x474, 0x0442 },
+	{ 0x475, 0x0660 },
+	{ 0x476, 0x0446 },
+	{ 0x477, 0x0510 },
+	{ 0x478, 0x04c6 },
+	{ 0x479, 0x0400 },
+	{ 0x47a, 0x04ce },
+	{ 0x47b, 0x0330 },
+	{ 0x47c, 0x05df },
+	{ 0x47d, 0x0001 },
+	{ 0x47e, 0x07ff },
+	{ 0x2db, 0x0a00 },
+	{ 0x2dd, 0x0023 },
+	{ 0x2df, 0x0102 },
+	{ 0x2ef, 0x924 },
+	{ 0x2f0, 0x924 },
+	{ 0x2f1, 0x924 },
+	{ 0x2f2, 0x924 },
+	{ 0x2f3, 0x924 },
+	{ 0x2f4, 0x924 },
+	{ 0x2eb, 0x60 },
+	{ 0x2ec, 0x60 },
+	{ 0x2ed, 0x60 },
+	{ 0x4f2, 0x33e },
+	{ 0x458, 0x0000 },
+	{ 0x15a, 0x0003 },
+	{ 0x80, 0x0 },
+};
+
 /* We use a function so we can use ARRAY_SIZE() */
 /* We use a function so we can use ARRAY_SIZE() */
 int wm5110_patch(struct arizona *arizona)
 int wm5110_patch(struct arizona *arizona)
 {
 {
 	switch (arizona->rev) {
 	switch (arizona->rev) {
 	case 0:
 	case 0:
-	case 1:
 		return regmap_register_patch(arizona->regmap,
 		return regmap_register_patch(arizona->regmap,
 					     wm5110_reva_patch,
 					     wm5110_reva_patch,
 					     ARRAY_SIZE(wm5110_reva_patch));
 					     ARRAY_SIZE(wm5110_reva_patch));
+	case 1:
+		return regmap_register_patch(arizona->regmap,
+					     wm5110_revb_patch,
+					     ARRAY_SIZE(wm5110_revb_patch));
+
 	default:
 	default:
 		return 0;
 		return 0;
 	}
 	}

+ 20 - 46
drivers/mfd/wm831x-core.c

@@ -614,18 +614,11 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
 }
 }
 EXPORT_SYMBOL_GPL(wm831x_set_bits);
 EXPORT_SYMBOL_GPL(wm831x_set_bits);
 
 
-static struct resource wm831x_io_parent = {
-	.start = 0,
-	.end   = 0xffffffff,
-	.flags = IORESOURCE_IO,
-};
-
 static struct resource wm831x_dcdc1_resources[] = {
 static struct resource wm831x_dcdc1_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_DC1_CONTROL_1,
 		.start = WM831X_DC1_CONTROL_1,
 		.end   = WM831X_DC1_DVS_CONTROL,
 		.end   = WM831X_DC1_DVS_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -644,10 +637,9 @@ static struct resource wm831x_dcdc1_resources[] = {
 
 
 static struct resource wm831x_dcdc2_resources[] = {
 static struct resource wm831x_dcdc2_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_DC2_CONTROL_1,
 		.start = WM831X_DC2_CONTROL_1,
 		.end   = WM831X_DC2_DVS_CONTROL,
 		.end   = WM831X_DC2_DVS_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -665,10 +657,9 @@ static struct resource wm831x_dcdc2_resources[] = {
 
 
 static struct resource wm831x_dcdc3_resources[] = {
 static struct resource wm831x_dcdc3_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_DC3_CONTROL_1,
 		.start = WM831X_DC3_CONTROL_1,
 		.end   = WM831X_DC3_SLEEP_CONTROL,
 		.end   = WM831X_DC3_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -680,10 +671,9 @@ static struct resource wm831x_dcdc3_resources[] = {
 
 
 static struct resource wm831x_dcdc4_resources[] = {
 static struct resource wm831x_dcdc4_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_DC4_CONTROL,
 		.start = WM831X_DC4_CONTROL,
 		.end   = WM831X_DC4_SLEEP_CONTROL,
 		.end   = WM831X_DC4_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -695,10 +685,9 @@ static struct resource wm831x_dcdc4_resources[] = {
 
 
 static struct resource wm8320_dcdc4_buck_resources[] = {
 static struct resource wm8320_dcdc4_buck_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_DC4_CONTROL,
 		.start = WM831X_DC4_CONTROL,
 		.end   = WM832X_DC4_SLEEP_CONTROL,
 		.end   = WM832X_DC4_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -718,10 +707,9 @@ static struct resource wm831x_gpio_resources[] = {
 
 
 static struct resource wm831x_isink1_resources[] = {
 static struct resource wm831x_isink1_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_CURRENT_SINK_1,
 		.start = WM831X_CURRENT_SINK_1,
 		.end   = WM831X_CURRENT_SINK_1,
 		.end   = WM831X_CURRENT_SINK_1,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.start = WM831X_IRQ_CS1,
 		.start = WM831X_IRQ_CS1,
@@ -732,10 +720,9 @@ static struct resource wm831x_isink1_resources[] = {
 
 
 static struct resource wm831x_isink2_resources[] = {
 static struct resource wm831x_isink2_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_CURRENT_SINK_2,
 		.start = WM831X_CURRENT_SINK_2,
 		.end   = WM831X_CURRENT_SINK_2,
 		.end   = WM831X_CURRENT_SINK_2,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.start = WM831X_IRQ_CS2,
 		.start = WM831X_IRQ_CS2,
@@ -746,10 +733,9 @@ static struct resource wm831x_isink2_resources[] = {
 
 
 static struct resource wm831x_ldo1_resources[] = {
 static struct resource wm831x_ldo1_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO1_CONTROL,
 		.start = WM831X_LDO1_CONTROL,
 		.end   = WM831X_LDO1_SLEEP_CONTROL,
 		.end   = WM831X_LDO1_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -761,10 +747,9 @@ static struct resource wm831x_ldo1_resources[] = {
 
 
 static struct resource wm831x_ldo2_resources[] = {
 static struct resource wm831x_ldo2_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO2_CONTROL,
 		.start = WM831X_LDO2_CONTROL,
 		.end   = WM831X_LDO2_SLEEP_CONTROL,
 		.end   = WM831X_LDO2_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -776,10 +761,9 @@ static struct resource wm831x_ldo2_resources[] = {
 
 
 static struct resource wm831x_ldo3_resources[] = {
 static struct resource wm831x_ldo3_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO3_CONTROL,
 		.start = WM831X_LDO3_CONTROL,
 		.end   = WM831X_LDO3_SLEEP_CONTROL,
 		.end   = WM831X_LDO3_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -791,10 +775,9 @@ static struct resource wm831x_ldo3_resources[] = {
 
 
 static struct resource wm831x_ldo4_resources[] = {
 static struct resource wm831x_ldo4_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO4_CONTROL,
 		.start = WM831X_LDO4_CONTROL,
 		.end   = WM831X_LDO4_SLEEP_CONTROL,
 		.end   = WM831X_LDO4_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -806,10 +789,9 @@ static struct resource wm831x_ldo4_resources[] = {
 
 
 static struct resource wm831x_ldo5_resources[] = {
 static struct resource wm831x_ldo5_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO5_CONTROL,
 		.start = WM831X_LDO5_CONTROL,
 		.end   = WM831X_LDO5_SLEEP_CONTROL,
 		.end   = WM831X_LDO5_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -821,10 +803,9 @@ static struct resource wm831x_ldo5_resources[] = {
 
 
 static struct resource wm831x_ldo6_resources[] = {
 static struct resource wm831x_ldo6_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO6_CONTROL,
 		.start = WM831X_LDO6_CONTROL,
 		.end   = WM831X_LDO6_SLEEP_CONTROL,
 		.end   = WM831X_LDO6_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -836,10 +817,9 @@ static struct resource wm831x_ldo6_resources[] = {
 
 
 static struct resource wm831x_ldo7_resources[] = {
 static struct resource wm831x_ldo7_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO7_CONTROL,
 		.start = WM831X_LDO7_CONTROL,
 		.end   = WM831X_LDO7_SLEEP_CONTROL,
 		.end   = WM831X_LDO7_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -851,10 +831,9 @@ static struct resource wm831x_ldo7_resources[] = {
 
 
 static struct resource wm831x_ldo8_resources[] = {
 static struct resource wm831x_ldo8_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO8_CONTROL,
 		.start = WM831X_LDO8_CONTROL,
 		.end   = WM831X_LDO8_SLEEP_CONTROL,
 		.end   = WM831X_LDO8_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -866,10 +845,9 @@ static struct resource wm831x_ldo8_resources[] = {
 
 
 static struct resource wm831x_ldo9_resources[] = {
 static struct resource wm831x_ldo9_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO9_CONTROL,
 		.start = WM831X_LDO9_CONTROL,
 		.end   = WM831X_LDO9_SLEEP_CONTROL,
 		.end   = WM831X_LDO9_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -881,10 +859,9 @@ static struct resource wm831x_ldo9_resources[] = {
 
 
 static struct resource wm831x_ldo10_resources[] = {
 static struct resource wm831x_ldo10_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO10_CONTROL,
 		.start = WM831X_LDO10_CONTROL,
 		.end   = WM831X_LDO10_SLEEP_CONTROL,
 		.end   = WM831X_LDO10_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 	{
 	{
 		.name  = "UV",
 		.name  = "UV",
@@ -896,10 +873,9 @@ static struct resource wm831x_ldo10_resources[] = {
 
 
 static struct resource wm831x_ldo11_resources[] = {
 static struct resource wm831x_ldo11_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_LDO11_ON_CONTROL,
 		.start = WM831X_LDO11_ON_CONTROL,
 		.end   = WM831X_LDO11_SLEEP_CONTROL,
 		.end   = WM831X_LDO11_SLEEP_CONTROL,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 };
 };
 
 
@@ -998,19 +974,17 @@ static struct resource wm831x_rtc_resources[] = {
 
 
 static struct resource wm831x_status1_resources[] = {
 static struct resource wm831x_status1_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_STATUS_LED_1,
 		.start = WM831X_STATUS_LED_1,
 		.end   = WM831X_STATUS_LED_1,
 		.end   = WM831X_STATUS_LED_1,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 };
 };
 
 
 static struct resource wm831x_status2_resources[] = {
 static struct resource wm831x_status2_resources[] = {
 	{
 	{
-		.parent = &wm831x_io_parent,
 		.start = WM831X_STATUS_LED_2,
 		.start = WM831X_STATUS_LED_2,
 		.end   = WM831X_STATUS_LED_2,
 		.end   = WM831X_STATUS_LED_2,
-		.flags = IORESOURCE_IO,
+		.flags = IORESOURCE_REG,
 	},
 	},
 };
 };
 
 

+ 1 - 1
drivers/mfd/wm8994-core.c

@@ -390,7 +390,7 @@ static const __devinitdata struct reg_default wm8958_reva_patch[] = {
 
 
 static const __devinitdata struct reg_default wm1811_reva_patch[] = {
 static const __devinitdata struct reg_default wm1811_reva_patch[] = {
 	{ 0x102, 0x3 },
 	{ 0x102, 0x3 },
-	{ 0x56, 0x7 },
+	{ 0x56, 0xc07 },
 	{ 0x5d, 0x7e },
 	{ 0x5d, 0x7e },
 	{ 0x5e, 0x0 },
 	{ 0x5e, 0x0 },
 	{ 0x102, 0x0 },
 	{ 0x102, 0x0 },

+ 1 - 1
drivers/mfd/wm8994-regmap.c

@@ -1136,7 +1136,7 @@ static bool wm1811_volatile_register(struct device *dev, unsigned int reg)
 
 
 	switch (reg) {
 	switch (reg) {
 	case WM8994_GPIO_6:
 	case WM8994_GPIO_6:
-		if (wm8994->revision > 1)
+		if (wm8994->cust_id > 1 || wm8994->revision > 1)
 			return true;
 			return true;
 		else
 		else
 			return false;
 			return false;

+ 9 - 0
drivers/pwm/Kconfig

@@ -115,6 +115,15 @@ config  PWM_TIEHRPWM
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-tiehrpwm.
 	  will be called pwm-tiehrpwm.
 
 
+config PWM_TWL6030
+	tristate "TWL6030 PWM support"
+	depends on TWL4030_CORE
+	help
+	  Generic PWM framework driver for TWL6030.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-twl6030.
+
 config PWM_VT8500
 config PWM_VT8500
 	tristate "vt8500 pwm support"
 	tristate "vt8500 pwm support"
 	depends on ARCH_VT8500
 	depends on ARCH_VT8500

+ 1 - 0
drivers/pwm/Makefile

@@ -8,4 +8,5 @@ obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
 obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
 obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
 obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
 obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
 obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
 obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
+obj-$(CONFIG_PWM_TWL6030)	+= pwm-twl6030.o
 obj-$(CONFIG_PWM_VT8500)	+= pwm-vt8500.o
 obj-$(CONFIG_PWM_VT8500)	+= pwm-vt8500.o

+ 69 - 50
drivers/mfd/twl6030-pwm.c → drivers/pwm/pwm-twl6030.c

@@ -20,6 +20,7 @@
 
 
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/pwm.h>
 #include <linux/i2c/twl.h>
 #include <linux/i2c/twl.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
@@ -45,40 +46,54 @@
 
 
 #define PWM_CTRL2_MODE_MASK	0x3
 #define PWM_CTRL2_MODE_MASK	0x3
 
 
-struct pwm_device {
-	const char *label;
-	unsigned int pwm_id;
+struct twl6030_pwm_chip {
+	struct pwm_chip chip;
 };
 };
 
 
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 {
-	u8 duty_cycle;
 	int ret;
 	int ret;
+	u8 val;
 
 
-	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
-		return -EINVAL;
+	/* Configure PWM */
+	val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
+	      PWM_CTRL2_MODE_HW;
 
 
-	duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n",
+			pwm->label, ret);
+		return ret;
+	}
 
 
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
+	return 0;
+}
 
 
+static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			      int duty_ns, int period_ns)
+{
+	u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
+	int ret;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
 	if (ret < 0) {
 	if (ret < 0) {
 		pr_err("%s: Failed to configure PWM, Error %d\n",
 		pr_err("%s: Failed to configure PWM, Error %d\n",
 			pwm->label, ret);
 			pwm->label, ret);
 		return ret;
 		return ret;
 	}
 	}
+
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL(pwm_config);
 
 
-int pwm_enable(struct pwm_device *pwm)
+static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 {
-	u8 val;
 	int ret;
 	int ret;
+	u8 val;
 
 
 	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	if (ret < 0) {
 	if (ret < 0) {
-		pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
+		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
+			pwm->label, ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -88,23 +103,23 @@ int pwm_enable(struct pwm_device *pwm)
 
 
 	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
 	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
 	if (ret < 0) {
 	if (ret < 0) {
-		pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
+		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
+			pwm->label, ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
 	twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL(pwm_enable);
 
 
-void pwm_disable(struct pwm_device *pwm)
+static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 {
-	u8 val;
 	int ret;
 	int ret;
+	u8 val;
 
 
 	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
 	if (ret < 0) {
 	if (ret < 0) {
-		pr_err("%s: Failed to disable PWM, Error %d\n",
+		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
 			pwm->label, ret);
 			pwm->label, ret);
 		return;
 		return;
 	}
 	}
@@ -114,52 +129,56 @@ void pwm_disable(struct pwm_device *pwm)
 
 
 	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
 	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
 	if (ret < 0) {
 	if (ret < 0) {
-		pr_err("%s: Failed to disable PWM, Error %d\n",
+		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
 			pwm->label, ret);
 			pwm->label, ret);
-		return;
 	}
 	}
-	return;
 }
 }
-EXPORT_SYMBOL(pwm_disable);
 
 
-struct pwm_device *pwm_request(int pwm_id, const char *label)
+static const struct pwm_ops twl6030_pwm_ops = {
+	.request = twl6030_pwm_request,
+	.config = twl6030_pwm_config,
+	.enable = twl6030_pwm_enable,
+	.disable = twl6030_pwm_disable,
+};
+
+static int twl6030_pwm_probe(struct platform_device *pdev)
 {
 {
-	u8 val;
+	struct twl6030_pwm_chip *twl6030;
 	int ret;
 	int ret;
-	struct pwm_device *pwm;
-
-	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
-	if (pwm == NULL) {
-		pr_err("%s: failed to allocate memory\n", label);
-		return NULL;
-	}
 
 
-	pwm->label = label;
-	pwm->pwm_id = pwm_id;
-
-	/* Configure PWM */
-	val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
-		PWM_CTRL2_MODE_HW;
+	twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL);
+	if (!twl6030)
+		return -ENOMEM;
 
 
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
+	twl6030->chip.dev = &pdev->dev;
+	twl6030->chip.ops = &twl6030_pwm_ops;
+	twl6030->chip.base = -1;
+	twl6030->chip.npwm = 1;
 
 
-	if (ret < 0) {
-		pr_err("%s: Failed to configure PWM, Error %d\n",
-			 pwm->label, ret);
+	ret = pwmchip_add(&twl6030->chip);
+	if (ret < 0)
+		return ret;
 
 
-		kfree(pwm);
-		return NULL;
-	}
+	platform_set_drvdata(pdev, twl6030);
 
 
-	return pwm;
+	return 0;
 }
 }
-EXPORT_SYMBOL(pwm_request);
 
 
-void pwm_free(struct pwm_device *pwm)
+static int twl6030_pwm_remove(struct platform_device *pdev)
 {
 {
-	pwm_disable(pwm);
-	kfree(pwm);
+	struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&twl6030->chip);
 }
 }
-EXPORT_SYMBOL(pwm_free);
 
 
+static struct platform_driver twl6030_pwm_driver = {
+	.driver = {
+		.name = "twl6030-pwm",
+	},
+	.probe = twl6030_pwm_probe,
+	.remove = __devexit_p(twl6030_pwm_remove),
+};
+module_platform_driver(twl6030_pwm_driver);
+
+MODULE_ALIAS("platform:twl6030-pwm");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 120 - 16
drivers/regulator/88pm8607.c

@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/machine.h>
@@ -23,6 +25,7 @@ struct pm8607_regulator_info {
 	struct pm860x_chip	*chip;
 	struct pm860x_chip	*chip;
 	struct regulator_dev	*regulator;
 	struct regulator_dev	*regulator;
 	struct i2c_client	*i2c;
 	struct i2c_client	*i2c;
+	struct i2c_client	*i2c_8606;
 
 
 	unsigned int	*vol_table;
 	unsigned int	*vol_table;
 	unsigned int	*vol_suspend;
 	unsigned int	*vol_suspend;
@@ -242,6 +245,35 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 	return ret;
 	return ret;
 }
 }
 
 
+static int pm8606_preg_enable(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
+			       1 << rdev->desc->enable_mask, 0);
+}
+
+static int pm8606_preg_disable(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
+			       1 << rdev->desc->enable_mask,
+			       1 << rdev->desc->enable_mask);
+}
+
+static int pm8606_preg_is_enabled(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = pm860x_reg_read(info->i2c, rdev->desc->enable_reg);
+	if (ret < 0)
+		return ret;
+
+	return !((unsigned char)ret & (1 << rdev->desc->enable_mask));
+}
+
 static struct regulator_ops pm8607_regulator_ops = {
 static struct regulator_ops pm8607_regulator_ops = {
 	.list_voltage	= pm8607_list_voltage,
 	.list_voltage	= pm8607_list_voltage,
 	.set_voltage_sel = pm8607_set_voltage_sel,
 	.set_voltage_sel = pm8607_set_voltage_sel,
@@ -251,6 +283,25 @@ static struct regulator_ops pm8607_regulator_ops = {
 	.is_enabled = regulator_is_enabled_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 };
 };
 
 
+static struct regulator_ops pm8606_preg_ops = {
+	.enable		= pm8606_preg_enable,
+	.disable	= pm8606_preg_disable,
+	.is_enabled	= pm8606_preg_is_enabled,
+};
+
+#define PM8606_PREG(ereg, ebit)						\
+{									\
+	.desc	= {							\
+		.name	= "PREG",					\
+		.ops	= &pm8606_preg_ops,				\
+		.type	= REGULATOR_CURRENT,				\
+		.id	= PM8606_ID_PREG,				\
+		.owner	= THIS_MODULE,					\
+		.enable_reg = PM8606_##ereg,				\
+		.enable_mask = (ebit),					\
+	},								\
+}
+
 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit)			\
 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit)			\
 {									\
 {									\
 	.desc	= {							\
 	.desc	= {							\
@@ -311,6 +362,38 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
 	PM8607_LDO(14,        LDO14, 0, SUPPLIES_EN12, 6),
 	PM8607_LDO(14,        LDO14, 0, SUPPLIES_EN12, 6),
 };
 };
 
 
+static struct pm8607_regulator_info pm8606_regulator_info[] = {
+	PM8606_PREG(PREREGULATORB, 5),
+};
+
+#ifdef CONFIG_OF
+static int pm8607_regulator_dt_init(struct platform_device *pdev,
+				    struct pm8607_regulator_info *info,
+				    struct regulator_config *config)
+{
+	struct device_node *nproot, *np;
+	nproot = pdev->dev.parent->of_node;
+	if (!nproot)
+		return -ENODEV;
+	nproot = of_find_node_by_name(nproot, "regulators");
+	if (!nproot) {
+		dev_err(&pdev->dev, "failed to find regulators node\n");
+		return -ENODEV;
+	}
+	for_each_child_of_node(nproot, np) {
+		if (!of_node_cmp(np->name, info->desc.name)) {
+			config->init_data =
+				of_get_regulator_init_data(&pdev->dev, np);
+			config->of_node = np;
+			break;
+		}
+	}
+	return 0;
+}
+#else
+#define pm8607_regulator_dt_init(x, y, z)	(-1)
+#endif
+
 static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 {
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -320,22 +403,28 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct resource *res;
 	int i;
 	int i;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource!\n");
-		return -EINVAL;
-	}
-	for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
-		info = &pm8607_regulator_info[i];
-		if (info->desc.id == res->start)
-			break;
-	}
-	if (i == ARRAY_SIZE(pm8607_regulator_info)) {
-		dev_err(&pdev->dev, "Failed to find regulator %llu\n",
-			(unsigned long long)res->start);
-		return -EINVAL;
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (res) {
+		/* There're resources in 88PM8607 regulator driver */
+		for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
+			info = &pm8607_regulator_info[i];
+			if (info->desc.vsel_reg == res->start)
+				break;
+		}
+		if (i == ARRAY_SIZE(pm8607_regulator_info)) {
+			dev_err(&pdev->dev, "Failed to find regulator %llu\n",
+				(unsigned long long)res->start);
+			return -EINVAL;
+		}
+	} else {
+		/* There's no resource in 88PM8606 PREG regulator driver */
+		info = &pm8606_regulator_info[0];
+		/* i is used to check regulator ID */
+		i = -1;
 	}
 	}
 	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
 	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+	info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
+			chip->client;
 	info->chip = chip;
 	info->chip = chip;
 
 
 	/* check DVC ramp slope double */
 	/* check DVC ramp slope double */
@@ -343,15 +432,17 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 		info->slope_double = 1;
 		info->slope_double = 1;
 
 
 	config.dev = &pdev->dev;
 	config.dev = &pdev->dev;
-	config.init_data = pdata;
 	config.driver_data = info;
 	config.driver_data = info;
 
 
+	if (pm8607_regulator_dt_init(pdev, info, &config))
+		if (pdata)
+			config.init_data = pdata;
+
 	if (chip->id == CHIP_PM8607)
 	if (chip->id == CHIP_PM8607)
 		config.regmap = chip->regmap;
 		config.regmap = chip->regmap;
 	else
 	else
 		config.regmap = chip->regmap_companion;
 		config.regmap = chip->regmap_companion;
 
 
-	/* replace driver_data with info */
 	info->regulator = regulator_register(&info->desc, &config);
 	info->regulator = regulator_register(&info->desc, &config);
 	if (IS_ERR(info->regulator)) {
 	if (IS_ERR(info->regulator)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -372,6 +463,18 @@ static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
+static struct platform_device_id pm8607_regulator_driver_ids[] = {
+	{
+		.name	= "88pm860x-regulator",
+		.driver_data	= 0,
+	}, {
+		.name	= "88pm860x-preg",
+		.driver_data	= 0,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
+
 static struct platform_driver pm8607_regulator_driver = {
 static struct platform_driver pm8607_regulator_driver = {
 	.driver		= {
 	.driver		= {
 		.name	= "88pm860x-regulator",
 		.name	= "88pm860x-regulator",
@@ -379,6 +482,7 @@ static struct platform_driver pm8607_regulator_driver = {
 	},
 	},
 	.probe		= pm8607_regulator_probe,
 	.probe		= pm8607_regulator_probe,
 	.remove		= __devexit_p(pm8607_regulator_remove),
 	.remove		= __devexit_p(pm8607_regulator_remove),
+	.id_table	= pm8607_regulator_driver_ids,
 };
 };
 
 
 static int __init pm8607_regulator_init(void)
 static int __init pm8607_regulator_init(void)

+ 1 - 1
drivers/regulator/Kconfig

@@ -122,7 +122,7 @@ config REGULATOR_FAN53555
 
 
 config REGULATOR_ANATOP
 config REGULATOR_ANATOP
 	tristate "Freescale i.MX on-chip ANATOP LDO regulators"
 	tristate "Freescale i.MX on-chip ANATOP LDO regulators"
-	depends on MFD_ANATOP
+	depends on MFD_SYSCON
 	help
 	help
 	  Say y here to support Freescale i.MX on-chip ANATOP LDOs
 	  Say y here to support Freescale i.MX on-chip ANATOP LDOs
 	  regulators. It is recommended that this option be
 	  regulators. It is recommended that this option be

+ 1 - 0
drivers/regulator/ab3100.c

@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/driver.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500.h>
 
 
 /* LDO registers and some handy masking definitions for AB3100 */
 /* LDO registers and some handy masking definitions for AB3100 */

+ 21 - 10
drivers/regulator/anatop-regulator.c

@@ -21,19 +21,20 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/mfd/syscon.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
-#include <linux/mfd/anatop.h>
+#include <linux/regmap.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/of_regulator.h>
 
 
 struct anatop_regulator {
 struct anatop_regulator {
 	const char *name;
 	const char *name;
 	u32 control_reg;
 	u32 control_reg;
-	struct anatop *mfd;
+	struct regmap *anatop;
 	int vol_bit_shift;
 	int vol_bit_shift;
 	int vol_bit_width;
 	int vol_bit_width;
 	int min_bit_val;
 	int min_bit_val;
@@ -43,7 +44,8 @@ struct anatop_regulator {
 	struct regulator_init_data *initdata;
 	struct regulator_init_data *initdata;
 };
 };
 
 
-static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
+static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
+					unsigned selector)
 {
 {
 	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 	u32 val, mask;
 	u32 val, mask;
@@ -56,12 +58,13 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
 	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
 	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
 		anatop_reg->vol_bit_shift;
 		anatop_reg->vol_bit_shift;
 	val <<= anatop_reg->vol_bit_shift;
 	val <<= anatop_reg->vol_bit_shift;
-	anatop_write_reg(anatop_reg->mfd, anatop_reg->control_reg, val, mask);
+	regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
+				mask, val);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static int anatop_get_voltage_sel(struct regulator_dev *reg)
+static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
 {
 {
 	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 	u32 val, mask;
 	u32 val, mask;
@@ -69,7 +72,7 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
 	if (!anatop_reg->control_reg)
 	if (!anatop_reg->control_reg)
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
-	val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg);
+	regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
 	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
 	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
 		anatop_reg->vol_bit_shift;
 		anatop_reg->vol_bit_shift;
 	val = (val & mask) >> anatop_reg->vol_bit_shift;
 	val = (val & mask) >> anatop_reg->vol_bit_shift;
@@ -78,8 +81,8 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
 }
 }
 
 
 static struct regulator_ops anatop_rops = {
 static struct regulator_ops anatop_rops = {
-	.set_voltage_sel = anatop_set_voltage_sel,
-	.get_voltage_sel = anatop_get_voltage_sel,
+	.set_voltage_sel = anatop_regmap_set_voltage_sel,
+	.get_voltage_sel = anatop_regmap_get_voltage_sel,
 	.list_voltage = regulator_list_voltage_linear,
 	.list_voltage = regulator_list_voltage_linear,
 	.map_voltage = regulator_map_voltage_linear,
 	.map_voltage = regulator_map_voltage_linear,
 };
 };
@@ -88,11 +91,11 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
 {
 {
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct device_node *np = dev->of_node;
+	struct device_node *anatop_np;
 	struct regulator_desc *rdesc;
 	struct regulator_desc *rdesc;
 	struct regulator_dev *rdev;
 	struct regulator_dev *rdev;
 	struct anatop_regulator *sreg;
 	struct anatop_regulator *sreg;
 	struct regulator_init_data *initdata;
 	struct regulator_init_data *initdata;
-	struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_config config = { };
 	struct regulator_config config = { };
 	int ret = 0;
 	int ret = 0;
 
 
@@ -109,7 +112,15 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
 	rdesc->ops = &anatop_rops;
 	rdesc->ops = &anatop_rops;
 	rdesc->type = REGULATOR_VOLTAGE;
 	rdesc->type = REGULATOR_VOLTAGE;
 	rdesc->owner = THIS_MODULE;
 	rdesc->owner = THIS_MODULE;
-	sreg->mfd = anatopmfd;
+
+	anatop_np = of_get_parent(np);
+	if (!anatop_np)
+		return -ENODEV;
+	sreg->anatop = syscon_node_to_regmap(anatop_np);
+	of_node_put(anatop_np);
+	if (IS_ERR(sreg->anatop))
+		return PTR_ERR(sreg->anatop);
+
 	ret = of_property_read_u32(np, "anatop-reg-offset",
 	ret = of_property_read_u32(np, "anatop-reg-offset",
 				   &sreg->control_reg);
 				   &sreg->control_reg);
 	if (ret) {
 	if (ret) {

+ 17 - 18
drivers/regulator/max8925-regulator.c

@@ -214,37 +214,36 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
 	MAX8925_LDO(20, 750, 3900, 50),
 	MAX8925_LDO(20, 750, 3900, 50),
 };
 };
 
 
-static struct max8925_regulator_info * __devinit find_regulator_info(int id)
-{
-	struct max8925_regulator_info *ri;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
-		ri = &max8925_regulator_info[i];
-		if (ri->desc.id == id)
-			return ri;
-	}
-	return NULL;
-}
-
 static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 {
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *pdata = chip->dev->platform_data;
+	struct regulator_init_data *pdata = pdev->dev.platform_data;
 	struct regulator_config config = { };
 	struct regulator_config config = { };
 	struct max8925_regulator_info *ri;
 	struct max8925_regulator_info *ri;
+	struct resource *res;
 	struct regulator_dev *rdev;
 	struct regulator_dev *rdev;
+	int i;
 
 
-	ri = find_regulator_info(pdev->id);
-	if (ri == NULL) {
-		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource!\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
+		ri = &max8925_regulator_info[i];
+		if (ri->vol_reg == res->start)
+			break;
+	}
+	if (i == ARRAY_SIZE(max8925_regulator_info)) {
+		dev_err(&pdev->dev, "Failed to find regulator %llu\n",
+			(unsigned long long)res->start);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	ri->i2c = chip->i2c;
 	ri->i2c = chip->i2c;
 	ri->chip = chip;
 	ri->chip = chip;
 
 
 	config.dev = &pdev->dev;
 	config.dev = &pdev->dev;
-	config.init_data = pdata->regulator[pdev->id];
+	config.init_data = pdata;
 	config.driver_data = ri;
 	config.driver_data = ri;
 
 
 	rdev = regulator_register(&ri->desc, &config);
 	rdev = regulator_register(&ri->desc, &config);

+ 119 - 8
drivers/regulator/palmas-regulator.c

@@ -22,6 +22,9 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/regmap.h>
 #include <linux/regmap.h>
 #include <linux/mfd/palmas.h>
 #include <linux/mfd/palmas.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regulator/of_regulator.h>
 
 
 struct regs_info {
 struct regs_info {
 	char	*name;
 	char	*name;
@@ -568,10 +571,103 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
 	return 0;
 	return 0;
 }
 }
 
 
+static struct of_regulator_match palmas_matches[] = {
+	{ .name = "smps12", },
+	{ .name = "smps123", },
+	{ .name = "smps3", },
+	{ .name = "smps45", },
+	{ .name = "smps457", },
+	{ .name = "smps6", },
+	{ .name = "smps7", },
+	{ .name = "smps8", },
+	{ .name = "smps9", },
+	{ .name = "smps10", },
+	{ .name = "ldo1", },
+	{ .name = "ldo2", },
+	{ .name = "ldo3", },
+	{ .name = "ldo4", },
+	{ .name = "ldo5", },
+	{ .name = "ldo6", },
+	{ .name = "ldo7", },
+	{ .name = "ldo8", },
+	{ .name = "ldo9", },
+	{ .name = "ldoln", },
+	{ .name = "ldousb", },
+};
+
+static void __devinit palmas_dt_to_pdata(struct device *dev,
+		struct device_node *node,
+		struct palmas_pmic_platform_data *pdata)
+{
+	struct device_node *regulators;
+	u32 prop;
+	int idx, ret;
+
+	regulators = of_find_node_by_name(node, "regulators");
+	if (!regulators) {
+		dev_info(dev, "regulator node not found\n");
+		return;
+	}
+
+	ret = of_regulator_match(dev, regulators, palmas_matches,
+			PALMAS_NUM_REGS);
+	if (ret < 0) {
+		dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+		return;
+	}
+
+	for (idx = 0; idx < PALMAS_NUM_REGS; idx++) {
+		if (!palmas_matches[idx].init_data ||
+				!palmas_matches[idx].of_node)
+			continue;
+
+		pdata->reg_data[idx] = palmas_matches[idx].init_data;
+
+		pdata->reg_init[idx] = devm_kzalloc(dev,
+				sizeof(struct palmas_reg_init), GFP_KERNEL);
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,warm_reset", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->warm_reset = prop;
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,roof_floor", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->roof_floor = prop;
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,mode_sleep", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->mode_sleep = prop;
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,warm_reset", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->warm_reset = prop;
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,tstep", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->tstep = prop;
+
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+				"ti,vsel", &prop);
+		if (!ret)
+			pdata->reg_init[idx]->vsel = prop;
+	}
+
+	ret = of_property_read_u32(node, "ti,ldo6_vibrator", &prop);
+	if (!ret)
+		pdata->ldo6_vibrator = prop;
+}
+
+
 static __devinit int palmas_probe(struct platform_device *pdev)
 static __devinit int palmas_probe(struct platform_device *pdev)
 {
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
 	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
 	struct regulator_dev *rdev;
 	struct regulator_dev *rdev;
 	struct regulator_config config = { };
 	struct regulator_config config = { };
 	struct palmas_pmic *pmic;
 	struct palmas_pmic *pmic;
@@ -579,10 +675,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 	int id = 0, ret;
 	int id = 0, ret;
 	unsigned int addr, reg;
 	unsigned int addr, reg;
 
 
-	if (!pdata)
-		return -EINVAL;
-	if (!pdata->reg_data)
-		return -EINVAL;
+	if (node && !pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+
+		if (!pdata)
+			return -ENOMEM;
+
+		palmas_dt_to_pdata(&pdev->dev, node, pdata);
+	}
 
 
 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
 	if (!pmic)
 	if (!pmic)
@@ -661,7 +761,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 		pmic->desc[id].owner = THIS_MODULE;
 		pmic->desc[id].owner = THIS_MODULE;
 
 
 		/* Initialise sleep/init values from platform data */
 		/* Initialise sleep/init values from platform data */
-		if (pdata && pdata->reg_init) {
+		if (pdata) {
 			reg_init = pdata->reg_init[id];
 			reg_init = pdata->reg_init[id];
 			if (reg_init) {
 			if (reg_init) {
 				ret = palmas_smps_init(palmas, id, reg_init);
 				ret = palmas_smps_init(palmas, id, reg_init);
@@ -685,11 +785,13 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 				pmic->range[id] = 1;
 				pmic->range[id] = 1;
 		}
 		}
 
 
-		if (pdata && pdata->reg_data)
+		if (pdata)
 			config.init_data = pdata->reg_data[id];
 			config.init_data = pdata->reg_data[id];
 		else
 		else
 			config.init_data = NULL;
 			config.init_data = NULL;
 
 
+		config.of_node = palmas_matches[id].of_node;
+
 		rdev = regulator_register(&pmic->desc[id], &config);
 		rdev = regulator_register(&pmic->desc[id], &config);
 		if (IS_ERR(rdev)) {
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 			dev_err(&pdev->dev,
@@ -726,11 +828,13 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 						palmas_regs_info[id].ctrl_addr);
 						palmas_regs_info[id].ctrl_addr);
 		pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
 		pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
 
 
-		if (pdata && pdata->reg_data)
+		if (pdata)
 			config.init_data = pdata->reg_data[id];
 			config.init_data = pdata->reg_data[id];
 		else
 		else
 			config.init_data = NULL;
 			config.init_data = NULL;
 
 
+		config.of_node = palmas_matches[id].of_node;
+
 		rdev = regulator_register(&pmic->desc[id], &config);
 		rdev = regulator_register(&pmic->desc[id], &config);
 		if (IS_ERR(rdev)) {
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 			dev_err(&pdev->dev,
@@ -744,7 +848,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 		pmic->rdev[id] = rdev;
 		pmic->rdev[id] = rdev;
 
 
 		/* Initialise sleep/init values from platform data */
 		/* Initialise sleep/init values from platform data */
-		if (pdata->reg_init) {
+		if (pdata) {
 			reg_init = pdata->reg_init[id];
 			reg_init = pdata->reg_init[id];
 			if (reg_init) {
 			if (reg_init) {
 				ret = palmas_ldo_init(palmas, id, reg_init);
 				ret = palmas_ldo_init(palmas, id, reg_init);
@@ -774,9 +878,15 @@ static int __devexit palmas_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
+static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-pmic", },
+	{ /* end */ }
+};
+
 static struct platform_driver palmas_driver = {
 static struct platform_driver palmas_driver = {
 	.driver = {
 	.driver = {
 		.name = "palmas-pmic",
 		.name = "palmas-pmic",
+		.of_match_table = of_palmas_match_tbl,
 		.owner = THIS_MODULE,
 		.owner = THIS_MODULE,
 	},
 	},
 	.probe = palmas_probe,
 	.probe = palmas_probe,
@@ -799,3 +909,4 @@ MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("Palmas voltage regulator driver");
 MODULE_DESCRIPTION("Palmas voltage regulator driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:palmas-pmic");
 MODULE_ALIAS("platform:palmas-pmic");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);

+ 6 - 6
drivers/regulator/wm831x-dcdc.c

@@ -475,9 +475,9 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 
 
 	dcdc->wm831x = wm831x;
 	dcdc->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}
@@ -650,9 +650,9 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
 
 
 	dcdc->wm831x = wm831x;
 	dcdc->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}
@@ -794,9 +794,9 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
 
 
 	dcdc->wm831x = wm831x;
 	dcdc->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}

+ 2 - 2
drivers/regulator/wm831x-isink.c

@@ -172,9 +172,9 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
 
 
 	isink->wm831x = wm831x;
 	isink->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}

+ 6 - 6
drivers/regulator/wm831x-ldo.c

@@ -273,9 +273,9 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
 
 
 	ldo->wm831x = wm831x;
 	ldo->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}
@@ -530,9 +530,9 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
 
 
 	ldo->wm831x = wm831x;
 	ldo->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}
@@ -687,9 +687,9 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
 
 
 	ldo->wm831x = wm831x;
 	ldo->wm831x = wm831x;
 
 
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (res == NULL) {
 	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource\n");
+		dev_err(&pdev->dev, "No REG resource\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto err;
 		goto err;
 	}
 	}

+ 34 - 9
drivers/rtc/rtc-88pm860x.c

@@ -11,6 +11,7 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
@@ -284,6 +285,28 @@ out:
 }
 }
 #endif
 #endif
 
 
+#ifdef CONFIG_OF
+static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev,
+					struct pm860x_rtc_info *info)
+{
+	struct device_node *np = pdev->dev.parent->of_node;
+	int ret;
+	if (!np)
+		return -ENODEV;
+	np = of_find_node_by_name(np, "rtc");
+	if (!np) {
+		dev_err(&pdev->dev, "failed to find rtc node\n");
+		return -ENODEV;
+	}
+	ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc);
+	if (ret)
+		info->vrtc = 0;
+	return 0;
+}
+#else
+#define pm860x_rtc_dt_init(x, y)	(-1)
+#endif
+
 static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 {
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -294,8 +317,6 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 	int ret;
 	int ret;
 
 
 	pdata = pdev->dev.platform_data;
 	pdata = pdev->dev.platform_data;
-	if (pdata == NULL)
-		dev_warn(&pdev->dev, "No platform data!\n");
 
 
 	info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL);
 	info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL);
 	if (!info)
 	if (!info)
@@ -345,9 +366,11 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 	rtc_tm_to_time(&tm, &ticks);
 	rtc_tm_to_time(&tm, &ticks);
-	if (pdata && pdata->sync) {
-		pdata->sync(ticks);
-		info->sync = pdata->sync;
+	if (pm860x_rtc_dt_init(pdev, info)) {
+		if (pdata && pdata->sync) {
+			pdata->sync(ticks);
+			info->sync = pdata->sync;
+		}
 	}
 	}
 
 
 	info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev,
 	info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev,
@@ -366,10 +389,12 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 
 
 #ifdef VRTC_CALIBRATION
 #ifdef VRTC_CALIBRATION
 	/* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
 	/* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
-	if (pdata && pdata->vrtc)
-		info->vrtc = pdata->vrtc & 0x3;
-	else
-		info->vrtc = 1;
+	if (pm860x_rtc_dt_init(pdev, info)) {
+		if (pdata && pdata->vrtc)
+			info->vrtc = pdata->vrtc & 0x3;
+		else
+			info->vrtc = 1;
+	}
 	pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
 	pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
 
 
 	/* calibrate VRTC */
 	/* calibrate VRTC */

+ 79 - 67
drivers/video/backlight/88pm860x_bl.c

@@ -11,6 +11,7 @@
 
 
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/fb.h>
@@ -31,57 +32,26 @@ struct pm860x_backlight_data {
 	int	port;
 	int	port;
 	int	pwm;
 	int	pwm;
 	int	iset;
 	int	iset;
+	int	reg_duty_cycle;
+	int	reg_always_on;
+	int	reg_current;
 };
 };
 
 
-static inline int wled_a(int port)
-{
-	int ret;
-
-	ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
-	return ret;
-}
-
-static inline int wled_b(int port)
-{
-	int ret;
-
-	ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
-	return ret;
-}
-
-/* WLED2 & WLED3 share the same IDC */
-static inline int wled_idc(int port)
-{
-	int ret;
-
-	switch (port) {
-	case PM8606_BACKLIGHT1:
-	case PM8606_BACKLIGHT2:
-		ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
-		break;
-	case PM8606_BACKLIGHT3:
-	default:
-		ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
-		break;
-	}
-	return ret;
-}
-
 static int backlight_power_set(struct pm860x_chip *chip, int port,
 static int backlight_power_set(struct pm860x_chip *chip, int port,
 		int on)
 		int on)
 {
 {
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
 	switch (port) {
 	switch (port) {
-	case PM8606_BACKLIGHT1:
+	case 0:
 		ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) :
 		ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) :
 			pm8606_osc_disable(chip, WLED1_DUTY);
 			pm8606_osc_disable(chip, WLED1_DUTY);
 		break;
 		break;
-	case PM8606_BACKLIGHT2:
+	case 1:
 		ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) :
 		ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) :
 			pm8606_osc_disable(chip, WLED2_DUTY);
 			pm8606_osc_disable(chip, WLED2_DUTY);
 		break;
 		break;
-	case PM8606_BACKLIGHT3:
+	case 2:
 		ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) :
 		ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) :
 			pm8606_osc_disable(chip, WLED3_DUTY);
 			pm8606_osc_disable(chip, WLED3_DUTY);
 		break;
 		break;
@@ -104,13 +74,13 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
 	if (brightness)
 	if (brightness)
 		backlight_power_set(chip, data->port, 1);
 		backlight_power_set(chip, data->port, 1);
 
 
-	ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
+	ret = pm860x_reg_write(data->i2c, data->reg_duty_cycle, value);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
 
 
 	if ((data->current_brightness == 0) && brightness) {
 	if ((data->current_brightness == 0) && brightness) {
 		if (data->iset) {
 		if (data->iset) {
-			ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
+			ret = pm860x_set_bits(data->i2c, data->reg_current,
 					      CURRENT_BITMASK, data->iset);
 					      CURRENT_BITMASK, data->iset);
 			if (ret < 0)
 			if (ret < 0)
 				goto out;
 				goto out;
@@ -123,17 +93,17 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
 		}
 		}
 		if (brightness == MAX_BRIGHTNESS) {
 		if (brightness == MAX_BRIGHTNESS) {
 			/* set WLED_ON bit as 100% */
 			/* set WLED_ON bit as 100% */
-			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+			ret = pm860x_set_bits(data->i2c, data->reg_always_on,
 					      PM8606_WLED_ON, PM8606_WLED_ON);
 					      PM8606_WLED_ON, PM8606_WLED_ON);
 		}
 		}
 	} else {
 	} else {
 		if (brightness == MAX_BRIGHTNESS) {
 		if (brightness == MAX_BRIGHTNESS) {
 			/* set WLED_ON bit as 100% */
 			/* set WLED_ON bit as 100% */
-			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+			ret = pm860x_set_bits(data->i2c, data->reg_always_on,
 					      PM8606_WLED_ON, PM8606_WLED_ON);
 					      PM8606_WLED_ON, PM8606_WLED_ON);
 		} else {
 		} else {
 			/* clear WLED_ON bit since it's not 100% */
 			/* clear WLED_ON bit since it's not 100% */
-			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+			ret = pm860x_set_bits(data->i2c, data->reg_always_on,
 					      PM8606_WLED_ON, 0);
 					      PM8606_WLED_ON, 0);
 		}
 		}
 	}
 	}
@@ -174,7 +144,7 @@ static int pm860x_backlight_get_brightness(struct backlight_device *bl)
 	struct pm860x_chip *chip = data->chip;
 	struct pm860x_chip *chip = data->chip;
 	int ret;
 	int ret;
 
 
-	ret = pm860x_reg_read(data->i2c, wled_a(data->port));
+	ret = pm860x_reg_read(data->i2c, data->reg_duty_cycle);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
 	data->current_brightness = ret;
 	data->current_brightness = ret;
@@ -190,45 +160,85 @@ static const struct backlight_ops pm860x_backlight_ops = {
 	.get_brightness	= pm860x_backlight_get_brightness,
 	.get_brightness	= pm860x_backlight_get_brightness,
 };
 };
 
 
+#ifdef CONFIG_OF
+static int pm860x_backlight_dt_init(struct platform_device *pdev,
+				    struct pm860x_backlight_data *data,
+				    char *name)
+{
+	struct device_node *nproot = pdev->dev.parent->of_node, *np;
+	int iset = 0;
+	if (!nproot)
+		return -ENODEV;
+	nproot = of_find_node_by_name(nproot, "backlights");
+	if (!nproot) {
+		dev_err(&pdev->dev, "failed to find backlights node\n");
+		return -ENODEV;
+	}
+	for_each_child_of_node(nproot, np) {
+		if (!of_node_cmp(np->name, name)) {
+			of_property_read_u32(np, "marvell,88pm860x-iset",
+					     &iset);
+			data->iset = PM8606_WLED_CURRENT(iset);
+			of_property_read_u32(np, "marvell,88pm860x-pwm",
+					     &data->pwm);
+			break;
+		}
+	}
+	return 0;
+}
+#else
+#define pm860x_backlight_dt_init(x, y, z)	(-1)
+#endif
+
 static int pm860x_backlight_probe(struct platform_device *pdev)
 static int pm860x_backlight_probe(struct platform_device *pdev)
 {
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_backlight_pdata *pdata = NULL;
+	struct pm860x_backlight_pdata *pdata = pdev->dev.platform_data;
 	struct pm860x_backlight_data *data;
 	struct pm860x_backlight_data *data;
 	struct backlight_device *bl;
 	struct backlight_device *bl;
 	struct resource *res;
 	struct resource *res;
 	struct backlight_properties props;
 	struct backlight_properties props;
 	char name[MFD_NAME_SIZE];
 	char name[MFD_NAME_SIZE];
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource!\n");
-		return -EINVAL;
-	}
-
-	pdata = pdev->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "platform data isn't assigned to "
-			"backlight\n");
-		return -EINVAL;
-	}
+	int ret = 0;
 
 
 	data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_backlight_data),
 	data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_backlight_data),
 			    GFP_KERNEL);
 			    GFP_KERNEL);
 	if (data == NULL)
 	if (data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
-	strncpy(name, res->name, MFD_NAME_SIZE);
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for duty cycle\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_duty_cycle = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resorce for always on\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_always_on = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for current\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_current = res->start;
+
+	memset(name, 0, MFD_NAME_SIZE);
+	sprintf(name, "backlight-%d", pdev->id);
+	data->port = pdev->id;
 	data->chip = chip;
 	data->chip = chip;
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client	\
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client	\
 			: chip->companion;
 			: chip->companion;
 	data->current_brightness = MAX_BRIGHTNESS;
 	data->current_brightness = MAX_BRIGHTNESS;
-	data->pwm = pdata->pwm;
-	data->iset = pdata->iset;
-	data->port = pdata->flags;
-	if (data->port < 0) {
-		dev_err(&pdev->dev, "wrong platform data is assigned");
-		return -EINVAL;
+	if (pm860x_backlight_dt_init(pdev, data, name)) {
+		if (pdata) {
+			data->pwm = pdata->pwm;
+			data->iset = pdata->iset;
+		}
 	}
 	}
 
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	memset(&props, 0, sizeof(struct backlight_properties));
@@ -247,12 +257,14 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	/* read current backlight */
 	/* read current backlight */
 	ret = pm860x_backlight_get_brightness(bl);
 	ret = pm860x_backlight_get_brightness(bl);
 	if (ret < 0)
 	if (ret < 0)
-		goto out;
+		goto out_brt;
 
 
 	backlight_update_status(bl);
 	backlight_update_status(bl);
 	return 0;
 	return 0;
-out:
+out_brt:
 	backlight_device_unregister(bl);
 	backlight_device_unregister(bl);
+out:
+	devm_kfree(&pdev->dev, data);
 	return ret;
 	return ret;
 }
 }
 
 

+ 7 - 0
drivers/video/backlight/Kconfig

@@ -373,6 +373,13 @@ config BACKLIGHT_PANDORA
 	  If you have a Pandora console, say Y to enable the
 	  If you have a Pandora console, say Y to enable the
 	  backlight driver.
 	  backlight driver.
 
 
+config BACKLIGHT_TPS65217
+	tristate "TPS65217 Backlight"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
+	help
+	  If you have a Texas Instruments TPS65217 say Y to enable the
+	  backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 endif # BACKLIGHT_CLASS_DEVICE
 
 
 endif # BACKLIGHT_LCD_SUPPORT
 endif # BACKLIGHT_LCD_SUPPORT

+ 1 - 0
drivers/video/backlight/Makefile

@@ -43,3 +43,4 @@ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o

+ 41 - 38
drivers/video/backlight/max8925_bl.c

@@ -27,7 +27,9 @@
 struct max8925_backlight_data {
 struct max8925_backlight_data {
 	struct max8925_chip	*chip;
 	struct max8925_chip	*chip;
 
 
-	int		current_brightness;
+	int	current_brightness;
+	int	reg_mode_cntl;
+	int	reg_cntl;
 };
 };
 
 
 static int max8925_backlight_set(struct backlight_device *bl, int brightness)
 static int max8925_backlight_set(struct backlight_device *bl, int brightness)
@@ -42,16 +44,16 @@ static int max8925_backlight_set(struct backlight_device *bl, int brightness)
 	else
 	else
 		value = brightness;
 		value = brightness;
 
 
-	ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
+	ret = max8925_reg_write(chip->i2c, data->reg_cntl, value);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
 
 
 	if (!data->current_brightness && brightness)
 	if (!data->current_brightness && brightness)
 		/* enable WLED output */
 		/* enable WLED output */
-		ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
+		ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 1, 1);
 	else if (!brightness)
 	else if (!brightness)
 		/* disable WLED output */
 		/* disable WLED output */
-		ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
+		ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 1, 0);
 	if (ret < 0)
 	if (ret < 0)
 		goto out;
 		goto out;
 	dev_dbg(chip->dev, "set brightness %d\n", value);
 	dev_dbg(chip->dev, "set brightness %d\n", value);
@@ -85,7 +87,7 @@ static int max8925_backlight_get_brightness(struct backlight_device *bl)
 	struct max8925_chip *chip = data->chip;
 	struct max8925_chip *chip = data->chip;
 	int ret;
 	int ret;
 
 
-	ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
+	ret = max8925_reg_read(chip->i2c, data->reg_cntl);
 	if (ret < 0)
 	if (ret < 0)
 		return -EINVAL;
 		return -EINVAL;
 	data->current_brightness = ret;
 	data->current_brightness = ret;
@@ -102,69 +104,70 @@ static const struct backlight_ops max8925_backlight_ops = {
 static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 {
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct max8925_platform_data *max8925_pdata;
-	struct max8925_backlight_pdata *pdata = NULL;
+	struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
 	struct max8925_backlight_data *data;
 	struct max8925_backlight_data *data;
 	struct backlight_device *bl;
 	struct backlight_device *bl;
 	struct backlight_properties props;
 	struct backlight_properties props;
 	struct resource *res;
 	struct resource *res;
-	char name[MAX8925_NAME_SIZE];
 	unsigned char value;
 	unsigned char value;
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource!\n");
-		return -EINVAL;
-	}
-
-	if (pdev->dev.parent->platform_data) {
-		max8925_pdata = pdev->dev.parent->platform_data;
-		pdata = max8925_pdata->backlight;
-	}
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "platform data isn't assigned to "
-			"backlight\n");
-		return -EINVAL;
-	}
+	int ret = 0;
 
 
 	data = devm_kzalloc(&pdev->dev, sizeof(struct max8925_backlight_data),
 	data = devm_kzalloc(&pdev->dev, sizeof(struct max8925_backlight_data),
 			    GFP_KERNEL);
 			    GFP_KERNEL);
 	if (data == NULL)
 	if (data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
-	strncpy(name, res->name, MAX8925_NAME_SIZE);
+
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for mode control!\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_mode_cntl = res->start;
+	res = platform_get_resource(pdev, IORESOURCE_REG, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for control!\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_cntl = res->start;
+
 	data->chip = chip;
 	data->chip = chip;
 	data->current_brightness = 0;
 	data->current_brightness = 0;
 
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = MAX_BRIGHTNESS;
 	props.max_brightness = MAX_BRIGHTNESS;
-	bl = backlight_device_register(name, &pdev->dev, data,
+	bl = backlight_device_register("max8925-backlight", &pdev->dev, data,
 					&max8925_backlight_ops, &props);
 					&max8925_backlight_ops, &props);
 	if (IS_ERR(bl)) {
 	if (IS_ERR(bl)) {
 		dev_err(&pdev->dev, "failed to register backlight\n");
 		dev_err(&pdev->dev, "failed to register backlight\n");
-		return PTR_ERR(bl);
+		ret = PTR_ERR(bl);
+		goto out;
 	}
 	}
 	bl->props.brightness = MAX_BRIGHTNESS;
 	bl->props.brightness = MAX_BRIGHTNESS;
 
 
 	platform_set_drvdata(pdev, bl);
 	platform_set_drvdata(pdev, bl);
 
 
 	value = 0;
 	value = 0;
-	if (pdata->lxw_scl)
-		value |= (1 << 7);
-	if (pdata->lxw_freq)
-		value |= (LWX_FREQ(pdata->lxw_freq) << 4);
-	if (pdata->dual_string)
-		value |= (1 << 1);
-	ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
+	if (pdata) {
+		if (pdata->lxw_scl)
+			value |= (1 << 7);
+		if (pdata->lxw_freq)
+			value |= (LWX_FREQ(pdata->lxw_freq) << 4);
+		if (pdata->dual_string)
+			value |= (1 << 1);
+	}
+	ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value);
 	if (ret < 0)
 	if (ret < 0)
-		goto out;
+		goto out_brt;
 
 
 	backlight_update_status(bl);
 	backlight_update_status(bl);
 	return 0;
 	return 0;
-out:
+out_brt:
 	backlight_device_unregister(bl);
 	backlight_device_unregister(bl);
+out:
+	devm_kfree(&pdev->dev, data);
 	return ret;
 	return ret;
 }
 }
 
 

+ 342 - 0
drivers/video/backlight/tps65217_bl.c

@@ -0,0 +1,342 @@
+/*
+ * tps65217_bl.c
+ *
+ * TPS65217 backlight driver
+ *
+ * Copyright (C) 2012 Matthias Kaehlcke
+ * Author: Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/mfd/tps65217.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct tps65217_bl {
+	struct tps65217 *tps;
+	struct device *dev;
+	struct backlight_device *bl;
+	bool is_enabled;
+};
+
+static int tps65217_bl_enable(struct tps65217_bl *tps65217_bl)
+{
+	int rc;
+
+	rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+			TPS65217_WLEDCTRL1_ISINK_ENABLE,
+			TPS65217_WLEDCTRL1_ISINK_ENABLE, TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to enable backlight: %d\n", rc);
+		return rc;
+	}
+
+	tps65217_bl->is_enabled = true;
+
+	dev_dbg(tps65217_bl->dev, "backlight enabled\n");
+
+	return 0;
+}
+
+static int tps65217_bl_disable(struct tps65217_bl *tps65217_bl)
+{
+	int rc;
+
+	rc = tps65217_clear_bits(tps65217_bl->tps,
+				TPS65217_REG_WLEDCTRL1,
+				TPS65217_WLEDCTRL1_ISINK_ENABLE,
+				TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to disable backlight: %d\n", rc);
+		return rc;
+	}
+
+	tps65217_bl->is_enabled = false;
+
+	dev_dbg(tps65217_bl->dev, "backlight disabled\n");
+
+	return 0;
+}
+
+static int tps65217_bl_update_status(struct backlight_device *bl)
+{
+	struct tps65217_bl *tps65217_bl = bl_get_data(bl);
+	int rc;
+	int brightness = bl->props.brightness;
+
+	if (bl->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
+	if ((bl->props.power != FB_BLANK_UNBLANK) ||
+		(bl->props.fb_blank != FB_BLANK_UNBLANK))
+		/* framebuffer in low power mode or blanking active */
+		brightness = 0;
+
+	if (brightness > 0) {
+		rc = tps65217_reg_write(tps65217_bl->tps,
+					TPS65217_REG_WLEDCTRL2,
+					brightness - 1,
+					TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to set brightness level: %d\n", rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
+
+		if (!tps65217_bl->is_enabled)
+			rc = tps65217_bl_enable(tps65217_bl);
+	} else {
+		rc = tps65217_bl_disable(tps65217_bl);
+	}
+
+	return rc;
+}
+
+static int tps65217_bl_get_brightness(struct backlight_device *bl)
+{
+	return bl->props.brightness;
+}
+
+static const struct backlight_ops tps65217_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= tps65217_bl_update_status,
+	.get_brightness	= tps65217_bl_get_brightness
+};
+
+static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
+			struct tps65217_bl_pdata *pdata)
+{
+	int rc;
+
+	rc = tps65217_bl_disable(tps65217_bl);
+	if (rc)
+		return rc;
+
+	switch (pdata->isel) {
+	case TPS65217_BL_ISET1:
+		/* select ISET_1 current level */
+		rc = tps65217_clear_bits(tps65217_bl->tps,
+					TPS65217_REG_WLEDCTRL1,
+					TPS65217_WLEDCTRL1_ISEL,
+					TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to select ISET1 current level: %d)\n",
+				rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "selected ISET1 current level\n");
+
+		break;
+
+	case TPS65217_BL_ISET2:
+		/* select ISET2 current level */
+		rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+				TPS65217_WLEDCTRL1_ISEL,
+				TPS65217_WLEDCTRL1_ISEL, TPS65217_PROTECT_NONE);
+		if (rc) {
+			dev_err(tps65217_bl->dev,
+				"failed to select ISET2 current level: %d\n",
+				rc);
+			return rc;
+		}
+
+		dev_dbg(tps65217_bl->dev, "selected ISET2 current level\n");
+
+		break;
+
+	default:
+		dev_err(tps65217_bl->dev,
+			"invalid value for current level: %d\n", pdata->isel);
+		return -EINVAL;
+	}
+
+	/* set PWM frequency */
+	rc = tps65217_set_bits(tps65217_bl->tps,
+			TPS65217_REG_WLEDCTRL1,
+			TPS65217_WLEDCTRL1_FDIM_MASK,
+			pdata->fdim,
+			TPS65217_PROTECT_NONE);
+	if (rc) {
+		dev_err(tps65217_bl->dev,
+			"failed to select PWM dimming frequency: %d\n",
+			rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct tps65217_bl_pdata *
+tps65217_bl_parse_dt(struct platform_device *pdev)
+{
+	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *node = of_node_get(tps->dev->of_node);
+	struct tps65217_bl_pdata *pdata, *err;
+	u32 val;
+
+	node = of_find_node_by_name(node, "backlight");
+	if (!node)
+		return ERR_PTR(-ENODEV);
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "failed to allocate platform data\n");
+		err = ERR_PTR(-ENOMEM);
+		goto err;
+	}
+
+	pdata->isel = TPS65217_BL_ISET1;
+	if (!of_property_read_u32(node, "isel", &val)) {
+		if (val < TPS65217_BL_ISET1 ||
+			val > TPS65217_BL_ISET2) {
+			dev_err(&pdev->dev,
+				"invalid 'isel' value in the device tree\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		pdata->isel = val;
+	}
+
+	pdata->fdim = TPS65217_BL_FDIM_200HZ;
+	if (!of_property_read_u32(node, "fdim", &val)) {
+		switch (val) {
+		case 100:
+			pdata->fdim = TPS65217_BL_FDIM_100HZ;
+			break;
+
+		case 200:
+			pdata->fdim = TPS65217_BL_FDIM_200HZ;
+			break;
+
+		case 500:
+			pdata->fdim = TPS65217_BL_FDIM_500HZ;
+			break;
+
+		case 1000:
+			pdata->fdim = TPS65217_BL_FDIM_1000HZ;
+			break;
+
+		default:
+			dev_err(&pdev->dev,
+				"invalid 'fdim' value in the device tree\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+	}
+
+	of_node_put(node);
+
+	return pdata;
+
+err:
+	of_node_put(node);
+
+	return err;
+}
+#else
+static struct tps65217_bl_pdata *
+tps65217_bl_parse_dt(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
+static int tps65217_bl_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct tps65217_bl *tps65217_bl;
+	struct tps65217_bl_pdata *pdata;
+	struct backlight_properties bl_props;
+
+	if (tps->dev->of_node) {
+		pdata = tps65217_bl_parse_dt(pdev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	} else {
+		if (!pdev->dev.platform_data) {
+			dev_err(&pdev->dev, "no platform data provided\n");
+			return -EINVAL;
+		}
+
+		pdata = pdev->dev.platform_data;
+	}
+
+	tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
+				GFP_KERNEL);
+	if (tps65217_bl == NULL) {
+		dev_err(&pdev->dev, "allocation of struct tps65217_bl failed\n");
+		return -ENOMEM;
+	}
+
+	tps65217_bl->tps = tps;
+	tps65217_bl->dev = &pdev->dev;
+	tps65217_bl->is_enabled = false;
+
+	rc = tps65217_bl_hw_init(tps65217_bl, pdata);
+	if (rc)
+		return rc;
+
+	memset(&bl_props, 0, sizeof(struct backlight_properties));
+	bl_props.type = BACKLIGHT_RAW;
+	bl_props.max_brightness = 100;
+
+	tps65217_bl->bl = backlight_device_register(pdev->name,
+						tps65217_bl->dev, tps65217_bl,
+						&tps65217_bl_ops, &bl_props);
+	if (IS_ERR(tps65217_bl->bl)) {
+		dev_err(tps65217_bl->dev,
+			"registration of backlight device failed: %d\n", rc);
+		return PTR_ERR(tps65217_bl->bl);
+	}
+
+	tps65217_bl->bl->props.brightness = 0;
+	platform_set_drvdata(pdev, tps65217_bl);
+
+	return 0;
+}
+
+static int tps65217_bl_remove(struct platform_device *pdev)
+{
+	struct tps65217_bl *tps65217_bl = platform_get_drvdata(pdev);
+
+	backlight_device_unregister(tps65217_bl->bl);
+
+	return 0;
+}
+
+static struct platform_driver tps65217_bl_driver = {
+	.probe		= tps65217_bl_probe,
+	.remove		= tps65217_bl_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "tps65217-bl",
+	},
+};
+
+module_platform_driver(tps65217_bl_driver);
+
+MODULE_DESCRIPTION("TPS65217 Backlight driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Matthias Kaehlcke <matthias@kaehlcke.net>");

+ 1 - 0
drivers/watchdog/iTCO_wdt.c

@@ -37,6 +37,7 @@
  *	document number TBD                   : DH89xxCC
  *	document number TBD                   : DH89xxCC
  *	document number TBD                   : Panther Point
  *	document number TBD                   : Panther Point
  *	document number TBD                   : Lynx Point
  *	document number TBD                   : Lynx Point
+ *	document number TBD                   : Lynx Point-LP
  */
  */
 
 
 /*
 /*

+ 1 - 0
include/linux/i2c/twl.h

@@ -188,6 +188,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
 
 
 int twl_get_type(void);
 int twl_get_type(void);
 int twl_get_version(void);
 int twl_get_version(void);
+int twl_get_hfclk_rate(void);
 
 
 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
 int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
 int twl6030_interrupt_mask(u8 bit_mask, u8 offset);

+ 2 - 1
include/linux/ioport.h

@@ -29,8 +29,9 @@ struct resource {
 #define IORESOURCE_BITS		0x000000ff	/* Bus-specific bits */
 #define IORESOURCE_BITS		0x000000ff	/* Bus-specific bits */
 
 
 #define IORESOURCE_TYPE_BITS	0x00001f00	/* Resource type */
 #define IORESOURCE_TYPE_BITS	0x00001f00	/* Resource type */
-#define IORESOURCE_IO		0x00000100
+#define IORESOURCE_IO		0x00000100	/* PCI/ISA I/O ports */
 #define IORESOURCE_MEM		0x00000200
 #define IORESOURCE_MEM		0x00000200
+#define IORESOURCE_REG		0x00000300	/* Register offsets */
 #define IORESOURCE_IRQ		0x00000400
 #define IORESOURCE_IRQ		0x00000400
 #define IORESOURCE_DMA		0x00000800
 #define IORESOURCE_DMA		0x00000800
 #define IORESOURCE_BUS		0x00001000
 #define IORESOURCE_BUS		0x00001000

+ 19 - 29
include/linux/mfd/88pm860x.h

@@ -34,22 +34,6 @@ enum {
 	PM8606_ID_MAX,
 	PM8606_ID_MAX,
 };
 };
 
 
-enum {
-	PM8606_BACKLIGHT1 = 0,
-	PM8606_BACKLIGHT2,
-	PM8606_BACKLIGHT3,
-};
-
-enum {
-	PM8606_LED1_RED = 0,
-	PM8606_LED1_GREEN,
-	PM8606_LED1_BLUE,
-	PM8606_LED2_RED,
-	PM8606_LED2_GREEN,
-	PM8606_LED2_BLUE,
-	PM8607_LED_VIBRATOR,
-};
-
 
 
 /* 8606 Registers */
 /* 8606 Registers */
 #define PM8606_DCM_BOOST		(0x00)
 #define PM8606_DCM_BOOST		(0x00)
@@ -322,7 +306,7 @@ struct pm860x_chip {
 	struct regmap           *regmap_companion;
 	struct regmap           *regmap_companion;
 
 
 	int			buck3_double;	/* DVC ramp slope double */
 	int			buck3_double;	/* DVC ramp slope double */
-	unsigned short		companion_addr;
+	int			companion_addr;
 	unsigned short		osc_vote;
 	unsigned short		osc_vote;
 	int			id;
 	int			id;
 	int			irq_mode;
 	int			irq_mode;
@@ -340,16 +324,12 @@ enum {
 };
 };
 
 
 struct pm860x_backlight_pdata {
 struct pm860x_backlight_pdata {
-	int		id;
 	int		pwm;
 	int		pwm;
 	int		iset;
 	int		iset;
-	unsigned long	flags;
 };
 };
 
 
 struct pm860x_led_pdata {
 struct pm860x_led_pdata {
-	int		id;
 	int		iset;
 	int		iset;
-	unsigned long	flags;
 };
 };
 
 
 struct pm860x_rtc_pdata {
 struct pm860x_rtc_pdata {
@@ -379,15 +359,29 @@ struct pm860x_platform_data {
 	struct pm860x_rtc_pdata		*rtc;
 	struct pm860x_rtc_pdata		*rtc;
 	struct pm860x_touch_pdata	*touch;
 	struct pm860x_touch_pdata	*touch;
 	struct pm860x_power_pdata	*power;
 	struct pm860x_power_pdata	*power;
-	struct regulator_init_data	*regulator;
-
-	unsigned short	companion_addr;	/* I2C address of companion chip */
+	struct regulator_init_data	*buck1;
+	struct regulator_init_data	*buck2;
+	struct regulator_init_data	*buck3;
+	struct regulator_init_data	*ldo1;
+	struct regulator_init_data	*ldo2;
+	struct regulator_init_data	*ldo3;
+	struct regulator_init_data	*ldo4;
+	struct regulator_init_data	*ldo5;
+	struct regulator_init_data	*ldo6;
+	struct regulator_init_data	*ldo7;
+	struct regulator_init_data	*ldo8;
+	struct regulator_init_data	*ldo9;
+	struct regulator_init_data	*ldo10;
+	struct regulator_init_data	*ldo12;
+	struct regulator_init_data	*ldo_vibrator;
+	struct regulator_init_data	*ldo14;
+
+	int 		companion_addr;	/* I2C address of companion chip */
 	int		i2c_port;	/* Controlled by GI2C or PI2C */
 	int		i2c_port;	/* Controlled by GI2C or PI2C */
 	int		irq_mode;	/* Clear interrupt by read/write(0/1) */
 	int		irq_mode;	/* Clear interrupt by read/write(0/1) */
 	int		irq_base;	/* IRQ base number of 88pm860x */
 	int		irq_base;	/* IRQ base number of 88pm860x */
 	int		num_leds;
 	int		num_leds;
 	int		num_backlights;
 	int		num_backlights;
-	int		num_regulators;
 };
 };
 
 
 extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
 extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
@@ -408,8 +402,4 @@ extern int pm860x_page_bulk_write(struct i2c_client *, int, int,
 extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char,
 extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char,
 				unsigned char);
 				unsigned char);
 
 
-extern int pm860x_device_init(struct pm860x_chip *chip,
-			      struct pm860x_platform_data *pdata) __devinit ;
-extern void pm860x_device_exit(struct pm860x_chip *chip) __devexit ;
-
 #endif /* __LINUX_MFD_88PM860X_H */
 #endif /* __LINUX_MFD_88PM860X_H */

+ 129 - 0
include/linux/mfd/ab3100.h

@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * AB3100 core access functions
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+
+#include <linux/regulator/machine.h>
+
+struct device;
+
+#ifndef MFD_AB3100_H
+#define MFD_AB3100_H
+
+
+#define AB3100_P1A	0xc0
+#define AB3100_P1B	0xc1
+#define AB3100_P1C	0xc2
+#define AB3100_P1D	0xc3
+#define AB3100_P1E	0xc4
+#define AB3100_P1F	0xc5
+#define AB3100_P1G	0xc6
+#define AB3100_R2A	0xc7
+#define AB3100_R2B	0xc8
+
+/*
+ * AB3100, EVENTA1, A2 and A3 event register flags
+ * these are catenated into a single 32-bit flag in the code
+ * for event notification broadcasts.
+ */
+#define AB3100_EVENTA1_ONSWA				(0x01<<16)
+#define AB3100_EVENTA1_ONSWB				(0x02<<16)
+#define AB3100_EVENTA1_ONSWC				(0x04<<16)
+#define AB3100_EVENTA1_DCIO				(0x08<<16)
+#define AB3100_EVENTA1_OVER_TEMP			(0x10<<16)
+#define AB3100_EVENTA1_SIM_OFF				(0x20<<16)
+#define AB3100_EVENTA1_VBUS				(0x40<<16)
+#define AB3100_EVENTA1_VSET_USB				(0x80<<16)
+
+#define AB3100_EVENTA2_READY_TX				(0x01<<8)
+#define AB3100_EVENTA2_READY_RX				(0x02<<8)
+#define AB3100_EVENTA2_OVERRUN_ERROR			(0x04<<8)
+#define AB3100_EVENTA2_FRAMING_ERROR			(0x08<<8)
+#define AB3100_EVENTA2_CHARG_OVERCURRENT		(0x10<<8)
+#define AB3100_EVENTA2_MIDR				(0x20<<8)
+#define AB3100_EVENTA2_BATTERY_REM			(0x40<<8)
+#define AB3100_EVENTA2_ALARM				(0x80<<8)
+
+#define AB3100_EVENTA3_ADC_TRIG5			(0x01)
+#define AB3100_EVENTA3_ADC_TRIG4			(0x02)
+#define AB3100_EVENTA3_ADC_TRIG3			(0x04)
+#define AB3100_EVENTA3_ADC_TRIG2			(0x08)
+#define AB3100_EVENTA3_ADC_TRIGVBAT			(0x10)
+#define AB3100_EVENTA3_ADC_TRIGVTX			(0x20)
+#define AB3100_EVENTA3_ADC_TRIG1			(0x40)
+#define AB3100_EVENTA3_ADC_TRIG0			(0x80)
+
+/* AB3100, STR register flags */
+#define AB3100_STR_ONSWA				(0x01)
+#define AB3100_STR_ONSWB				(0x02)
+#define AB3100_STR_ONSWC				(0x04)
+#define AB3100_STR_DCIO					(0x08)
+#define AB3100_STR_BOOT_MODE				(0x10)
+#define AB3100_STR_SIM_OFF				(0x20)
+#define AB3100_STR_BATT_REMOVAL				(0x40)
+#define AB3100_STR_VBUS					(0x80)
+
+/*
+ * AB3100 contains 8 regulators, one external regulator controller
+ * and a buck converter, further the LDO E and buck converter can
+ * have separate settings if they are in sleep mode, this is
+ * modeled as a separate regulator.
+ */
+#define AB3100_NUM_REGULATORS				10
+
+/**
+ * struct ab3100
+ * @access_mutex: lock out concurrent accesses to the AB3100 registers
+ * @dev: pointer to the containing device
+ * @i2c_client: I2C client for this chip
+ * @testreg_client: secondary client for test registers
+ * @chip_name: name of this chip variant
+ * @chip_id: 8 bit chip ID for this chip variant
+ * @event_subscribers: event subscribers are listed here
+ * @startup_events: a copy of the first reading of the event registers
+ * @startup_events_read: whether the first events have been read
+ *
+ * This struct is PRIVATE and devices using it should NOT
+ * access ANY fields. It is used as a token for calling the
+ * AB3100 functions.
+ */
+struct ab3100 {
+	struct mutex access_mutex;
+	struct device *dev;
+	struct i2c_client *i2c_client;
+	struct i2c_client *testreg_client;
+	char chip_name[32];
+	u8 chip_id;
+	struct blocking_notifier_head event_subscribers;
+	u8 startup_events[3];
+	bool startup_events_read;
+};
+
+/**
+ * struct ab3100_platform_data
+ * Data supplied to initialize board connections to the AB3100
+ * @reg_constraints: regulator constraints for target board
+ *     the order of these constraints are: LDO A, C, D, E,
+ *     F, G, H, K, EXT and BUCK.
+ * @reg_initvals: initial values for the regulator registers
+ *     plus two sleep settings for LDO E and the BUCK converter.
+ *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
+ *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
+ *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
+ * @external_voltage: voltage level of the external regulator.
+ */
+struct ab3100_platform_data {
+	struct regulator_init_data reg_constraints[AB3100_NUM_REGULATORS];
+	u8 reg_initvals[AB3100_NUM_REGULATORS+2];
+	int external_voltage;
+};
+
+int ab3100_event_register(struct ab3100 *ab3100,
+			  struct notifier_block *nb);
+int ab3100_event_unregister(struct ab3100 *ab3100,
+			    struct notifier_block *nb);
+
+#endif /*  MFD_AB3100_H */

+ 1 - 116
include/linux/mfd/abx500.h

@@ -1,12 +1,9 @@
 /*
 /*
  * Copyright (C) 2007-2009 ST-Ericsson AB
  * Copyright (C) 2007-2009 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
  * License terms: GNU General Public License (GPL) version 2
- * AB3100 core access functions
- * Author: Linus Walleij <linus.walleij@stericsson.com>
  *
  *
  * ABX500 core access functions.
  * ABX500 core access functions.
- * The abx500 interface is used for the Analog Baseband chip
- * ab3100 and ab8500.
+ * The abx500 interface is used for the Analog Baseband chips.
  *
  *
  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
@@ -21,118 +18,6 @@ struct device;
 #ifndef MFD_ABX500_H
 #ifndef MFD_ABX500_H
 #define MFD_ABX500_H
 #define MFD_ABX500_H
 
 
-#define AB3100_P1A	0xc0
-#define AB3100_P1B	0xc1
-#define AB3100_P1C	0xc2
-#define AB3100_P1D	0xc3
-#define AB3100_P1E	0xc4
-#define AB3100_P1F	0xc5
-#define AB3100_P1G	0xc6
-#define AB3100_R2A	0xc7
-#define AB3100_R2B	0xc8
-
-/*
- * AB3100, EVENTA1, A2 and A3 event register flags
- * these are catenated into a single 32-bit flag in the code
- * for event notification broadcasts.
- */
-#define AB3100_EVENTA1_ONSWA				(0x01<<16)
-#define AB3100_EVENTA1_ONSWB				(0x02<<16)
-#define AB3100_EVENTA1_ONSWC				(0x04<<16)
-#define AB3100_EVENTA1_DCIO				(0x08<<16)
-#define AB3100_EVENTA1_OVER_TEMP			(0x10<<16)
-#define AB3100_EVENTA1_SIM_OFF				(0x20<<16)
-#define AB3100_EVENTA1_VBUS				(0x40<<16)
-#define AB3100_EVENTA1_VSET_USB				(0x80<<16)
-
-#define AB3100_EVENTA2_READY_TX				(0x01<<8)
-#define AB3100_EVENTA2_READY_RX				(0x02<<8)
-#define AB3100_EVENTA2_OVERRUN_ERROR			(0x04<<8)
-#define AB3100_EVENTA2_FRAMING_ERROR			(0x08<<8)
-#define AB3100_EVENTA2_CHARG_OVERCURRENT		(0x10<<8)
-#define AB3100_EVENTA2_MIDR				(0x20<<8)
-#define AB3100_EVENTA2_BATTERY_REM			(0x40<<8)
-#define AB3100_EVENTA2_ALARM				(0x80<<8)
-
-#define AB3100_EVENTA3_ADC_TRIG5			(0x01)
-#define AB3100_EVENTA3_ADC_TRIG4			(0x02)
-#define AB3100_EVENTA3_ADC_TRIG3			(0x04)
-#define AB3100_EVENTA3_ADC_TRIG2			(0x08)
-#define AB3100_EVENTA3_ADC_TRIGVBAT			(0x10)
-#define AB3100_EVENTA3_ADC_TRIGVTX			(0x20)
-#define AB3100_EVENTA3_ADC_TRIG1			(0x40)
-#define AB3100_EVENTA3_ADC_TRIG0			(0x80)
-
-/* AB3100, STR register flags */
-#define AB3100_STR_ONSWA				(0x01)
-#define AB3100_STR_ONSWB				(0x02)
-#define AB3100_STR_ONSWC				(0x04)
-#define AB3100_STR_DCIO					(0x08)
-#define AB3100_STR_BOOT_MODE				(0x10)
-#define AB3100_STR_SIM_OFF				(0x20)
-#define AB3100_STR_BATT_REMOVAL				(0x40)
-#define AB3100_STR_VBUS					(0x80)
-
-/*
- * AB3100 contains 8 regulators, one external regulator controller
- * and a buck converter, further the LDO E and buck converter can
- * have separate settings if they are in sleep mode, this is
- * modeled as a separate regulator.
- */
-#define AB3100_NUM_REGULATORS				10
-
-/**
- * struct ab3100
- * @access_mutex: lock out concurrent accesses to the AB3100 registers
- * @dev: pointer to the containing device
- * @i2c_client: I2C client for this chip
- * @testreg_client: secondary client for test registers
- * @chip_name: name of this chip variant
- * @chip_id: 8 bit chip ID for this chip variant
- * @event_subscribers: event subscribers are listed here
- * @startup_events: a copy of the first reading of the event registers
- * @startup_events_read: whether the first events have been read
- *
- * This struct is PRIVATE and devices using it should NOT
- * access ANY fields. It is used as a token for calling the
- * AB3100 functions.
- */
-struct ab3100 {
-	struct mutex access_mutex;
-	struct device *dev;
-	struct i2c_client *i2c_client;
-	struct i2c_client *testreg_client;
-	char chip_name[32];
-	u8 chip_id;
-	struct blocking_notifier_head event_subscribers;
-	u8 startup_events[3];
-	bool startup_events_read;
-};
-
-/**
- * struct ab3100_platform_data
- * Data supplied to initialize board connections to the AB3100
- * @reg_constraints: regulator constraints for target board
- *     the order of these constraints are: LDO A, C, D, E,
- *     F, G, H, K, EXT and BUCK.
- * @reg_initvals: initial values for the regulator registers
- *     plus two sleep settings for LDO E and the BUCK converter.
- *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
- *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
- *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
- * @external_voltage: voltage level of the external regulator.
- */
-struct ab3100_platform_data {
-	struct regulator_init_data reg_constraints[AB3100_NUM_REGULATORS];
-	u8 reg_initvals[AB3100_NUM_REGULATORS+2];
-	int external_voltage;
-};
-
-int ab3100_event_register(struct ab3100 *ab3100,
-			  struct notifier_block *nb);
-int ab3100_event_unregister(struct ab3100 *ab3100,
-			    struct notifier_block *nb);
-
 /**
 /**
  * struct abx500_init_setting
  * struct abx500_init_setting
  * Initial value of the registers for driver to use during setup.
  * Initial value of the registers for driver to use during setup.

+ 0 - 2
include/linux/mfd/abx500/ab8500.h

@@ -341,6 +341,4 @@ static inline int is_ab8500_2p0(struct ab8500 *ab)
 	return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
 	return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
 }
 }
 
 
-int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq);
-
 #endif /* MFD_AB8500_H */
 #endif /* MFD_AB8500_H */

+ 0 - 40
include/linux/mfd/anatop.h

@@ -1,40 +0,0 @@
-/*
- * anatop.h - Anatop MFD driver
- *
- *  Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
- *  Copyright (C) 2012 Linaro
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __LINUX_MFD_ANATOP_H
-#define __LINUX_MFD_ANATOP_H
-
-#include <linux/spinlock.h>
-
-/**
- * anatop - MFD data
- * @ioreg: ioremap register
- * @reglock: spinlock for register read/write
- */
-struct anatop {
-	void *ioreg;
-	spinlock_t reglock;
-};
-
-extern u32 anatop_read_reg(struct anatop *, u32);
-extern void anatop_write_reg(struct anatop *, u32, u32, u32);
-
-#endif /*  __LINUX_MFD_ANATOP_H */

+ 94 - 0
include/linux/mfd/da9055/core.h

@@ -0,0 +1,94 @@
+/*
+ * da9055 declarations for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DA9055_CORE_H
+#define __DA9055_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+
+/*
+ * PMIC IRQ
+ */
+#define DA9055_IRQ_ALARM	0x01
+#define DA9055_IRQ_TICK		0x02
+#define DA9055_IRQ_NONKEY	0x00
+#define DA9055_IRQ_REGULATOR	0x0B
+#define DA9055_IRQ_HWMON	0x03
+
+struct da9055_pdata;
+
+struct da9055 {
+	struct regmap *regmap;
+	struct regmap_irq_chip_data *irq_data;
+	struct device *dev;
+	struct i2c_client *i2c_client;
+
+	int irq_base;
+	int chip_irq;
+};
+
+/* Device I/O */
+static inline int da9055_reg_read(struct da9055 *da9055, unsigned char reg)
+{
+	int val, ret;
+
+	ret = regmap_read(da9055->regmap, reg, &val);
+	if (ret < 0)
+		return ret;
+
+	return val;
+}
+
+static inline int da9055_reg_write(struct da9055 *da9055, unsigned char reg,
+				    unsigned char val)
+{
+	return regmap_write(da9055->regmap, reg, val);
+}
+
+static inline int da9055_group_read(struct da9055 *da9055, unsigned char reg,
+				     unsigned reg_cnt, unsigned char *val)
+{
+	return regmap_bulk_read(da9055->regmap, reg, val, reg_cnt);
+}
+
+static inline int da9055_group_write(struct da9055 *da9055, unsigned char reg,
+				      unsigned reg_cnt, unsigned char *val)
+{
+	return regmap_raw_write(da9055->regmap, reg, val, reg_cnt);
+}
+
+static inline int da9055_reg_update(struct da9055 *da9055, unsigned char reg,
+				     unsigned char bit_mask,
+				     unsigned char reg_val)
+{
+	return regmap_update_bits(da9055->regmap, reg, bit_mask, reg_val);
+}
+
+/* Generic Device API */
+int da9055_device_init(struct da9055 *da9055);
+void da9055_device_exit(struct da9055 *da9055);
+
+extern struct regmap_config da9055_regmap_config;
+
+#endif /* __DA9055_CORE_H */

+ 32 - 0
include/linux/mfd/da9055/pdata.h

@@ -0,0 +1,32 @@
+/* Copyright (C) 2012 Dialog Semiconductor Ltd.
+ *
+ *  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 __DA9055_PDATA_H
+#define __DA9055_PDATA_H
+
+#define DA9055_MAX_REGULATORS	8
+
+struct da9055;
+
+enum gpio_select {
+	NO_GPIO = 0,
+	GPIO_1,
+	GPIO_2
+};
+
+struct da9055_pdata {
+	int (*init) (struct da9055 *da9055);
+	int irq_base;
+	int gpio_base;
+
+	struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
+	bool reset_enable;		/* Enable RTC in RESET Mode */
+	enum gpio_select *gpio_rsel;	/* Select regulator set thru GPIO 1/2 */
+	enum gpio_select *gpio_ren;	/* Enable regulator thru GPIO 1/2 */
+};
+#endif /* __DA9055_PDATA_H */

+ 699 - 0
include/linux/mfd/da9055/reg.h

@@ -0,0 +1,699 @@
+/*
+ * DA9055 declarations for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DA9055_REG_H
+#define __DA9055_REG_H
+
+/*
+ * PMIC registers
+ */
+ /* PAGE0 */
+#define	DA9055_REG_PAGE_CON		0x00
+
+/* System Control and Event Registers */
+#define	DA9055_REG_STATUS_A		0x01
+#define	DA9055_REG_STATUS_B		0x02
+#define	DA9055_REG_FAULT_LOG		0x03
+#define	DA9055_REG_EVENT_A		0x04
+#define	DA9055_REG_EVENT_B		0x05
+#define	DA9055_REG_EVENT_C		0x06
+#define	DA9055_REG_IRQ_MASK_A		0x07
+#define	DA9055_REG_IRQ_MASK_B		0x08
+#define	DA9055_REG_IRQ_MASK_C		0x09
+#define	DA9055_REG_CONTROL_A		0x0A
+#define	DA9055_REG_CONTROL_B		0x0B
+#define	DA9055_REG_CONTROL_C		0x0C
+#define	DA9055_REG_CONTROL_D		0x0D
+#define	DA9055_REG_CONTROL_E		0x0E
+#define	DA9055_REG_PD_DIS		0x0F
+
+/* GPIO Control Registers */
+#define	DA9055_REG_GPIO0_1		0x10
+#define	DA9055_REG_GPIO2		0x11
+#define	DA9055_REG_GPIO_MODE0_2		0x12
+
+/* Regulator Control Registers */
+#define	DA9055_REG_BCORE_CONT		0x13
+#define	DA9055_REG_BMEM_CONT		0x14
+#define	DA9055_REG_LDO1_CONT		0x15
+#define	DA9055_REG_LDO2_CONT		0x16
+#define	DA9055_REG_LDO3_CONT		0x17
+#define	DA9055_REG_LDO4_CONT		0x18
+#define	DA9055_REG_LDO5_CONT		0x19
+#define	DA9055_REG_LDO6_CONT		0x1A
+
+/* GP-ADC Control Registers */
+#define	DA9055_REG_ADC_MAN		0x1B
+#define	DA9055_REG_ADC_CONT		0x1C
+#define	DA9055_REG_VSYS_MON		0x1D
+#define	DA9055_REG_ADC_RES_L		0x1E
+#define	DA9055_REG_ADC_RES_H		0x1F
+#define	DA9055_REG_VSYS_RES		0x20
+#define	DA9055_REG_ADCIN1_RES		0x21
+#define	DA9055_REG_ADCIN2_RES		0x22
+#define	DA9055_REG_ADCIN3_RES		0x23
+
+/* Sequencer Control Registers */
+#define	DA9055_REG_EN_32K		0x35
+
+/* Regulator Setting Registers */
+#define	DA9055_REG_BUCK_LIM		0x37
+#define	DA9055_REG_BCORE_MODE		0x38
+#define	DA9055_REG_VBCORE_A		0x39
+#define	DA9055_REG_VBMEM_A		0x3A
+#define	DA9055_REG_VLDO1_A		0x3B
+#define	DA9055_REG_VLDO2_A		0x3C
+#define	DA9055_REG_VLDO3_A		0x3D
+#define	DA9055_REG_VLDO4_A		0x3E
+#define	DA9055_REG_VLDO5_A		0x3F
+#define	DA9055_REG_VLDO6_A		0x40
+#define	DA9055_REG_VBCORE_B		0x41
+#define	DA9055_REG_VBMEM_B		0x42
+#define	DA9055_REG_VLDO1_B		0x43
+#define	DA9055_REG_VLDO2_B		0x44
+#define	DA9055_REG_VLDO3_B		0x45
+#define	DA9055_REG_VLDO4_B		0x46
+#define	DA9055_REG_VLDO5_B		0x47
+#define	DA9055_REG_VLDO6_B		0x48
+
+/* GP-ADC Threshold Registers */
+#define	DA9055_REG_AUTO1_HIGH		0x49
+#define	DA9055_REG_AUTO1_LOW		0x4A
+#define	DA9055_REG_AUTO2_HIGH		0x4B
+#define	DA9055_REG_AUTO2_LOW		0x4C
+#define	DA9055_REG_AUTO3_HIGH		0x4D
+#define	DA9055_REG_AUTO3_LOW		0x4E
+
+/* OTP */
+#define	DA9055_REG_OPT_COUNT		0x50
+#define	DA9055_REG_OPT_ADDR		0x51
+#define	DA9055_REG_OPT_DATA		0x52
+
+/* RTC Calendar and Alarm Registers */
+#define	DA9055_REG_COUNT_S		0x53
+#define	DA9055_REG_COUNT_MI		0x54
+#define	DA9055_REG_COUNT_H		0x55
+#define	DA9055_REG_COUNT_D		0x56
+#define	DA9055_REG_COUNT_MO		0x57
+#define	DA9055_REG_COUNT_Y		0x58
+#define	DA9055_REG_ALARM_MI		0x59
+#define	DA9055_REG_ALARM_H		0x5A
+#define	DA9055_REG_ALARM_D		0x5B
+#define	DA9055_REG_ALARM_MO		0x5C
+#define	DA9055_REG_ALARM_Y		0x5D
+#define	DA9055_REG_SECOND_A		0x5E
+#define	DA9055_REG_SECOND_B		0x5F
+#define	DA9055_REG_SECOND_C		0x60
+#define	DA9055_REG_SECOND_D		0x61
+
+/* Customer Trim and Configuration */
+#define	DA9055_REG_T_OFFSET		0x63
+#define	DA9055_REG_INTERFACE		0x64
+#define	DA9055_REG_CONFIG_A		0x65
+#define	DA9055_REG_CONFIG_B		0x66
+#define	DA9055_REG_CONFIG_C		0x67
+#define	DA9055_REG_CONFIG_D		0x68
+#define	DA9055_REG_CONFIG_E		0x69
+#define	DA9055_REG_TRIM_CLDR		0x6F
+
+/* General Purpose Registers */
+#define	DA9055_REG_GP_ID_0		0x70
+#define	DA9055_REG_GP_ID_1		0x71
+#define	DA9055_REG_GP_ID_2		0x72
+#define	DA9055_REG_GP_ID_3		0x73
+#define	DA9055_REG_GP_ID_4		0x74
+#define	DA9055_REG_GP_ID_5		0x75
+#define	DA9055_REG_GP_ID_6		0x76
+#define	DA9055_REG_GP_ID_7		0x77
+#define	DA9055_REG_GP_ID_8		0x78
+#define	DA9055_REG_GP_ID_9		0x79
+#define	DA9055_REG_GP_ID_10		0x7A
+#define	DA9055_REG_GP_ID_11		0x7B
+#define	DA9055_REG_GP_ID_12		0x7C
+#define	DA9055_REG_GP_ID_13		0x7D
+#define	DA9055_REG_GP_ID_14		0x7E
+#define	DA9055_REG_GP_ID_15		0x7F
+#define	DA9055_REG_GP_ID_16		0x80
+#define	DA9055_REG_GP_ID_17		0x81
+#define	DA9055_REG_GP_ID_18		0x82
+#define	DA9055_REG_GP_ID_19		0x83
+
+#define DA9055_MAX_REGISTER_CNT		DA9055_REG_GP_ID_19
+
+/*
+ * PMIC registers bits
+ */
+
+/* DA9055_REG_PAGE_CON (addr=0x00) */
+#define	DA9055_PAGE_WRITE_MODE		(0<<6)
+#define	DA9055_REPEAT_WRITE_MODE	(1<<6)
+
+/* DA9055_REG_STATUS_A (addr=0x01) */
+#define	DA9055_NOKEY_STS		0x01
+#define	DA9055_WAKE_STS			0x02
+#define	DA9055_DVC_BUSY_STS		0x04
+#define	DA9055_COMP1V2_STS		0x08
+#define	DA9055_NJIG_STS			0x10
+#define	DA9055_LDO5_LIM_STS		0x20
+#define	DA9055_LDO6_LIM_STS		0x40
+
+/* DA9055_REG_STATUS_B (addr=0x02) */
+#define	DA9055_GPI0_STS			0x01
+#define	DA9055_GPI1_STS			0x02
+#define	DA9055_GPI2_STS			0x04
+
+/* DA9055_REG_FAULT_LOG (addr=0x03) */
+#define	DA9055_TWD_ERROR_FLG		0x01
+#define	DA9055_POR_FLG			0x02
+#define	DA9055_VDD_FAULT_FLG		0x04
+#define	DA9055_VDD_START_FLG		0x08
+#define	DA9055_TEMP_CRIT_FLG		0x10
+#define	DA9055_KEY_RESET_FLG		0x20
+#define	DA9055_WAIT_SHUT_FLG		0x80
+
+/* DA9055_REG_EVENT_A (addr=0x04) */
+#define	DA9055_NOKEY_EINT		0x01
+#define	DA9055_ALARM_EINT		0x02
+#define	DA9055_TICK_EINT		0x04
+#define	DA9055_ADC_RDY_EINT		0x08
+#define	DA9055_SEQ_RDY_EINT		0x10
+#define	DA9055_EVENTS_B_EINT		0x20
+#define	DA9055_EVENTS_C_EINT		0x40
+
+/* DA9055_REG_EVENT_B (addr=0x05) */
+#define	DA9055_E_WAKE_EINT		0x01
+#define	DA9055_E_TEMP_EINT		0x02
+#define	DA9055_E_COMP1V2_EINT		0x04
+#define	DA9055_E_LDO_LIM_EINT		0x08
+#define	DA9055_E_NJIG_EINT		0x20
+#define	DA9055_E_VDD_MON_EINT		0x40
+#define	DA9055_E_VDD_WARN_EINT		0x80
+
+/* DA9055_REG_EVENT_C (addr=0x06) */
+#define	DA9055_E_GPI0_EINT		0x01
+#define	DA9055_E_GPI1_EINT		0x02
+#define	DA9055_E_GPI2_EINT		0x04
+
+/* DA9055_REG_IRQ_MASK_A (addr=0x07) */
+#define	DA9055_M_NONKEY_EINT		0x01
+#define	DA9055_M_ALARM_EINT		0x02
+#define	DA9055_M_TICK_EINT		0x04
+#define	DA9055_M_ADC_RDY_EINT		0x08
+#define	DA9055_M_SEQ_RDY_EINT		0x10
+
+/* DA9055_REG_IRQ_MASK_B (addr=0x08) */
+#define	DA9055_M_WAKE_EINT		0x01
+#define	DA9055_M_TEMP_EINT		0x02
+#define	DA9055_M_COMP_1V2_EINT		0x04
+#define	DA9055_M_LDO_LIM_EINT		0x08
+#define	DA9055_M_NJIG_EINT		0x20
+#define	DA9055_M_VDD_MON_EINT		0x40
+#define	DA9055_M_VDD_WARN_EINT		0x80
+
+/* DA9055_REG_IRQ_MASK_C (addr=0x09) */
+#define	DA9055_M_GPI0_EINT		0x01
+#define	DA9055_M_GPI1_EINT		0x02
+#define	DA9055_M_GPI2_EINT		0x04
+
+/* DA9055_REG_CONTROL_A (addr=0xA) */
+#define	DA9055_DEBOUNCING_SHIFT		0x00
+#define	DA9055_DEBOUNCING_MASK		0x07
+#define	DA9055_NRES_MODE_SHIFT		0x03
+#define	DA9055_NRES_MODE_MASK		0x08
+#define	DA9055_SLEW_RATE_SHIFT		0x04
+#define	DA9055_SLEW_RATE_MASK		0x30
+#define	DA9055_NOKEY_LOCK_SHIFT		0x06
+#define	DA9055_NOKEY_LOCK_MASK		0x40
+
+/* DA9055_REG_CONTROL_B (addr=0xB) */
+#define	DA9055_RTC_MODE_PD		0x01
+#define	DA9055_RTC_MODE_SD_SHIFT	0x01
+#define	DA9055_RTC_MODE_SD		0x02
+#define	DA9055_RTC_EN			0x04
+#define	DA9055_ECO_MODE_SHIFT		0x03
+#define	DA9055_ECO_MODE_MASK		0x08
+#define	DA9055_TWDSCALE_SHIFT		4
+#define	DA9055_TWDSCALE_MASK		0x70
+#define	DA9055_V_LOCK_SHIFT		0x07
+#define	DA9055_V_LOCK_MASK		0x80
+
+/* DA9055_REG_CONTROL_C (addr=0xC) */
+#define	DA9055_SYSTEM_EN_SHIFT		0x00
+#define	DA9055_SYSTEM_EN_MASK		0x01
+#define	DA9055_POWERN_EN_SHIFT		0x01
+#define	DA9055_POWERN_EN_MASK		0x02
+#define	DA9055_POWER1_EN_SHIFT		0x02
+#define	DA9055_POWER1_EN_MASK		0x04
+
+/* DA9055_REG_CONTROL_D (addr=0xD) */
+#define	DA9055_STANDBY_SHIFT		0x02
+#define	DA9055_STANDBY_MASK		0x08
+#define	DA9055_AUTO_BOOT_SHIFT		0x03
+#define	DA9055_AUTO_BOOT_MASK		0x04
+
+/* DA9055_REG_CONTROL_E (addr=0xE) */
+#define	DA9055_WATCHDOG_SHIFT		0x00
+#define	DA9055_WATCHDOG_MASK		0x01
+#define	DA9055_SHUTDOWN_SHIFT		0x01
+#define	DA9055_SHUTDOWN_MASK		0x02
+#define	DA9055_WAKE_UP_SHIFT		0x02
+#define	DA9055_WAKE_UP_MASK		0x04
+
+/* DA9055_REG_GPIO (addr=0x10/0x11) */
+#define	DA9055_GPIO0_PIN_SHIFT		0x00
+#define	DA9055_GPIO0_PIN_MASK		0x03
+#define	DA9055_GPIO0_TYPE_SHIFT		0x02
+#define	DA9055_GPIO0_TYPE_MASK		0x04
+#define	DA9055_GPIO0_WEN_SHIFT		0x03
+#define	DA9055_GPIO0_WEN_MASK		0x08
+#define	DA9055_GPIO1_PIN_SHIFT		0x04
+#define	DA9055_GPIO1_PIN_MASK		0x30
+#define	DA9055_GPIO1_TYPE_SHIFT		0x06
+#define	DA9055_GPIO1_TYPE_MASK		0x40
+#define	DA9055_GPIO1_WEN_SHIFT		0x07
+#define	DA9055_GPIO1_WEN_MASK		0x80
+#define	DA9055_GPIO2_PIN_SHIFT		0x00
+#define	DA9055_GPIO2_PIN_MASK		0x30
+#define	DA9055_GPIO2_TYPE_SHIFT		0x02
+#define	DA9055_GPIO2_TYPE_MASK		0x04
+#define	DA9055_GPIO2_WEN_SHIFT		0x03
+#define	DA9055_GPIO2_WEN_MASK		0x08
+
+/* DA9055_REG_GPIO_MODE (addr=0x12) */
+#define	DA9055_GPIO0_MODE_SHIFT		0x00
+#define	DA9055_GPIO0_MODE_MASK		0x01
+#define	DA9055_GPIO1_MODE_SHIFT		0x01
+#define	DA9055_GPIO1_MODE_MASK		0x02
+#define	DA9055_GPIO2_MODE_SHIFT		0x02
+#define	DA9055_GPIO2_MODE_MASK		0x04
+
+/* DA9055_REG_BCORE_CONT (addr=0x13) */
+#define	DA9055_BCORE_EN_SHIFT		0x00
+#define	DA9055_BCORE_EN_MASK		0x01
+#define	DA9055_BCORE_GPI_SHIFT		0x01
+#define	DA9055_BCORE_GPI_MASK		0x02
+#define	DA9055_BCORE_PD_DIS_SHIFT	0x03
+#define	DA9055_BCORE_PD_DIS_MASK	0x04
+#define	DA9055_VBCORE_SEL_SHIFT		0x04
+#define	DA9055_SEL_REG_A		0x0
+#define	DA9055_SEL_REG_B		0x10
+#define	DA9055_VBCORE_SEL_MASK		0x10
+#define DA9055_V_GPI_MASK		0x60
+#define DA9055_V_GPI_SHIFT		0x05
+#define DA9055_E_GPI_MASK		0x06
+#define DA9055_E_GPI_SHIFT		0x01
+#define	DA9055_VBCORE_GPI_SHIFT		0x05
+#define	DA9055_VBCORE_GPI_MASK		0x60
+#define	DA9055_BCORE_CONF_SHIFT		0x07
+#define	DA9055_BCORE_CONF_MASK		0x80
+
+/* DA9055_REG_BMEM_CONT (addr=0x14) */
+#define	DA9055_BMEM_EN_SHIFT		0x00
+#define	DA9055_BMEM_EN_MASK		0x01
+#define	DA9055_BMEM_GPI_SHIFT		0x01
+#define	DA9055_BMEM_GPI_MASK		0x06
+#define	DA9055_BMEM_PD_DIS_SHIFT	0x03
+#define	DA9055_BMEM_PD_DIS_MASK		0x08
+#define	DA9055_VBMEM_SEL_SHIT		0x04
+#define	DA9055_VBMEM_SEL_VBMEM_A	(0<<4)
+#define	DA9055_VBMEM_SEL_VBMEM_B	(1<<4)
+#define	DA9055_VBMEM_SEL_MASK		0x10
+#define	DA9055_VBMEM_GPI_SHIFT		0x05
+#define	DA9055_VBMEM_GPI_MASK		0x60
+#define	DA9055_BMEM_CONF_SHIFT		0x07
+#define	DA9055_BMEM_CONF_MASK		0x80
+
+/* DA9055_REG_LDO_CONT (addr=0x15-0x1A) */
+#define	DA9055_LDO_EN_SHIFT		0x00
+#define	DA9055_LDO_EN_MASK		0x01
+#define	DA9055_LDO_GPI_SHIFT		0x01
+#define	DA9055_LDO_GPI_MASK		0x06
+#define	DA9055_LDO_PD_DIS_SHIFT		0x03
+#define	DA9055_LDO_PD_DIS_MASK		0x08
+#define	DA9055_VLDO_SEL_SHIFT		0x04
+#define	DA9055_VLDO_SEL_MASK		0x10
+#define	DA9055_VLDO_SEL_VLDO_A		0x00
+#define	DA9055_VLDO_SEL_VLDO_B		0x01
+#define	DA9055_VLDO_GPI_SHIFT		0x05
+#define	DA9055_VLDO_GPI_MASK		0x60
+#define	DA9055_LDO_CONF_SHIFT		0x07
+#define	DA9055_LDO_CONF_MASK		0x80
+#define	DA9055_REGUALTOR_SET_A		0x00
+#define	DA9055_REGUALTOR_SET_B		0x10
+
+/* DA9055_REG_ADC_MAN (addr=0x1B) */
+#define	DA9055_ADC_MUX_SHIFT		0
+#define	DA9055_ADC_MUX_MASK		0xF
+#define	DA9055_ADC_MUX_VSYS		0x0
+#define	DA9055_ADC_MUX_ADCIN1		0x01
+#define	DA9055_ADC_MUX_ADCIN2		0x02
+#define	DA9055_ADC_MUX_ADCIN3		0x03
+#define	DA9055_ADC_MUX_T_SENSE		0x04
+#define	DA9055_ADC_MAN_SHIFT		0x04
+#define	DA9055_ADC_MAN_CONV		0x10
+#define DA9055_ADC_LSB_MASK		0X03
+#define DA9055_ADC_MODE_MASK		0x20
+#define	DA9055_ADC_MODE_SHIFT		5
+#define	DA9055_ADC_MODE_1MS		(1<<5)
+#define	DA9055_COMP1V2_EN_SHIFT		7
+
+/* DA9055_REG_ADC_CONT (addr=0x1C) */
+#define	DA9055_ADC_AUTO_VSYS_EN_SHIFT	0
+#define	DA9055_ADC_AUTO_AD1_EN_SHIFT	1
+#define	DA9055_ADC_AUTO_AD2_EN_SHIFT	2
+#define	DA9055_ADC_AUTO_AD3_EN_SHIFT	3
+#define	DA9055_ADC_ISRC_EN_SHIFT	4
+#define	DA9055_ADC_ADCIN1_DEB_SHIFT	5
+#define	DA9055_ADC_ADCIN2_DEB_SHIFT	6
+#define	DA9055_ADC_ADCIN3_DEB_SHIFT	7
+#define DA9055_AD1_ISRC_MASK		0x10
+#define DA9055_AD1_ISRC_SHIFT		4
+
+/* DA9055_REG_VSYS_MON (addr=0x1D) */
+#define	DA9055_VSYS_VAL_SHIFT		0
+#define	DA9055_VSYS_VAL_MASK		0xFF
+#define	DA9055_VSYS_VAL_BASE		0x00
+#define	DA9055_VSYS_VAL_MAX		DA9055_VSYS_VAL_MASK
+#define	DA9055_VSYS_VOLT_BASE		2500
+#define	DA9055_VSYS_VOLT_INC		10
+#define	DA9055_VSYS_STEPS		255
+#define	DA9055_VSYS_VOLT_MIN		2500
+
+/* DA9044_REG_XXX_RES (addr=0x20-0x23) */
+#define	DA9055_ADC_VAL_SHIFT		0
+#define	DA9055_ADC_VAL_MASK		0xFF
+#define	DA9055_ADC_VAL_BASE		0x00
+#define	DA9055_ADC_VAL_MAX		DA9055_ADC_VAL_MASK
+#define	DA9055_ADC_VOLT_BASE		0
+#define	DA9055_ADC_VSYS_VOLT_BASE	2500
+#define	DA9055_ADC_VOLT_INC		10
+#define	DA9055_ADC_VSYS_VOLT_INC	12
+#define	DA9055_ADC_STEPS		255
+
+/* DA9055_REG_EN_32K  (addr=0x35)*/
+#define	DA9055_STARTUP_TIME_MASK	0x07
+#define	DA9055_STARTUP_TIME_0S		0x0
+#define	DA9055_STARTUP_TIME_0_52S	0x1
+#define	DA9055_STARTUP_TIME_1S		0x2
+#define	DA9055_CRYSTAL_EN		0x08
+#define	DA9055_DELAY_MODE_EN		0x10
+#define	DA9055_OUT_CLCK_GATED		0x20
+#define	DA9055_RTC_CLOCK_GATED		0x40
+#define	DA9055_EN_32KOUT_BUF		0x80
+
+/* DA9055_REG_RESET (addr=0x36) */
+/* Timer up to 31.744 ms */
+#define	DA9055_RESET_TIMER_VAL_SHIFT	0
+#define	DA9055_RESET_LOW_VAL_MASK	0x3F
+#define	DA9055_RESET_LOW_VAL_BASE	0
+#define	DA9055_RESET_LOW_VAL_MAX	DA9055_RESET_LOW_VAL_MASK
+#define	DA9055_RESET_US_LOW_BASE	1024 /* min val in units of us */
+#define	DA9055_RESET_US_LOW_INC		1024 /* inc val in units of us */
+#define	DA9055_RESET_US_LOW_STEP	30
+
+/* Timer up to 1048.576ms */
+#define	DA9055_RESET_HIGH_VAL_MASK	0x3F
+#define	DA9055_RESET_HIGH_VAL_BASE	0
+#define	DA9055_RESET_HIGH_VAL_MAX	DA9055_RESET_HIGH_VAL_MASK
+#define	DA9055_RESET_US_HIGH_BASE	32768 /* min val in units of us */
+#define	DA9055_RESET_US_HIGH_INC	32768 /* inv val in units of us */
+#define	DA9055_RESET_US_HIGH_STEP	31
+
+/* DA9055_REG_BUCK_ILIM (addr=0x37)*/
+#define	DA9055_BMEM_ILIM_SHIFT		0
+#define	DA9055_ILIM_MASK		0x3
+#define	DA9055_ILIM_500MA		0x0
+#define	DA9055_ILIM_600MA		0x1
+#define	DA9055_ILIM_700MA		0x2
+#define	DA9055_ILIM_800MA		0x3
+#define	DA9055_BCORE_ILIM_SHIFT		2
+
+/* DA9055_REG_BCORE_MODE (addr=0x38) */
+#define	DA9055_BMEM_MODE_SHIFT		0
+#define	DA9055_MODE_MASK		0x3
+#define	DA9055_MODE_AB			0x0
+#define	DA9055_MODE_SLEEP		0x1
+#define	DA9055_MODE_SYNCHRO		0x2
+#define	DA9055_MODE_AUTO		0x3
+#define	DA9055_BCORE_MODE_SHIFT		2
+
+/* DA9055_REG_VBCORE_A/B (addr=0x39/0x41)*/
+#define	DA9055_VBCORE_VAL_SHIFT		0
+#define	DA9055_VBCORE_VAL_MASK		0x3F
+#define	DA9055_VBCORE_VAL_BASE		0x09
+#define	DA9055_VBCORE_VAL_MAX		DA9055_VBCORE_VAL_MASK
+#define	DA9055_VBCORE_VOLT_BASE		750
+#define	DA9055_VBCORE_VOLT_INC		25
+#define	DA9055_VBCORE_STEPS		53
+#define	DA9055_VBCORE_VOLT_MIN		DA9055_VBCORE_VOLT_BASE
+#define	DA9055_BCORE_SL_SYNCHRO		(0<<7)
+#define	DA9055_BCORE_SL_SLEEP		(1<<7)
+
+/* DA9055_REG_VBMEM_A/B (addr=0x3A/0x42)*/
+#define	DA9055_VBMEM_VAL_SHIFT		0
+#define	DA9055_VBMEM_VAL_MASK		0x3F
+#define	DA9055_VBMEM_VAL_BASE		0x00
+#define	DA9055_VBMEM_VAL_MAX		DA9055_VBMEM_VAL_MASK
+#define	DA9055_VBMEM_VOLT_BASE		925
+#define	DA9055_VBMEM_VOLT_INC		25
+#define	DA9055_VBMEM_STEPS		63
+#define	DA9055_VBMEM_VOLT_MIN		DA9055_VBMEM_VOLT_BASE
+#define	DA9055_BCMEM_SL_SYNCHRO		(0<<7)
+#define	DA9055_BCMEM_SL_SLEEP		(1<<7)
+
+
+/* DA9055_REG_VLDO (addr=0x3B-0x40/0x43-0x48)*/
+#define	DA9055_VLDO_VAL_SHIFT		0
+#define	DA9055_VLDO_VAL_MASK		0x3F
+#define	DA9055_VLDO6_VAL_MASK		0x7F
+#define	DA9055_VLDO_VAL_BASE		0x02
+#define	DA9055_VLDO2_VAL_BASE		0x03
+#define	DA9055_VLDO6_VAL_BASE		0x00
+#define	DA9055_VLDO_VAL_MAX		DA9055_VLDO_VAL_MASK
+#define	DA9055_VLDO6_VAL_MAX		DA9055_VLDO6_VAL_MASK
+#define	DA9055_VLDO_VOLT_BASE		900
+#define	DA9055_VLDO_VOLT_INC		50
+#define	DA9055_VLDO6_VOLT_INC		20
+#define	DA9055_VLDO_STEPS		48
+#define	DA9055_VLDO5_STEPS		37
+#define	DA9055_VLDO6_STEPS		120
+#define	DA9055_VLDO_VOLT_MIN		DA9055_VLDO_VOLT_BASE
+#define	DA9055_LDO_MODE_SHIFT		7
+#define	DA9055_LDO_SL_NORMAL		0
+#define	DA9055_LDO_SL_SLEEP		1
+
+/* DA9055_REG_OTP_CONT (addr=0x50) */
+#define	DA9055_OTP_TIM_NORMAL		(0<<0)
+#define	DA9055_OTP_TIM_MARGINAL		(1<<0)
+#define	DA9055_OTP_GP_RD_SHIFT		1
+#define	DA9055_OTP_APPS_RD_SHIFT	2
+#define	DA9055_PC_DONE_SHIFT		3
+#define	DA9055_OTP_GP_LOCK_SHIFT	4
+#define	DA9055_OTP_APPS_LOCK_SHIFT	5
+#define	DA9055_OTP_CONF_LOCK_SHIFT	6
+#define	DA9055_OTP_WRITE_DIS_SHIFT	7
+
+/* DA9055_REG_COUNT_S (addr=0x53) */
+#define	DA9055_RTC_SEC			0x3F
+#define	DA9055_RTC_MONITOR_EN		0x40
+#define	DA9055_RTC_READ			0x80
+
+/* DA9055_REG_COUNT_MI (addr=0x54) */
+#define	DA9055_RTC_MIN			0x3F
+
+/* DA9055_REG_COUNT_H (addr=0x55) */
+#define	DA9055_RTC_HOUR			0x1F
+
+/* DA9055_REG_COUNT_D (addr=0x56) */
+#define	DA9055_RTC_DAY			0x1F
+
+/* DA9055_REG_COUNT_MO (addr=0x57) */
+#define	DA9055_RTC_MONTH		0x0F
+
+/* DA9055_REG_COUNT_Y (addr=0x58) */
+#define	DA9055_RTC_YEAR			0x3F
+#define	DA9055_RTC_YEAR_BASE		2000
+
+/* DA9055_REG_ALARM_MI (addr=0x59) */
+#define	DA9055_RTC_ALM_MIN		0x3F
+#define	DA9055_ALARM_STATUS_SHIFT	6
+#define	DA9055_ALARM_STATUS_MASK	0x3
+#define	DA9055_ALARM_STATUS_NO_ALARM	0x0
+#define	DA9055_ALARM_STATUS_TICK	0x1
+#define	DA9055_ALARM_STATUS_TIMER_ALARM	0x2
+#define	DA9055_ALARM_STATUS_BOTH	0x3
+
+/* DA9055_REG_ALARM_H (addr=0x5A) */
+#define	DA9055_RTC_ALM_HOUR		0x1F
+
+/* DA9055_REG_ALARM_D (addr=0x5B) */
+#define	DA9055_RTC_ALM_DAY		0x1F
+
+/* DA9055_REG_ALARM_MO (addr=0x5C) */
+#define	DA9055_RTC_ALM_MONTH		0x0F
+#define	DA9055_RTC_TICK_WAKE_MASK	0x20
+#define	DA9055_RTC_TICK_WAKE_SHIFT	5
+#define	DA9055_RTC_TICK_TYPE		0x10
+#define	DA9055_RTC_TICK_TYPE_SHIFT	0x4
+#define	DA9055_RTC_TICK_SEC		0x0
+#define	DA9055_RTC_TICK_MIN		0x1
+#define	DA9055_ALARAM_TICK_WAKE		0x20
+
+/* DA9055_REG_ALARM_Y (addr=0x5D) */
+#define	DA9055_RTC_TICK_EN		0x80
+#define	DA9055_RTC_ALM_EN		0x40
+#define	DA9055_RTC_TICK_ALM_MASK	0xC0
+#define	DA9055_RTC_ALM_YEAR		0x3F
+
+/* DA9055_REG_TRIM_CLDR (addr=0x62) */
+#define	DA9055_TRIM_32K_SHIFT		0
+#define	DA9055_TRIM_32K_MASK		0x7F
+#define	DA9055_TRIM_DECREMENT		(1<<7)
+#define	DA9055_TRIM_INCREMENT		(0<<7)
+#define	DA9055_TRIM_VAL_BASE		0x0
+#define	DA9055_TRIM_PPM_BASE		0x0 /* min val in units of 0.1PPM */
+#define	DA9055_TRIM_PPM_INC		19 /* min inc in units of 0.1PPM */
+#define	DA9055_TRIM_STEPS		127
+
+/* DA9055_REG_CONFIG_A (addr=0x65) */
+#define	DA9055_PM_I_V_VDDCORE		(0<<0)
+#define	DA9055_PM_I_V_VDD_IO		(1<<0)
+#define	DA9055_VDD_FAULT_TYPE_ACT_LOW	(0<<1)
+#define	DA9055_VDD_FAULT_TYPE_ACT_HIGH	(1<<1)
+#define	DA9055_PM_O_TYPE_PUSH_PULL	(0<<2)
+#define	DA9055_PM_O_TYPE_OPEN_DRAIN	(1<<2)
+#define	DA9055_IRQ_TYPE_ACT_LOW		(0<<3)
+#define	DA9055_IRQ_TYPE_ACT_HIGH	(1<<3)
+#define	DA9055_NIRQ_MODE_IMM		(0<<4)
+#define	DA9055_NIRQ_MODE_ACTIVE		(1<<4)
+#define	DA9055_GPI_V_VDDCORE		(0<<5)
+#define	DA9055_GPI_V_VDD_IO		(1<<5)
+#define	DA9055_PM_IF_V_VDDCORE		(0<<6)
+#define	DA9055_PM_IF_V_VDD_IO		(1<<6)
+
+/* DA9055_REG_CONFIG_B (addr=0x66) */
+#define	DA9055_VDD_FAULT_VAL_SHIFT	0
+#define	DA9055_VDD_FAULT_VAL_MASK	0xF
+#define	DA9055_VDD_FAULT_VAL_BASE	0x0
+#define	DA9055_VDD_FAULT_VAL_MAX	DA9055_VDD_FAULT_VAL_MASK
+#define	DA9055_VDD_FAULT_VOLT_BASE	2500
+#define	DA9055_VDD_FAULT_VOLT_INC	50
+#define	DA9055_VDD_FAULT_STEPS		15
+
+#define	DA9055_VDD_HYST_VAL_SHIFT	4
+#define	DA9055_VDD_HYST_VAL_MASK	0x7
+#define	DA9055_VDD_HYST_VAL_BASE	0x0
+#define	DA9055_VDD_HYST_VAL_MAX		DA9055_VDD_HYST_VAL_MASK
+#define	DA9055_VDD_HYST_VOLT_BASE	100
+#define	DA9055_VDD_HYST_VOLT_INC	50
+#define	DA9055_VDD_HYST_STEPS		7
+#define	DA9055_VDD_HYST_VOLT_MIN	DA9055_VDD_HYST_VOLT_BASE
+
+#define	DA9055_VDD_FAULT_EN_SHIFT	7
+
+/* DA9055_REG_CONFIG_C (addr=0x67) */
+#define	DA9055_BCORE_CLK_INV_SHIFT	0
+#define	DA9055_BMEM_CLK_INV_SHIFT	1
+#define	DA9055_NFAULT_CONF_SHIFT	2
+#define	DA9055_LDO_SD_SHIFT		4
+#define	DA9055_LDO5_BYP_SHIFT		6
+#define	DA9055_LDO6_BYP_SHIFT		7
+
+/* DA9055_REG_CONFIG_D (addr=0x68) */
+#define	DA9055_NONKEY_PIN_SHIFT		0
+#define	DA9055_NONKEY_PIN_MASK		0x3
+#define	DA9055_NONKEY_PIN_PORT_MODE	0x0
+#define	DA9055_NONKEY_PIN_KEY_MODE	0x1
+#define	DA9055_NONKEY_PIN_MULTI_FUNC	0x2
+#define	DA9055_NONKEY_PIN_DEDICT	0x3
+#define	DA9055_NONKEY_SD_SHIFT		2
+#define	DA9055_KEY_DELAY_SHIFT		3
+#define	DA9055_KEY_DELAY_MASK		0x3
+#define	DA9055_KEY_DELAY_4S		0x0
+#define	DA9055_KEY_DELAY_6S		0x1
+#define	DA9055_KEY_DELAY_8S		0x2
+#define	DA9055_KEY_DELAY_10S		0x3
+
+/* DA9055_REG_CONFIG_E (addr=0x69) */
+#define	DA9055_GPIO_PUPD_PULL_UP	0x0
+#define	DA9055_GPIO_PUPD_OPEN_DRAIN	0x1
+#define	DA9055_GPIO0_PUPD_SHIFT		0
+#define	DA9055_GPIO1_PUPD_SHIFT		1
+#define	DA9055_GPIO2_PUPD_SHIFT		2
+#define	DA9055_UVOV_DELAY_SHIFT		4
+#define	DA9055_UVOV_DELAY_MASK		0x3
+#define	DA9055_RESET_DURATION_SHIFT	6
+#define	DA9055_RESET_DURATION_MASK	0x3
+#define	DA9055_RESET_DURATION_0MS	0x0
+#define	DA9055_RESET_DURATION_100MS	0x1
+#define	DA9055_RESET_DURATION_500MS	0x2
+#define	DA9055_RESET_DURATION_1000MS	0x3
+
+/* DA9055_REG_MON_REG_1 (addr=0x6A) */
+#define	DA9055_MON_THRES_SHIFT		0
+#define	DA9055_MON_THRES_MASK		0x3
+#define	DA9055_MON_RES_SHIFT		2
+#define	DA9055_MON_DEB_SHIFT		3
+#define	DA9055_MON_MODE_SHIFT		4
+#define	DA9055_MON_MODE_MASK		0x3
+#define	DA9055_START_MAX_SHIFT		6
+#define	DA9055_START_MAX_MASK		0x3
+
+/* DA9055_REG_MON_REG_2 (addr=0x6B) */
+#define	DA9055_LDO1_MON_EN_SHIFT	0
+#define	DA9055_LDO2_MON_EN_SHIFT	1
+#define	DA9055_LDO3_MON_EN_SHIFT	2
+#define	DA9055_LDO4_MON_EN_SHIFT	3
+#define	DA9055_LDO5_MON_EN_SHIFT	4
+#define	DA9055_LDO6_MON_EN_SHIFT	5
+#define	DA9055_BCORE_MON_EN_SHIFT	6
+#define	DA9055_BMEM_MON_EN_SHIFT	7
+
+/* DA9055_REG_CONFIG_F (addr=0x6C) */
+#define	DA9055_LDO1_DEF_SHIFT		0
+#define	DA9055_LDO2_DEF_SHIFT		1
+#define	DA9055_LDO3_DEF_SHIFT		2
+#define	DA9055_LDO4_DEF_SHIFT		3
+#define	DA9055_LDO5_DEF_SHIFT		4
+#define	DA9055_LDO6_DEF_SHIFT		5
+#define	DA9055_BCORE_DEF_SHIFT		6
+#define	DA9055_BMEM_DEF_SHIFT		7
+
+/* DA9055_REG_MON_REG_4 (addr=0x6D) */
+#define	DA9055_MON_A8_IDX_SHIFT		0
+#define	DA9055_MON_A89_IDX_MASK		0x3
+#define	DA9055_MON_A89_IDX_NONE		0x0
+#define	DA9055_MON_A89_IDX_BUCKCORE	0x1
+#define	DA9055_MON_A89_IDX_LDO3		0x2
+#define	DA9055_MON_A9_IDX_SHIFT		5
+
+/* DA9055_REG_MON_REG_5 (addr=0x6E) */
+#define	DA9055_MON_A10_IDX_SHIFT	0
+#define	DA9055_MON_A10_IDX_MASK		0x3
+#define	DA9055_MON_A10_IDX_NONE		0x0
+#define	DA9055_MON_A10_IDX_LDO1		0x1
+#define	DA9055_MON_A10_IDX_LDO2		0x2
+#define	DA9055_MON_A10_IDX_LDO5		0x3
+#define	DA9055_MON_A10_IDX_LDO6		0x4
+
+#endif /* __DA9055_REG_H */

+ 52 - 0
include/linux/mfd/lp8788-isink.h

@@ -0,0 +1,52 @@
+/*
+ * TI LP8788 MFD - common definitions for current sinks
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ISINK_LP8788_H__
+#define __ISINK_LP8788_H__
+
+/* register address */
+#define LP8788_ISINK_CTRL		0x99
+#define LP8788_ISINK12_IOUT		0x9A
+#define LP8788_ISINK3_IOUT		0x9B
+#define LP8788_ISINK1_PWM		0x9C
+#define LP8788_ISINK2_PWM		0x9D
+#define LP8788_ISINK3_PWM		0x9E
+
+/* mask bits */
+#define LP8788_ISINK1_IOUT_M		0x0F	/* Addr 9Ah */
+#define LP8788_ISINK2_IOUT_M		0xF0
+#define LP8788_ISINK3_IOUT_M		0x0F	/* Addr 9Bh */
+
+/* 6 bits used for PWM code : Addr 9C ~ 9Eh */
+#define LP8788_ISINK_MAX_PWM		63
+#define LP8788_ISINK_SCALE_OFFSET	3
+
+static const u8 lp8788_iout_addr[] = {
+	LP8788_ISINK12_IOUT,
+	LP8788_ISINK12_IOUT,
+	LP8788_ISINK3_IOUT,
+};
+
+static const u8 lp8788_iout_mask[] = {
+	LP8788_ISINK1_IOUT_M,
+	LP8788_ISINK2_IOUT_M,
+	LP8788_ISINK3_IOUT_M,
+};
+
+static const u8 lp8788_pwm_addr[] = {
+	LP8788_ISINK1_PWM,
+	LP8788_ISINK2_PWM,
+	LP8788_ISINK3_PWM,
+};
+
+#endif

+ 364 - 0
include/linux/mfd/lp8788.h

@@ -0,0 +1,364 @@
+/*
+ * TI LP8788 MFD Device
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __MFD_LP8788_H__
+#define __MFD_LP8788_H__
+
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+#define LP8788_DEV_BUCK		"lp8788-buck"
+#define LP8788_DEV_DLDO		"lp8788-dldo"
+#define LP8788_DEV_ALDO		"lp8788-aldo"
+#define LP8788_DEV_CHARGER	"lp8788-charger"
+#define LP8788_DEV_RTC		"lp8788-rtc"
+#define LP8788_DEV_BACKLIGHT	"lp8788-backlight"
+#define LP8788_DEV_VIBRATOR	"lp8788-vibrator"
+#define LP8788_DEV_KEYLED	"lp8788-keyled"
+#define LP8788_DEV_ADC		"lp8788-adc"
+
+#define LP8788_NUM_BUCKS	4
+#define LP8788_NUM_DLDOS	12
+#define LP8788_NUM_ALDOS	10
+#define LP8788_NUM_BUCK2_DVS	2
+
+#define LP8788_CHG_IRQ		"CHG_IRQ"
+#define LP8788_PRSW_IRQ		"PRSW_IRQ"
+#define LP8788_BATT_IRQ		"BATT_IRQ"
+#define LP8788_ALM_IRQ		"ALARM_IRQ"
+
+enum lp8788_int_id {
+	/* interrup register 1 : Addr 00h */
+	LP8788_INT_TSDL,
+	LP8788_INT_TSDH,
+	LP8788_INT_UVLO,
+	LP8788_INT_FLAGMON,
+	LP8788_INT_PWRON_TIME,
+	LP8788_INT_PWRON,
+	LP8788_INT_COMP1,
+	LP8788_INT_COMP2,
+
+	/* interrupt register 2 : Addr 01h */
+	LP8788_INT_CHG_INPUT_STATE,
+	LP8788_INT_CHG_STATE,
+	LP8788_INT_EOC,
+	LP8788_INT_CHG_RESTART,
+	LP8788_INT_RESTART_TIMEOUT,
+	LP8788_INT_FULLCHG_TIMEOUT,
+	LP8788_INT_PRECHG_TIMEOUT,
+
+	/* interrupt register 3 : Addr 02h */
+	LP8788_INT_RTC_ALARM1 = 17,
+	LP8788_INT_RTC_ALARM2,
+	LP8788_INT_ENTER_SYS_SUPPORT,
+	LP8788_INT_EXIT_SYS_SUPPORT,
+	LP8788_INT_BATT_LOW,
+	LP8788_INT_NO_BATT,
+
+	LP8788_INT_MAX = 24,
+};
+
+enum lp8788_dvs_sel {
+	DVS_SEL_V0,
+	DVS_SEL_V1,
+	DVS_SEL_V2,
+	DVS_SEL_V3,
+};
+
+enum lp8788_ext_ldo_en_id {
+	EN_ALDO1,
+	EN_ALDO234,
+	EN_ALDO5,
+	EN_ALDO7,
+	EN_DLDO7,
+	EN_DLDO911,
+	EN_LDOS_MAX,
+};
+
+enum lp8788_charger_event {
+	NO_CHARGER,
+	CHARGER_DETECTED,
+};
+
+enum lp8788_bl_ctrl_mode {
+	LP8788_BL_REGISTER_ONLY,
+	LP8788_BL_COMB_PWM_BASED,	/* PWM + I2C, changed by PWM input */
+	LP8788_BL_COMB_REGISTER_BASED,	/* PWM + I2C, changed by I2C */
+};
+
+enum lp8788_bl_dim_mode {
+	LP8788_DIM_EXPONENTIAL,
+	LP8788_DIM_LINEAR,
+};
+
+enum lp8788_bl_full_scale_current {
+	LP8788_FULLSCALE_5000uA,
+	LP8788_FULLSCALE_8500uA,
+	LP8788_FULLSCALE_1200uA,
+	LP8788_FULLSCALE_1550uA,
+	LP8788_FULLSCALE_1900uA,
+	LP8788_FULLSCALE_2250uA,
+	LP8788_FULLSCALE_2600uA,
+	LP8788_FULLSCALE_2950uA,
+};
+
+enum lp8788_bl_ramp_step {
+	LP8788_RAMP_8us,
+	LP8788_RAMP_1024us,
+	LP8788_RAMP_2048us,
+	LP8788_RAMP_4096us,
+	LP8788_RAMP_8192us,
+	LP8788_RAMP_16384us,
+	LP8788_RAMP_32768us,
+	LP8788_RAMP_65538us,
+};
+
+enum lp8788_bl_pwm_polarity {
+	LP8788_PWM_ACTIVE_HIGH,
+	LP8788_PWM_ACTIVE_LOW,
+};
+
+enum lp8788_isink_scale {
+	LP8788_ISINK_SCALE_100mA,
+	LP8788_ISINK_SCALE_120mA,
+};
+
+enum lp8788_isink_number {
+	LP8788_ISINK_1,
+	LP8788_ISINK_2,
+	LP8788_ISINK_3,
+};
+
+enum lp8788_alarm_sel {
+	LP8788_ALARM_1,
+	LP8788_ALARM_2,
+	LP8788_ALARM_MAX,
+};
+
+enum lp8788_adc_id {
+	LPADC_VBATT_5P5,
+	LPADC_VIN_CHG,
+	LPADC_IBATT,
+	LPADC_IC_TEMP,
+	LPADC_VBATT_6P0,
+	LPADC_VBATT_5P0,
+	LPADC_ADC1,
+	LPADC_ADC2,
+	LPADC_VDD,
+	LPADC_VCOIN,
+	LPADC_VDD_LDO,
+	LPADC_ADC3,
+	LPADC_ADC4,
+	LPADC_MAX,
+};
+
+struct lp8788;
+
+/*
+ * lp8788_buck1_dvs
+ * @gpio         : gpio pin number for dvs control
+ * @vsel         : dvs selector for buck v1 register
+ */
+struct lp8788_buck1_dvs {
+	int gpio;
+	enum lp8788_dvs_sel vsel;
+};
+
+/*
+ * lp8788_buck2_dvs
+ * @gpio         : two gpio pin numbers are used for dvs
+ * @vsel         : dvs selector for buck v2 register
+ */
+struct lp8788_buck2_dvs {
+	int gpio[LP8788_NUM_BUCK2_DVS];
+	enum lp8788_dvs_sel vsel;
+};
+
+/*
+ * struct lp8788_ldo_enable_pin
+ *
+ *   Basically, all LDOs are enabled through the I2C commands.
+ *   But ALDO 1 ~ 5, 7, DLDO 7, 9, 11 can be enabled by external gpio pins.
+ *
+ * @gpio         : gpio number which is used for enabling ldos
+ * @init_state   : initial gpio state (ex. GPIOF_OUT_INIT_LOW)
+ */
+struct lp8788_ldo_enable_pin {
+	int gpio;
+	int init_state;
+};
+
+/*
+ * struct lp8788_chg_param
+ * @addr         : charging control register address (range : 0x11 ~ 0x1C)
+ * @val          : charging parameter value
+ */
+struct lp8788_chg_param {
+	u8 addr;
+	u8 val;
+};
+
+/*
+ * struct lp8788_charger_platform_data
+ * @vbatt_adc         : adc selection id for battery voltage
+ * @batt_temp_adc     : adc selection id for battery temperature
+ * @max_vbatt_mv      : used for calculating battery capacity
+ * @chg_params        : initial charging parameters
+ * @num_chg_params    : numbers of charging parameters
+ * @charger_event     : the charger event can be reported to the platform side
+ */
+struct lp8788_charger_platform_data {
+	enum lp8788_adc_id vbatt_adc;
+	enum lp8788_adc_id batt_temp_adc;
+	unsigned int max_vbatt_mv;
+	struct lp8788_chg_param *chg_params;
+	int num_chg_params;
+	void (*charger_event) (struct lp8788 *lp,
+				enum lp8788_charger_event event);
+};
+
+/*
+ * struct lp8788_bl_pwm_data
+ * @pwm_set_intensity     : set duty of pwm
+ * @pwm_get_intensity     : get current duty of pwm
+ */
+struct lp8788_bl_pwm_data {
+	void (*pwm_set_intensity) (int brightness, int max_brightness);
+	int (*pwm_get_intensity) (int max_brightness);
+};
+
+/*
+ * struct lp8788_backlight_platform_data
+ * @name                  : backlight driver name. (default: "lcd-backlight")
+ * @initial_brightness    : initial value of backlight brightness
+ * @bl_mode               : brightness control by pwm or lp8788 register
+ * @dim_mode              : dimming mode selection
+ * @full_scale            : full scale current setting
+ * @rise_time             : brightness ramp up step time
+ * @fall_time             : brightness ramp down step time
+ * @pwm_pol               : pwm polarity setting when bl_mode is pwm based
+ * @pwm_data              : platform specific pwm generation functions
+ *                          only valid when bl_mode is pwm based
+ */
+struct lp8788_backlight_platform_data {
+	char *name;
+	int initial_brightness;
+	enum lp8788_bl_ctrl_mode bl_mode;
+	enum lp8788_bl_dim_mode dim_mode;
+	enum lp8788_bl_full_scale_current full_scale;
+	enum lp8788_bl_ramp_step rise_time;
+	enum lp8788_bl_ramp_step fall_time;
+	enum lp8788_bl_pwm_polarity pwm_pol;
+	struct lp8788_bl_pwm_data pwm_data;
+};
+
+/*
+ * struct lp8788_led_platform_data
+ * @name         : led driver name. (default: "keyboard-backlight")
+ * @scale        : current scale
+ * @num          : current sink number
+ * @iout_code    : current output value (Addr 9Ah ~ 9Bh)
+ */
+struct lp8788_led_platform_data {
+	char *name;
+	enum lp8788_isink_scale scale;
+	enum lp8788_isink_number num;
+	int iout_code;
+};
+
+/*
+ * struct lp8788_vib_platform_data
+ * @name         : vibrator driver name
+ * @scale        : current scale
+ * @num          : current sink number
+ * @iout_code    : current output value (Addr 9Ah ~ 9Bh)
+ * @pwm_code     : PWM code value (Addr 9Ch ~ 9Eh)
+ */
+struct lp8788_vib_platform_data {
+	char *name;
+	enum lp8788_isink_scale scale;
+	enum lp8788_isink_number num;
+	int iout_code;
+	int pwm_code;
+};
+
+/*
+ * struct lp8788_platform_data
+ * @init_func    : used for initializing registers
+ *                 before mfd driver is registered
+ * @buck_data    : regulator initial data for buck
+ * @dldo_data    : regulator initial data for digital ldo
+ * @aldo_data    : regulator initial data for analog ldo
+ * @buck1_dvs    : gpio configurations for buck1 dvs
+ * @buck2_dvs    : gpio configurations for buck2 dvs
+ * @ldo_pin      : gpio configurations for enabling LDOs
+ * @chg_pdata    : platform data for charger driver
+ * @alarm_sel    : rtc alarm selection (1 or 2)
+ * @bl_pdata     : configurable data for backlight driver
+ * @led_pdata    : configurable data for led driver
+ * @vib_pdata    : configurable data for vibrator driver
+ * @adc_pdata    : iio map data for adc driver
+ */
+struct lp8788_platform_data {
+	/* general system information */
+	int (*init_func) (struct lp8788 *lp);
+
+	/* regulators */
+	struct regulator_init_data *buck_data[LP8788_NUM_BUCKS];
+	struct regulator_init_data *dldo_data[LP8788_NUM_DLDOS];
+	struct regulator_init_data *aldo_data[LP8788_NUM_ALDOS];
+	struct lp8788_buck1_dvs *buck1_dvs;
+	struct lp8788_buck2_dvs *buck2_dvs;
+	struct lp8788_ldo_enable_pin *ldo_pin[EN_LDOS_MAX];
+
+	/* charger */
+	struct lp8788_charger_platform_data *chg_pdata;
+
+	/* rtc alarm */
+	enum lp8788_alarm_sel alarm_sel;
+
+	/* backlight */
+	struct lp8788_backlight_platform_data *bl_pdata;
+
+	/* current sinks */
+	struct lp8788_led_platform_data *led_pdata;
+	struct lp8788_vib_platform_data *vib_pdata;
+
+	/* adc iio map data */
+	struct iio_map *adc_pdata;
+};
+
+/*
+ * struct lp8788
+ * @dev          : parent device pointer
+ * @regmap       : used for i2c communcation on accessing registers
+ * @irqdm        : interrupt domain for handling nested interrupt
+ * @irq          : pin number of IRQ_N
+ * @pdata        : lp8788 platform specific data
+ */
+struct lp8788 {
+	struct device *dev;
+	struct regmap *regmap;
+	struct irq_domain *irqdm;
+	int irq;
+	struct lp8788_platform_data *pdata;
+};
+
+int lp8788_irq_init(struct lp8788 *lp, int chip_irq);
+void lp8788_irq_exit(struct lp8788 *lp);
+int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data);
+int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count);
+int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data);
+int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data);
+#endif

+ 1 - 0
include/linux/mfd/lpc_ich.h

@@ -43,6 +43,7 @@ struct lpc_ich_info {
 	char name[32];
 	char name[32];
 	unsigned int iTCO_version;
 	unsigned int iTCO_version;
 	unsigned int gpio_version;
 	unsigned int gpio_version;
+	u8 use_gpio;
 };
 };
 
 
 #endif
 #endif

+ 252 - 0
include/linux/mfd/max8907.h

@@ -0,0 +1,252 @@
+/*
+ * Functions to access MAX8907 power management chip.
+ *
+ * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
+ * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MFD_MAX8907_H
+#define __LINUX_MFD_MAX8907_H
+
+#include <linux/mutex.h>
+#include <linux/pm.h>
+
+#define MAX8907_GEN_I2C_ADDR		(0x78 >> 1)
+#define MAX8907_ADC_I2C_ADDR		(0x8e >> 1)
+#define MAX8907_RTC_I2C_ADDR		(0xd0 >> 1)
+
+/* MAX8907 register map */
+#define MAX8907_REG_SYSENSEL		0x00
+#define MAX8907_REG_ON_OFF_IRQ1		0x01
+#define MAX8907_REG_ON_OFF_IRQ1_MASK	0x02
+#define MAX8907_REG_ON_OFF_STAT		0x03
+#define MAX8907_REG_SDCTL1		0x04
+#define MAX8907_REG_SDSEQCNT1		0x05
+#define MAX8907_REG_SDV1		0x06
+#define MAX8907_REG_SDCTL2		0x07
+#define MAX8907_REG_SDSEQCNT2		0x08
+#define MAX8907_REG_SDV2		0x09
+#define MAX8907_REG_SDCTL3		0x0A
+#define MAX8907_REG_SDSEQCNT3		0x0B
+#define MAX8907_REG_SDV3		0x0C
+#define MAX8907_REG_ON_OFF_IRQ2		0x0D
+#define MAX8907_REG_ON_OFF_IRQ2_MASK	0x0E
+#define MAX8907_REG_RESET_CNFG		0x0F
+#define MAX8907_REG_LDOCTL16		0x10
+#define MAX8907_REG_LDOSEQCNT16		0x11
+#define MAX8907_REG_LDO16VOUT		0x12
+#define MAX8907_REG_SDBYSEQCNT		0x13
+#define MAX8907_REG_LDOCTL17		0x14
+#define MAX8907_REG_LDOSEQCNT17		0x15
+#define MAX8907_REG_LDO17VOUT		0x16
+#define MAX8907_REG_LDOCTL1		0x18
+#define MAX8907_REG_LDOSEQCNT1		0x19
+#define MAX8907_REG_LDO1VOUT		0x1A
+#define MAX8907_REG_LDOCTL2		0x1C
+#define MAX8907_REG_LDOSEQCNT2		0x1D
+#define MAX8907_REG_LDO2VOUT		0x1E
+#define MAX8907_REG_LDOCTL3		0x20
+#define MAX8907_REG_LDOSEQCNT3		0x21
+#define MAX8907_REG_LDO3VOUT		0x22
+#define MAX8907_REG_LDOCTL4		0x24
+#define MAX8907_REG_LDOSEQCNT4		0x25
+#define MAX8907_REG_LDO4VOUT		0x26
+#define MAX8907_REG_LDOCTL5		0x28
+#define MAX8907_REG_LDOSEQCNT5		0x29
+#define MAX8907_REG_LDO5VOUT		0x2A
+#define MAX8907_REG_LDOCTL6		0x2C
+#define MAX8907_REG_LDOSEQCNT6		0x2D
+#define MAX8907_REG_LDO6VOUT		0x2E
+#define MAX8907_REG_LDOCTL7		0x30
+#define MAX8907_REG_LDOSEQCNT7		0x31
+#define MAX8907_REG_LDO7VOUT		0x32
+#define MAX8907_REG_LDOCTL8		0x34
+#define MAX8907_REG_LDOSEQCNT8		0x35
+#define MAX8907_REG_LDO8VOUT		0x36
+#define MAX8907_REG_LDOCTL9		0x38
+#define MAX8907_REG_LDOSEQCNT9		0x39
+#define MAX8907_REG_LDO9VOUT		0x3A
+#define MAX8907_REG_LDOCTL10		0x3C
+#define MAX8907_REG_LDOSEQCNT10		0x3D
+#define MAX8907_REG_LDO10VOUT		0x3E
+#define MAX8907_REG_LDOCTL11		0x40
+#define MAX8907_REG_LDOSEQCNT11		0x41
+#define MAX8907_REG_LDO11VOUT		0x42
+#define MAX8907_REG_LDOCTL12		0x44
+#define MAX8907_REG_LDOSEQCNT12		0x45
+#define MAX8907_REG_LDO12VOUT		0x46
+#define MAX8907_REG_LDOCTL13		0x48
+#define MAX8907_REG_LDOSEQCNT13		0x49
+#define MAX8907_REG_LDO13VOUT		0x4A
+#define MAX8907_REG_LDOCTL14		0x4C
+#define MAX8907_REG_LDOSEQCNT14		0x4D
+#define MAX8907_REG_LDO14VOUT		0x4E
+#define MAX8907_REG_LDOCTL15		0x50
+#define MAX8907_REG_LDOSEQCNT15		0x51
+#define MAX8907_REG_LDO15VOUT		0x52
+#define MAX8907_REG_OUT5VEN		0x54
+#define MAX8907_REG_OUT5VSEQ		0x55
+#define MAX8907_REG_OUT33VEN		0x58
+#define MAX8907_REG_OUT33VSEQ		0x59
+#define MAX8907_REG_LDOCTL19		0x5C
+#define MAX8907_REG_LDOSEQCNT19		0x5D
+#define MAX8907_REG_LDO19VOUT		0x5E
+#define MAX8907_REG_LBCNFG		0x60
+#define MAX8907_REG_SEQ1CNFG		0x64
+#define MAX8907_REG_SEQ2CNFG		0x65
+#define MAX8907_REG_SEQ3CNFG		0x66
+#define MAX8907_REG_SEQ4CNFG		0x67
+#define MAX8907_REG_SEQ5CNFG		0x68
+#define MAX8907_REG_SEQ6CNFG		0x69
+#define MAX8907_REG_SEQ7CNFG		0x6A
+#define MAX8907_REG_LDOCTL18		0x72
+#define MAX8907_REG_LDOSEQCNT18		0x73
+#define MAX8907_REG_LDO18VOUT		0x74
+#define MAX8907_REG_BBAT_CNFG		0x78
+#define MAX8907_REG_CHG_CNTL1		0x7C
+#define MAX8907_REG_CHG_CNTL2		0x7D
+#define MAX8907_REG_CHG_IRQ1		0x7E
+#define MAX8907_REG_CHG_IRQ2		0x7F
+#define MAX8907_REG_CHG_IRQ1_MASK	0x80
+#define MAX8907_REG_CHG_IRQ2_MASK	0x81
+#define MAX8907_REG_CHG_STAT		0x82
+#define MAX8907_REG_WLED_MODE_CNTL	0x84
+#define MAX8907_REG_ILED_CNTL		0x84
+#define MAX8907_REG_II1RR		0x8E
+#define MAX8907_REG_II2RR		0x8F
+#define MAX8907_REG_LDOCTL20		0x9C
+#define MAX8907_REG_LDOSEQCNT20		0x9D
+#define MAX8907_REG_LDO20VOUT		0x9E
+
+/* RTC register map */
+#define MAX8907_REG_RTC_SEC		0x00
+#define MAX8907_REG_RTC_MIN		0x01
+#define MAX8907_REG_RTC_HOURS		0x02
+#define MAX8907_REG_RTC_WEEKDAY		0x03
+#define MAX8907_REG_RTC_DATE		0x04
+#define MAX8907_REG_RTC_MONTH		0x05
+#define MAX8907_REG_RTC_YEAR1		0x06
+#define MAX8907_REG_RTC_YEAR2		0x07
+#define MAX8907_REG_ALARM0_SEC		0x08
+#define MAX8907_REG_ALARM0_MIN		0x09
+#define MAX8907_REG_ALARM0_HOURS	0x0A
+#define MAX8907_REG_ALARM0_WEEKDAY	0x0B
+#define MAX8907_REG_ALARM0_DATE		0x0C
+#define MAX8907_REG_ALARM0_MONTH	0x0D
+#define MAX8907_REG_ALARM0_YEAR1	0x0E
+#define MAX8907_REG_ALARM0_YEAR2	0x0F
+#define MAX8907_REG_ALARM1_SEC		0x10
+#define MAX8907_REG_ALARM1_MIN		0x11
+#define MAX8907_REG_ALARM1_HOURS	0x12
+#define MAX8907_REG_ALARM1_WEEKDAY	0x13
+#define MAX8907_REG_ALARM1_DATE		0x14
+#define MAX8907_REG_ALARM1_MONTH	0x15
+#define MAX8907_REG_ALARM1_YEAR1	0x16
+#define MAX8907_REG_ALARM1_YEAR2	0x17
+#define MAX8907_REG_ALARM0_CNTL		0x18
+#define MAX8907_REG_ALARM1_CNTL		0x19
+#define MAX8907_REG_RTC_STATUS		0x1A
+#define MAX8907_REG_RTC_CNTL		0x1B
+#define MAX8907_REG_RTC_IRQ		0x1C
+#define MAX8907_REG_RTC_IRQ_MASK	0x1D
+#define MAX8907_REG_MPL_CNTL		0x1E
+
+/* ADC and Touch Screen Controller register map */
+#define MAX8907_CTL			0
+#define MAX8907_SEQCNT			1
+#define MAX8907_VOUT			2
+
+/* mask bit fields */
+#define MAX8907_MASK_LDO_SEQ		0x1C
+#define MAX8907_MASK_LDO_EN		0x01
+#define MAX8907_MASK_VBBATTCV		0x03
+#define MAX8907_MASK_OUT5V_VINEN	0x10
+#define MAX8907_MASK_OUT5V_ENSRC	0x0E
+#define MAX8907_MASK_OUT5V_EN		0x01
+#define MAX8907_MASK_POWER_OFF		0x40
+
+/* Regulator IDs */
+#define MAX8907_MBATT	0
+#define MAX8907_SD1	1
+#define MAX8907_SD2	2
+#define MAX8907_SD3	3
+#define MAX8907_LDO1	4
+#define MAX8907_LDO2	5
+#define MAX8907_LDO3	6
+#define MAX8907_LDO4	7
+#define MAX8907_LDO5	8
+#define MAX8907_LDO6	9
+#define MAX8907_LDO7	10
+#define MAX8907_LDO8	11
+#define MAX8907_LDO9	12
+#define MAX8907_LDO10	13
+#define MAX8907_LDO11	14
+#define MAX8907_LDO12	15
+#define MAX8907_LDO13	16
+#define MAX8907_LDO14	17
+#define MAX8907_LDO15	18
+#define MAX8907_LDO16	19
+#define MAX8907_LDO17	20
+#define MAX8907_LDO18	21
+#define MAX8907_LDO19	22
+#define MAX8907_LDO20	23
+#define MAX8907_OUT5V	24
+#define MAX8907_OUT33V	25
+#define MAX8907_BBAT	26
+#define MAX8907_SDBY	27
+#define MAX8907_VRTC	28
+#define MAX8907_NUM_REGULATORS (MAX8907_VRTC + 1)
+
+/* IRQ definitions */
+enum {
+	MAX8907_IRQ_VCHG_DC_OVP = 0,
+	MAX8907_IRQ_VCHG_DC_F,
+	MAX8907_IRQ_VCHG_DC_R,
+	MAX8907_IRQ_VCHG_THM_OK_R,
+	MAX8907_IRQ_VCHG_THM_OK_F,
+	MAX8907_IRQ_VCHG_MBATTLOW_F,
+	MAX8907_IRQ_VCHG_MBATTLOW_R,
+	MAX8907_IRQ_VCHG_RST,
+	MAX8907_IRQ_VCHG_DONE,
+	MAX8907_IRQ_VCHG_TOPOFF,
+	MAX8907_IRQ_VCHG_TMR_FAULT,
+
+	MAX8907_IRQ_GPM_RSTIN = 0,
+	MAX8907_IRQ_GPM_MPL,
+	MAX8907_IRQ_GPM_SW_3SEC,
+	MAX8907_IRQ_GPM_EXTON_F,
+	MAX8907_IRQ_GPM_EXTON_R,
+	MAX8907_IRQ_GPM_SW_1SEC,
+	MAX8907_IRQ_GPM_SW_F,
+	MAX8907_IRQ_GPM_SW_R,
+	MAX8907_IRQ_GPM_SYSCKEN_F,
+	MAX8907_IRQ_GPM_SYSCKEN_R,
+
+	MAX8907_IRQ_RTC_ALARM1 = 0,
+	MAX8907_IRQ_RTC_ALARM0,
+};
+
+struct max8907_platform_data {
+	struct regulator_init_data *init_data[MAX8907_NUM_REGULATORS];
+	bool pm_off;
+};
+
+struct regmap_irq_chips_data;
+
+struct max8907 {
+	struct device			*dev;
+	struct mutex			irq_lock;
+	struct i2c_client		*i2c_gen;
+	struct i2c_client		*i2c_rtc;
+	struct regmap			*regmap_gen;
+	struct regmap			*regmap_rtc;
+	struct regmap_irq_chip_data	*irqc_chg;
+	struct regmap_irq_chip_data	*irqc_on_off;
+	struct regmap_irq_chip_data	*irqc_rtc;
+};
+
+#endif

+ 23 - 3
include/linux/mfd/max8925.h

@@ -158,8 +158,6 @@ enum {
 #define TSC_IRQ_MASK			(0x03)
 #define TSC_IRQ_MASK			(0x03)
 #define RTC_IRQ_MASK			(0x0c)
 #define RTC_IRQ_MASK			(0x0c)
 
 
-#define MAX8925_MAX_REGULATOR		(23)
-
 #define MAX8925_NAME_SIZE		(32)
 #define MAX8925_NAME_SIZE		(32)
 
 
 /* IRQ definitions */
 /* IRQ definitions */
@@ -236,7 +234,29 @@ struct max8925_platform_data {
 	struct max8925_backlight_pdata	*backlight;
 	struct max8925_backlight_pdata	*backlight;
 	struct max8925_touch_pdata	*touch;
 	struct max8925_touch_pdata	*touch;
 	struct max8925_power_pdata	*power;
 	struct max8925_power_pdata	*power;
-	struct regulator_init_data	*regulator[MAX8925_MAX_REGULATOR];
+	struct regulator_init_data	*sd1;
+	struct regulator_init_data	*sd2;
+	struct regulator_init_data	*sd3;
+	struct regulator_init_data	*ldo1;
+	struct regulator_init_data	*ldo2;
+	struct regulator_init_data	*ldo3;
+	struct regulator_init_data	*ldo4;
+	struct regulator_init_data	*ldo5;
+	struct regulator_init_data	*ldo6;
+	struct regulator_init_data	*ldo7;
+	struct regulator_init_data	*ldo8;
+	struct regulator_init_data	*ldo9;
+	struct regulator_init_data	*ldo10;
+	struct regulator_init_data	*ldo11;
+	struct regulator_init_data	*ldo12;
+	struct regulator_init_data	*ldo13;
+	struct regulator_init_data	*ldo14;
+	struct regulator_init_data	*ldo15;
+	struct regulator_init_data	*ldo16;
+	struct regulator_init_data	*ldo17;
+	struct regulator_init_data	*ldo18;
+	struct regulator_init_data	*ldo19;
+	struct regulator_init_data	*ldo20;
 
 
 	int		irq_base;
 	int		irq_base;
 	int		tsc_irq;
 	int		tsc_irq;

+ 202 - 30
include/linux/mfd/palmas.h

@@ -23,6 +23,9 @@
 #define PALMAS_NUM_CLIENTS		3
 #define PALMAS_NUM_CLIENTS		3
 
 
 struct palmas_pmic;
 struct palmas_pmic;
+struct palmas_gpadc;
+struct palmas_resource;
+struct palmas_usb;
 
 
 struct palmas {
 struct palmas {
 	struct device *dev;
 	struct device *dev;
@@ -41,6 +44,9 @@ struct palmas {
 
 
 	/* Child Devices */
 	/* Child Devices */
 	struct palmas_pmic *pmic;
 	struct palmas_pmic *pmic;
+	struct palmas_gpadc *gpadc;
+	struct palmas_resource *resource;
+	struct palmas_usb *usb;
 
 
 	/* GPIO MUXing */
 	/* GPIO MUXing */
 	u8 gpio_muxed;
 	u8 gpio_muxed;
@@ -48,6 +54,23 @@ struct palmas {
 	u8 pwm_muxed;
 	u8 pwm_muxed;
 };
 };
 
 
+struct palmas_gpadc_platform_data {
+	/* Channel 3 current source is only enabled during conversion */
+	int ch3_current;
+
+	/* Channel 0 current source can be used for battery detection.
+	 * If used for battery detection this will cause a permanent current
+	 * consumption depending on current level set here.
+	 */
+	int ch0_current;
+
+	/* default BAT_REMOVAL_DAT setting on device probe */
+	int bat_removal;
+
+	/* Sets the START_POLARITY bit in the RT_CTRL register */
+	int start_polarity;
+};
+
 struct palmas_reg_init {
 struct palmas_reg_init {
 	/* warm_rest controls the voltage levels after a warm reset
 	/* warm_rest controls the voltage levels after a warm reset
 	 *
 	 *
@@ -107,21 +130,94 @@ struct palmas_reg_init {
 
 
 };
 };
 
 
+enum palmas_regulators {
+	/* SMPS regulators */
+	PALMAS_REG_SMPS12,
+	PALMAS_REG_SMPS123,
+	PALMAS_REG_SMPS3,
+	PALMAS_REG_SMPS45,
+	PALMAS_REG_SMPS457,
+	PALMAS_REG_SMPS6,
+	PALMAS_REG_SMPS7,
+	PALMAS_REG_SMPS8,
+	PALMAS_REG_SMPS9,
+	PALMAS_REG_SMPS10,
+	/* LDO regulators */
+	PALMAS_REG_LDO1,
+	PALMAS_REG_LDO2,
+	PALMAS_REG_LDO3,
+	PALMAS_REG_LDO4,
+	PALMAS_REG_LDO5,
+	PALMAS_REG_LDO6,
+	PALMAS_REG_LDO7,
+	PALMAS_REG_LDO8,
+	PALMAS_REG_LDO9,
+	PALMAS_REG_LDOLN,
+	PALMAS_REG_LDOUSB,
+	/* Total number of regulators */
+	PALMAS_NUM_REGS,
+};
+
 struct palmas_pmic_platform_data {
 struct palmas_pmic_platform_data {
 	/* An array of pointers to regulator init data indexed by regulator
 	/* An array of pointers to regulator init data indexed by regulator
 	 * ID
 	 * ID
 	 */
 	 */
-	struct regulator_init_data **reg_data;
+	struct regulator_init_data *reg_data[PALMAS_NUM_REGS];
 
 
 	/* An array of pointers to structures containing sleep mode and DVS
 	/* An array of pointers to structures containing sleep mode and DVS
 	 * configuration for regulators indexed by ID
 	 * configuration for regulators indexed by ID
 	 */
 	 */
-	struct palmas_reg_init **reg_init;
+	struct palmas_reg_init *reg_init[PALMAS_NUM_REGS];
 
 
 	/* use LDO6 for vibrator control */
 	/* use LDO6 for vibrator control */
 	int ldo6_vibrator;
 	int ldo6_vibrator;
+};
 
 
+struct palmas_usb_platform_data {
+	/* Set this if platform wishes its own vbus control */
+	int no_control_vbus;
 
 
+	/* Do we enable the wakeup comparator on probe */
+	int wakeup;
+};
+
+struct palmas_resource_platform_data {
+	int regen1_mode_sleep;
+	int regen2_mode_sleep;
+	int sysen1_mode_sleep;
+	int sysen2_mode_sleep;
+
+	/* bitfield to be loaded to NSLEEP_RES_ASSIGN */
+	u8 nsleep_res;
+	/* bitfield to be loaded to NSLEEP_SMPS_ASSIGN */
+	u8 nsleep_smps;
+	/* bitfield to be loaded to NSLEEP_LDO_ASSIGN1 */
+	u8 nsleep_ldo1;
+	/* bitfield to be loaded to NSLEEP_LDO_ASSIGN2 */
+	u8 nsleep_ldo2;
+
+	/* bitfield to be loaded to ENABLE1_RES_ASSIGN */
+	u8 enable1_res;
+	/* bitfield to be loaded to ENABLE1_SMPS_ASSIGN */
+	u8 enable1_smps;
+	/* bitfield to be loaded to ENABLE1_LDO_ASSIGN1 */
+	u8 enable1_ldo1;
+	/* bitfield to be loaded to ENABLE1_LDO_ASSIGN2 */
+	u8 enable1_ldo2;
+
+	/* bitfield to be loaded to ENABLE2_RES_ASSIGN */
+	u8 enable2_res;
+	/* bitfield to be loaded to ENABLE2_SMPS_ASSIGN */
+	u8 enable2_smps;
+	/* bitfield to be loaded to ENABLE2_LDO_ASSIGN1 */
+	u8 enable2_ldo1;
+	/* bitfield to be loaded to ENABLE2_LDO_ASSIGN2 */
+	u8 enable2_ldo2;
+};
+
+struct palmas_clk_platform_data {
+	int clk32kg_mode_sleep;
+	int clk32kgaudio_mode_sleep;
 };
 };
 
 
 struct palmas_platform_data {
 struct palmas_platform_data {
@@ -138,8 +234,49 @@ struct palmas_platform_data {
 	u8 pad1, pad2;
 	u8 pad1, pad2;
 
 
 	struct palmas_pmic_platform_data *pmic_pdata;
 	struct palmas_pmic_platform_data *pmic_pdata;
+	struct palmas_gpadc_platform_data *gpadc_pdata;
+	struct palmas_usb_platform_data *usb_pdata;
+	struct palmas_resource_platform_data *resource_pdata;
+	struct palmas_clk_platform_data *clk_pdata;
+};
+
+struct palmas_gpadc_calibration {
+	s32 gain;
+	s32 gain_error;
+	s32 offset_error;
 };
 };
 
 
+struct palmas_gpadc {
+	struct device *dev;
+	struct palmas *palmas;
+
+	int ch3_current;
+	int ch0_current;
+
+	int gpadc_force;
+
+	int bat_removal;
+
+	struct mutex reading_lock;
+	struct completion irq_complete;
+
+	int eoc_sw_irq;
+
+	struct palmas_gpadc_calibration *palmas_cal_tbl;
+
+	int conv0_channel;
+	int conv1_channel;
+	int rt_channel;
+};
+
+struct palmas_gpadc_result {
+	s32 raw_code;
+	s32 corrected_code;
+	s32 result;
+};
+
+#define PALMAS_MAX_CHANNELS 16
+
 /* Define the palmas IRQ numbers */
 /* Define the palmas IRQ numbers */
 enum palmas_irqs {
 enum palmas_irqs {
 	/* INT1 registers */
 	/* INT1 registers */
@@ -182,34 +319,6 @@ enum palmas_irqs {
 	PALMAS_NUM_IRQ,
 	PALMAS_NUM_IRQ,
 };
 };
 
 
-enum palmas_regulators {
-	/* SMPS regulators */
-	PALMAS_REG_SMPS12,
-	PALMAS_REG_SMPS123,
-	PALMAS_REG_SMPS3,
-	PALMAS_REG_SMPS45,
-	PALMAS_REG_SMPS457,
-	PALMAS_REG_SMPS6,
-	PALMAS_REG_SMPS7,
-	PALMAS_REG_SMPS8,
-	PALMAS_REG_SMPS9,
-	PALMAS_REG_SMPS10,
-	/* LDO regulators */
-	PALMAS_REG_LDO1,
-	PALMAS_REG_LDO2,
-	PALMAS_REG_LDO3,
-	PALMAS_REG_LDO4,
-	PALMAS_REG_LDO5,
-	PALMAS_REG_LDO6,
-	PALMAS_REG_LDO7,
-	PALMAS_REG_LDO8,
-	PALMAS_REG_LDO9,
-	PALMAS_REG_LDOLN,
-	PALMAS_REG_LDOUSB,
-	/* Total number of regulators */
-	PALMAS_NUM_REGS,
-};
-
 struct palmas_pmic {
 struct palmas_pmic {
 	struct palmas *palmas;
 	struct palmas *palmas;
 	struct device *dev;
 	struct device *dev;
@@ -223,6 +332,69 @@ struct palmas_pmic {
 	int range[PALMAS_REG_SMPS10];
 	int range[PALMAS_REG_SMPS10];
 };
 };
 
 
+struct palmas_resource {
+	struct palmas *palmas;
+	struct device *dev;
+};
+
+struct palmas_usb {
+	struct palmas *palmas;
+	struct device *dev;
+
+	/* for vbus reporting with irqs disabled */
+	spinlock_t lock;
+
+	struct regulator *vbus_reg;
+
+	/* used to set vbus, in atomic path */
+	struct work_struct set_vbus_work;
+
+	int irq1;
+	int irq2;
+	int irq3;
+	int irq4;
+
+	int vbus_enable;
+
+	u8 linkstat;
+};
+
+#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
+
+enum usb_irq_events {
+	/* Wakeup events from INT3 */
+	PALMAS_USB_ID_WAKEPUP,
+	PALMAS_USB_VBUS_WAKEUP,
+
+	/* ID_OTG_EVENTS */
+	PALMAS_USB_ID_GND,
+	N_PALMAS_USB_ID_GND,
+	PALMAS_USB_ID_C,
+	N_PALMAS_USB_ID_C,
+	PALMAS_USB_ID_B,
+	N_PALMAS_USB_ID_B,
+	PALMAS_USB_ID_A,
+	N_PALMAS_USB_ID_A,
+	PALMAS_USB_ID_FLOAT,
+	N_PALMAS_USB_ID_FLOAT,
+
+	/* VBUS_OTG_EVENTS */
+	PALMAS_USB_VB_SESS_END,
+	N_PALMAS_USB_VB_SESS_END,
+	PALMAS_USB_VB_SESS_VLD,
+	N_PALMAS_USB_VB_SESS_VLD,
+	PALMAS_USB_VA_SESS_VLD,
+	N_PALMAS_USB_VA_SESS_VLD,
+	PALMAS_USB_VA_VBUS_VLD,
+	N_PALMAS_USB_VA_VBUS_VLD,
+	PALMAS_USB_VADP_SNS,
+	N_PALMAS_USB_VADP_SNS,
+	PALMAS_USB_VADP_PRB,
+	N_PALMAS_USB_VADP_PRB,
+	PALMAS_USB_VOTG_SESS_VLD,
+	N_PALMAS_USB_VOTG_SESS_VLD,
+};
+
 /* defines so we can store the mux settings */
 /* defines so we can store the mux settings */
 #define PALMAS_GPIO_0_MUXED					(1 << 0)
 #define PALMAS_GPIO_0_MUXED					(1 << 0)
 #define PALMAS_GPIO_1_MUXED					(1 << 1)
 #define PALMAS_GPIO_1_MUXED					(1 << 1)

+ 109 - 0
include/linux/mfd/smsc.h

@@ -0,0 +1,109 @@
+/*
+ * SMSC ECE1099
+ *
+ * Copyright 2012 Texas Instruments Inc.
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.com>
+ *
+ *  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_MFD_SMSC_H
+#define __LINUX_MFD_SMSC_H
+
+#include <linux/regmap.h>
+
+#define SMSC_ID_ECE1099			1
+#define SMSC_NUM_CLIENTS		2
+
+#define SMSC_BASE_ADDR			0x38
+#define OMAP_GPIO_SMSC_IRQ		151
+
+#define SMSC_MAXGPIO         32
+#define SMSC_BANK(offs)      ((offs) >> 3)
+#define SMSC_BIT(offs)       (1u << ((offs) & 0x7))
+
+struct smsc {
+	struct device *dev;
+	struct i2c_client *i2c_clients[SMSC_NUM_CLIENTS];
+	struct regmap *regmap;
+	int clk;
+	/* Stored chip id */
+	int id;
+};
+
+struct smsc_gpio;
+struct smsc_keypad;
+
+static inline int smsc_read(struct device *child, unsigned int reg,
+	unsigned int *dest)
+{
+	struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+	return regmap_read(smsc->regmap, reg, dest);
+}
+
+static inline int smsc_write(struct device *child, unsigned int reg,
+	unsigned int value)
+{
+	struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+	return regmap_write(smsc->regmap, reg, value);
+}
+
+/* Registers for SMSC */
+#define SMSC_RESET						0xF5
+#define SMSC_GRP_INT						0xF9
+#define SMSC_CLK_CTRL						0xFA
+#define SMSC_WKUP_CTRL						0xFB
+#define SMSC_DEV_ID						0xFC
+#define SMSC_DEV_REV						0xFD
+#define SMSC_VEN_ID_L						0xFE
+#define SMSC_VEN_ID_H						0xFF
+
+/* CLK VALUE */
+#define SMSC_CLK_VALUE						0x13
+
+/* Registers for function GPIO INPUT */
+#define SMSC_GPIO_DATA_IN_START					0x00
+
+/* Registers for function GPIO OUPUT */
+#define SMSC_GPIO_DATA_OUT_START                                       0x05
+
+/* Definitions for SMSC GPIO CONFIGURATION REGISTER*/
+#define SMSC_GPIO_INPUT_LOW					0x01
+#define SMSC_GPIO_INPUT_RISING					0x09
+#define SMSC_GPIO_INPUT_FALLING					0x11
+#define SMSC_GPIO_INPUT_BOTH_EDGE				0x19
+#define SMSC_GPIO_OUTPUT_PP					0x21
+#define SMSC_GPIO_OUTPUT_OP					0x31
+
+#define GRP_INT_STAT						0xf9
+#define	SMSC_GPI_INT						0x0f
+#define SMSC_CFG_START						0x0A
+
+/* Registers for SMSC GPIO INTERRUPT STATUS REGISTER*/
+#define SMSC_GPIO_INT_STAT_START                                  0x32
+
+/* Registers for SMSC GPIO INTERRUPT MASK REGISTER*/
+#define SMSC_GPIO_INT_MASK_START                               0x37
+
+/* Registers for SMSC function KEYPAD*/
+#define SMSC_KP_OUT						0x40
+#define SMSC_KP_IN						0x41
+#define SMSC_KP_INT_STAT					0x42
+#define SMSC_KP_INT_MASK					0x43
+
+/* Definitions for keypad */
+#define SMSC_KP_KSO           0x70
+#define SMSC_KP_KSI           0x51
+#define SMSC_KSO_ALL_LOW        0x20
+#define SMSC_KP_SET_LOW_PWR        0x0B
+#define SMSC_KP_SET_HIGH           0xFF
+#define SMSC_KSO_EVAL           0x00
+
+#endif /*  __LINUX_MFD_SMSC_H */

+ 23 - 0
include/linux/mfd/syscon.h

@@ -0,0 +1,23 @@
+/*
+ * System Control Driver
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.org>
+ *
+ * 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_MFD_SYSCON_H__
+#define __LINUX_MFD_SYSCON_H__
+
+extern struct regmap *syscon_node_to_regmap(struct device_node *np);
+extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
+extern struct regmap *syscon_regmap_lookup_by_phandle(
+					struct device_node *np,
+					const char *property);
+#endif /* __LINUX_MFD_SYSCON_H__ */

+ 319 - 0
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h

@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_IMX6Q_IOMUXC_GPR_H
+#define __LINUX_IMX6Q_IOMUXC_GPR_H
+
+#include <linux/bitops.h>
+
+#define IOMUXC_GPR0	0x00
+#define IOMUXC_GPR1	0x04
+#define IOMUXC_GPR2	0x08
+#define IOMUXC_GPR3	0x0c
+#define IOMUXC_GPR4	0x10
+#define IOMUXC_GPR5	0x14
+#define IOMUXC_GPR6	0x18
+#define IOMUXC_GPR7	0x1c
+#define IOMUXC_GPR8	0x20
+#define IOMUXC_GPR9	0x24
+#define IOMUXC_GPR10	0x28
+#define IOMUXC_GPR11	0x2c
+#define IOMUXC_GPR12	0x30
+#define IOMUXC_GPR13	0x34
+
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_MASK		(0x3 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7_MUXED	(0x0 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7	(0x1 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_SSI_SRCK	(0x2 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_RX_BIT_CLK	(0x3 << 30)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_MASK		(0x3 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR_MUXED	(0x0 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR	(0x1 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_DO_SCKR	(0x2 << 28)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_MASK		(0x3 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7_MUXED	(0x0 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7	(0x1 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_SSI_STCK	(0x2 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_TX_BIT_CLK	(0x3 << 26)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_MASK		(0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7_MUXED	(0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7	(0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_SSI_SRCK	(0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_RX_BIT_CLK	(0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_MASK		(0x3 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2_MUXED	(0x0 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2	(0x1 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_SSI_STCK	(0x2 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_TX_BIT_CLK	(0x3 << 22)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_MASK		(0x3 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2_MUXED	(0x0 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2	(0x1 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_SSI_SRCK	(0x2 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_RX_BIT_CLK	(0x3 << 20)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_MASK		(0x3 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1_MUXED	(0x0 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1	(0x1 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_STCK	(0x2 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_TX_BIT_CLK	(0x3 << 18)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_MASK		(0x3 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1_MUXED	(0x0 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1	(0x1 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_SRCK	(0x2 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_RX_BIT_CLK	(0x3 << 16)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_MASK		(0x3 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK1	(0x0 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK2	(0x1 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK3	(0x2 << 14)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_MASK		BIT(7)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_SPDIF	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_IOMUX	BIT(7)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_MASK		BIT(6)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_ESAI		0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_I2C3		BIT(6)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_MASK		BIT(5)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_ECSPI4	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_EPIT2	BIT(5)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_MASK		BIT(4)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_ECSPI4	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_I2C1		BIT(4)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_MASK		BIT(3)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_ECSPI2	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_I2C1		BIT(3)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_MASK		BIT(2)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_ECSPI1	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_I2C2		BIT(2)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_MASK		BIT(1)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_ECSPI1	0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_I2C3		BIT(1)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_MASK		BIT(0)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IPU1		0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IOMUX	BIT(0)
+
+#define IMX6Q_GPR1_PCIE_REQ_MASK		(0x3 << 30)
+#define IMX6Q_GPR1_PCIE_EXIT_L1			BIT(28)
+#define IMX6Q_GPR1_PCIE_RDY_L23			BIT(27)
+#define IMX6Q_GPR1_PCIE_ENTER_L1		BIT(26)
+#define IMX6Q_GPR1_MIPI_COLOR_SW		BIT(25)
+#define IMX6Q_GPR1_DPI_OFF			BIT(24)
+#define IMX6Q_GPR1_EXC_MON_MASK			BIT(22)
+#define IMX6Q_GPR1_EXC_MON_OKAY			0x0
+#define IMX6Q_GPR1_EXC_MON_SLVE			BIT(22)
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_MASK		BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_GASKET		0x0
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_IOMUX		BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK		BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET		0x0
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX		BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK		BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_GASKET		0x0
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX		BIT(19)
+#define IMX6Q_GPR1_PCIE_TEST_PD			BIT(18)
+#define IMX6Q_GPR1_IPU_VPU_MUX_MASK		BIT(17)
+#define IMX6Q_GPR1_IPU_VPU_MUX_IPU1		0x0
+#define IMX6Q_GPR1_IPU_VPU_MUX_IPU2		BIT(17)
+#define IMX6Q_GPR1_PCIE_REF_CLK_EN		BIT(16)
+#define IMX6Q_GPR1_USB_EXP_MODE			BIT(15)
+#define IMX6Q_GPR1_PCIE_INT			BIT(14)
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_MASK		BIT(13)
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_ENET_RX_ER	0x0
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_GPIO_1	BIT(13)
+#define IMX6Q_GPR1_GINT				BIT(12)
+#define IMX6Q_GPR1_ADDRS3_MASK			(0x3 << 10)
+#define IMX6Q_GPR1_ADDRS3_32MB			(0x0 << 10)
+#define IMX6Q_GPR1_ADDRS3_64MB			(0x1 << 10)
+#define IMX6Q_GPR1_ADDRS3_128MB			(0x2 << 10)
+#define IMX6Q_GPR1_ACT_CS3			BIT(9)
+#define IMX6Q_GPR1_ADDRS2_MASK			(0x3 << 7)
+#define IMX6Q_GPR1_ACT_CS2			BIT(6)
+#define IMX6Q_GPR1_ADDRS1_MASK			(0x3 << 4)
+#define IMX6Q_GPR1_ACT_CS1			BIT(3)
+#define IMX6Q_GPR1_ADDRS0_MASK			(0x3 << 1)
+#define IMX6Q_GPR1_ACT_CS0			BIT(0)
+
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_MASK	(0x3 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_5		(0x0 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_3		(0x1 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_4		(0x2 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_6		(0x3 << 20)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_MASK		(0x7 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_0		(0x0 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_1		(0x1 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_2		(0x2 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_3		(0x3 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_4		(0x4 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_5		(0x5 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_6		(0x6 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_7		(0x7 << 16)
+#define IMX6Q_GPR2_BGREF_RRMODE_MASK		BIT(15)
+#define IMX6Q_GPR2_BGREF_RRMODE_EXT_RESISTOR	0x0
+#define IMX6Q_GPR2_BGREF_RRMODE_INT_RESISTOR	BIT(15)
+#define IMX6Q_GPR2_DI1_VS_POLARITY_MASK		BIT(10)
+#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_H	0x0
+#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_L	BIT(10)
+#define IMX6Q_GPR2_DI0_VS_POLARITY_MASK		BIT(9)
+#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_H	0x0
+#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_L	BIT(9)
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_MASK		BIT(8)
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_SPWG		0x0
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_JEIDA	BIT(8)
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_MASK		BIT(7)
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_18BIT		0x0
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_24BIT		BIT(7)
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_MASK		BIT(6)
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_SPWG		0x0
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_JEIDA	BIT(6)
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_MASK		BIT(5)
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_18BIT		0x0
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_24BIT		BIT(5)
+#define IMX6Q_GPR2_SPLIT_MODE_EN		BIT(4)
+#define IMX6Q_GPR2_CH1_MODE_MASK		(0x3 << 2)
+#define IMX6Q_GPR2_CH1_MODE_DISABLE		(0x0 << 2)
+#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI0	(0x1 << 2)
+#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI1	(0x3 << 2)
+#define IMX6Q_GPR2_CH0_MODE_MASK		(0x3 << 0)
+#define IMX6Q_GPR2_CH0_MODE_DISABLE		(0x0 << 0)
+#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI0	(0x1 << 0)
+#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI1	(0x3 << 0)
+
+#define IMX6Q_GPR3_GPU_DBG_MASK			(0x3 << 29)
+#define IMX6Q_GPR3_GPU_DBG_GPU3D		(0x0 << 29)
+#define IMX6Q_GPR3_GPU_DBG_GPU2D		(0x1 << 29)
+#define IMX6Q_GPR3_GPU_DBG_OPENVG		(0x2 << 29)
+#define IMX6Q_GPR3_BCH_WR_CACHE_CTL		BIT(28)
+#define IMX6Q_GPR3_BCH_RD_CACHE_CTL		BIT(27)
+#define IMX6Q_GPR3_USDHCX_WR_CACHE_CTL		BIT(26)
+#define IMX6Q_GPR3_USDHCX_RD_CACHE_CTL		BIT(25)
+#define IMX6Q_GPR3_OCRAM_CTL_MASK		(0xf << 21)
+#define IMX6Q_GPR3_OCRAM_STATUS_MASK		(0xf << 17)
+#define IMX6Q_GPR3_CORE3_DBG_ACK_EN		BIT(16)
+#define IMX6Q_GPR3_CORE2_DBG_ACK_EN		BIT(15)
+#define IMX6Q_GPR3_CORE1_DBG_ACK_EN		BIT(14)
+#define IMX6Q_GPR3_CORE0_DBG_ACK_EN		BIT(13)
+#define IMX6Q_GPR3_TZASC2_BOOT_LOCK		BIT(12)
+#define IMX6Q_GPR3_TZASC1_BOOT_LOCK		BIT(11)
+#define IMX6Q_GPR3_IPU_DIAG_MASK		BIT(10)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_MASK		(0x3 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI0	(0x0 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI1	(0x1 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI0	(0x2 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI1	(0x3 << 8)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_MASK		(0x3 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI0	(0x0 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1	(0x1 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0	(0x2 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1	(0x3 << 6)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_MASK		(0x3 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI0	(0x0 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1	(0x1 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI0	(0x2 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI1	(0x3 << 4)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_MASK		(0x3 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI0	(0x0 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI1	(0x1 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI0	(0x2 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI1	(0x3 << 2)
+
+#define IMX6Q_GPR4_VDOA_WR_CACHE_SEL		BIT(31)
+#define IMX6Q_GPR4_VDOA_RD_CACHE_SEL		BIT(30)
+#define IMX6Q_GPR4_VDOA_WR_CACHE_VAL		BIT(29)
+#define IMX6Q_GPR4_VDOA_RD_CACHE_VAL		BIT(28)
+#define IMX6Q_GPR4_PCIE_WR_CACHE_SEL		BIT(27)
+#define IMX6Q_GPR4_PCIE_RD_CACHE_SEL		BIT(26)
+#define IMX6Q_GPR4_PCIE_WR_CACHE_VAL		BIT(25)
+#define IMX6Q_GPR4_PCIE_RD_CACHE_VAL		BIT(24)
+#define IMX6Q_GPR4_SDMA_STOP_ACK		BIT(19)
+#define IMX6Q_GPR4_CAN2_STOP_ACK		BIT(18)
+#define IMX6Q_GPR4_CAN1_STOP_ACK		BIT(17)
+#define IMX6Q_GPR4_ENET_STOP_ACK		BIT(16)
+#define IMX6Q_GPR4_SOC_VERSION_MASK		(0xff << 8)
+#define IMX6Q_GPR4_SOC_VERSION_OFF		0x8
+#define IMX6Q_GPR4_VPU_WR_CACHE_SEL		BIT(7)
+#define IMX6Q_GPR4_VPU_RD_CACHE_SEL		BIT(6)
+#define IMX6Q_GPR4_VPU_P_WR_CACHE_VAL		BIT(3)
+#define IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK	BIT(2)
+#define IMX6Q_GPR4_IPU_WR_CACHE_CTL		BIT(1)
+#define IMX6Q_GPR4_IPU_RD_CACHE_CTL		BIT(0)
+
+#define IMX6Q_GPR5_L2_CLK_STOP			BIT(8)
+
+#define IMX6Q_GPR9_TZASC2_BYP			BIT(1)
+#define IMX6Q_GPR9_TZASC1_BYP			BIT(0)
+
+#define IMX6Q_GPR10_LOCK_DBG_EN			BIT(29)
+#define IMX6Q_GPR10_LOCK_DBG_CLK_EN		BIT(28)
+#define IMX6Q_GPR10_LOCK_SEC_ERR_RESP		BIT(27)
+#define IMX6Q_GPR10_LOCK_OCRAM_TZ_ADDR		(0x3f << 21)
+#define IMX6Q_GPR10_LOCK_OCRAM_TZ_EN		BIT(20)
+#define IMX6Q_GPR10_LOCK_DCIC2_MUX_MASK		(0x3 << 18)
+#define IMX6Q_GPR10_LOCK_DCIC1_MUX_MASK		(0x3 << 16)
+#define IMX6Q_GPR10_DBG_EN			BIT(13)
+#define IMX6Q_GPR10_DBG_CLK_EN			BIT(12)
+#define IMX6Q_GPR10_SEC_ERR_RESP_MASK		BIT(11)
+#define IMX6Q_GPR10_SEC_ERR_RESP_OKEY		0x0
+#define IMX6Q_GPR10_SEC_ERR_RESP_SLVE		BIT(11)
+#define IMX6Q_GPR10_OCRAM_TZ_ADDR_MASK		(0x3f << 5)
+#define IMX6Q_GPR10_OCRAM_TZ_EN_MASK		BIT(4)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_MASK		(0x3 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI0	(0x0 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1	(0x1 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI0	(0x2 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI1	(0x3 << 2)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_MASK		(0x3 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI0	(0x0 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI1	(0x1 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI0	(0x2 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI1	(0x3 << 0)
+
+#define IMX6Q_GPR12_ARMP_IPG_CLK_EN		BIT(27)
+#define IMX6Q_GPR12_ARMP_AHB_CLK_EN		BIT(26)
+#define IMX6Q_GPR12_ARMP_ATB_CLK_EN		BIT(25)
+#define IMX6Q_GPR12_ARMP_APB_CLK_EN		BIT(24)
+#define IMX6Q_GPR12_PCIE_CTL_2			BIT(10)
+
+#define IMX6Q_GPR13_SDMA_STOP_REQ		BIT(30)
+#define IMX6Q_GPR13_CAN2_STOP_REQ		BIT(29)
+#define IMX6Q_GPR13_CAN1_STOP_REQ		BIT(28)
+#define IMX6Q_GPR13_ENET_STOP_REQ		BIT(27)
+#define IMX6Q_GPR13_SATA_PHY_8_MASK		(0x7 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_0_5_DB		(0x0 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_1_0_DB		(0x1 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_1_5_DB		(0x2 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_2_0_DB		(0x3 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_2_5_DB		(0x4 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_3_0_DB		(0x5 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_3_5_DB		(0x6 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_4_0_DB		(0x7 << 24)
+#define IMX6Q_GPR13_SATA_PHY_7_MASK		(0x1f << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1I		(0x10 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1M		(0x10 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1X		(0x1a << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2I		(0x12 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2M		(0x12 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2X		(0x1a << 19)
+#define IMX6Q_GPR13_SATA_PHY_6_MASK		(0x7 << 16)
+#define IMX6Q_GPR13_SATA_SPEED_MASK		BIT(15)
+#define IMX6Q_GPR13_SATA_SPEED_1P5G		0x0
+#define IMX6Q_GPR13_SATA_SPEED_3P0G		BIT(15)
+#define IMX6Q_GPR13_SATA_PHY_5			BIT(14)
+#define IMX6Q_GPR13_SATA_PHY_4_MASK		(0x7 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_16_16		(0x0 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_14_16		(0x1 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_12_16		(0x2 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_10_16		(0x3 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_9_16		(0x4 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_8_16		(0x5 << 11)
+#define IMX6Q_GPR13_SATA_PHY_3_MASK		(0xf << 7)
+#define IMX6Q_GPR13_SATA_PHY_3_OFF		0x7
+#define IMX6Q_GPR13_SATA_PHY_2_MASK		(0x1f << 2)
+#define IMX6Q_GPR13_SATA_PHY_2_OFF		0x2
+#define IMX6Q_GPR13_SATA_PHY_1_MASK		(0x3 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_FAST		(0x0 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_MED		(0x1 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_SLOW		(0x2 << 0)
+
+#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */

+ 1 - 0
include/linux/mfd/tc3589x.h

@@ -117,6 +117,7 @@ struct tc3589x {
 	struct mutex lock;
 	struct mutex lock;
 	struct device *dev;
 	struct device *dev;
 	struct i2c_client *i2c;
 	struct i2c_client *i2c;
+	struct irq_domain *domain;
 
 
 	int irq_base;
 	int irq_base;
 	int num_gpio;
 	int num_gpio;

部分文件因文件數量過多而無法顯示