Setup Iintial baseline based on LK3.14 v0.0.init
authorDaniel jeong <daniel.jeong@ti.com>
Wed, 30 Apr 2014 07:29:24 +0000 (16:29 +0900)
committerDaniel jeong <daniel.jeong@ti.com>
Wed, 30 Apr 2014 07:29:24 +0000 (16:29 +0900)
Signed-off-by: Daniel jeong <daniel.jeong@ti.com>
57 files changed:
Documentation/devicetree/bindings/gpio/gpio-lp3943.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-lp55xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/lp3943.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/lp8727_charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/lp872x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/backlight/lp855x.txt [new file with mode: 0644]
Documentation/leds/leds-lm3556.txt [new file with mode: 0644]
Documentation/leds/leds-lp5562.txt [new file with mode: 0644]
Documentation/leds/leds-lp55xx.txt [new file with mode: 0644]
drivers/gpio/Kconfig [new file with mode: 0644]
drivers/gpio/Makefile [new file with mode: 0644]
drivers/gpio/gpio-lp3943.c [new file with mode: 0644]
drivers/leds/Kconfig [new file with mode: 0644]
drivers/leds/Makefile [new file with mode: 0644]
drivers/leds/leds-lm355x.c [new file with mode: 0644]
drivers/leds/leds-lm3642.c [new file with mode: 0644]
drivers/leds/leds-lp5562.c [new file with mode: 0644]
drivers/leds/leds-lp55xx-common.c [new file with mode: 0644]
drivers/leds/leds-lp55xx-common.h [new file with mode: 0644]
drivers/leds/leds-lp8501.c [new file with mode: 0644]
drivers/leds/leds-lp8788.c [new file with mode: 0644]
drivers/media/i2c/Kconfig [new file with mode: 0644]
drivers/media/i2c/Makefile [new file with mode: 0644]
drivers/media/i2c/lm3560.c [new file with mode: 0644]
drivers/mfd/Kconfig [new file with mode: 0644]
drivers/mfd/Makefile [new file with mode: 0644]
drivers/mfd/lp3943.c [new file with mode: 0644]
drivers/mfd/lp8788-irq.c [new file with mode: 0644]
drivers/mfd/lp8788.c [new file with mode: 0644]
drivers/power/Kconfig [new file with mode: 0644]
drivers/power/Makefile [new file with mode: 0644]
drivers/power/lp8727_charger.c [new file with mode: 0644]
drivers/power/lp8788-charger.c [new file with mode: 0644]
drivers/regulator/Kconfig [new file with mode: 0644]
drivers/regulator/Makefile [new file with mode: 0644]
drivers/regulator/lp872x.c [new file with mode: 0644]
drivers/regulator/lp8755.c [new file with mode: 0644]
drivers/regulator/lp8788-buck.c [new file with mode: 0644]
drivers/regulator/lp8788-ldo.c [new file with mode: 0644]
drivers/rtc/Kconfig [new file with mode: 0644]
drivers/rtc/Makefile [new file with mode: 0644]
drivers/rtc/rtc-lp8788.c [new file with mode: 0644]
drivers/video/backlight/Kconfig [new file with mode: 0644]
drivers/video/backlight/Makefile [new file with mode: 0644]
drivers/video/backlight/lm3630a_bl.c [new file with mode: 0644]
drivers/video/backlight/lm3639_bl.c [new file with mode: 0644]
drivers/video/backlight/lp855x_bl.c [new file with mode: 0644]
drivers/video/backlight/lp8788_bl.c [new file with mode: 0644]
include/linux/platform_data/leds-lm355x.h [new file with mode: 0644]
include/linux/platform_data/leds-lm3642.h [new file with mode: 0644]
include/linux/platform_data/leds-lp55xx.h [new file with mode: 0644]
include/linux/platform_data/lm3630a_bl.h [new file with mode: 0644]
include/linux/platform_data/lm3639_bl.h [new file with mode: 0644]
include/linux/platform_data/lp855x.h [new file with mode: 0644]
include/linux/platform_data/lp8727.h [new file with mode: 0644]
include/linux/platform_data/lp8755.h [new file with mode: 0644]
include/media/lm3560.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/gpio/gpio-lp3943.txt b/Documentation/devicetree/bindings/gpio/gpio-lp3943.txt
new file mode 100644 (file)
index 0000000..80fcb7d
--- /dev/null
@@ -0,0 +1,37 @@
+TI/National Semiconductor LP3943 GPIO controller
+
+Required properties:
+  - compatible: "ti,lp3943-gpio"
+  - gpio-controller: Marks the device node as a GPIO controller.
+  - #gpio-cells: Should be 2. See gpio.txt in this directory for a
+                 description of the cells format.
+
+Example:
+Simple LED controls with LP3943 GPIO controller
+
+&i2c4 {
+       lp3943@60 {
+               compatible = "ti,lp3943";
+               reg = <0x60>;
+
+               gpioex: gpio {
+                       compatible = "ti,lp3943-gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+};
+
+leds {
+       compatible = "gpio-leds";
+       indicator1 {
+               label = "indi1";
+               gpios = <&gpioex 9 GPIO_ACTIVE_LOW>;
+       };
+
+       indicator2 {
+               label = "indi2";
+               gpios = <&gpioex 10 GPIO_ACTIVE_LOW>;
+               default-state = "off";
+       };
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
new file mode 100644 (file)
index 0000000..c55b8c0
--- /dev/null
@@ -0,0 +1,222 @@
+Binding for TI/National Semiconductor LP55xx Led Drivers
+
+Required properties:
+- compatible: "national,lp5521" or "national,lp5523" or "ti,lp5562" or "ti,lp8501"
+- reg: I2C slave address
+- clock-mode: Input clock mode, (0: automode, 1: internal, 2: external)
+
+Each child has own specific current settings
+- led-cur: Current setting at each led channel (mA x10, 0 if led is not connected)
+- max-cur: Maximun current at each led channel.
+
+Optional properties:
+- enable-gpio: GPIO attached to the chip's enable pin
+- label: Used for naming LEDs
+- pwr-sel: LP8501 specific property. Power selection for output channels.
+         0: D1~9 are connected to VDD
+         1: D1~6 with VDD, D7~9 with VOUT
+         2: D1~6 with VOUT, D7~9 with VDD
+         3: D1~9 are connected to VOUT
+
+Alternatively, each child can have a specific channel name and trigger:
+- chan-name (optional): name of channel
+- linux,default-trigger (optional): see
+  Documentation/devicetree/bindings/leds/common.txt
+
+example 1) LP5521
+3 LED channels, external clock used. Channel names are 'lp5521_pri:channel0',
+'lp5521_pri:channel1' and 'lp5521_pri:channel2', with a heartbeat trigger
+on channel 0.
+
+lp5521@32 {
+       compatible = "national,lp5521";
+       reg = <0x32>;
+       label = "lp5521_pri";
+       clock-mode = /bits/ 8 <2>;
+
+       chan0 {
+               led-cur = /bits/ 8 <0x2f>;
+               max-cur = /bits/ 8 <0x5f>;
+               linux,default-trigger = "heartbeat";
+       };
+
+       chan1 {
+               led-cur = /bits/ 8 <0x2f>;
+               max-cur = /bits/ 8 <0x5f>;
+       };
+
+       chan2 {
+               led-cur = /bits/ 8 <0x2f>;
+               max-cur = /bits/ 8 <0x5f>;
+       };
+};
+
+example 2) LP5523
+9 LED channels with specific name. Internal clock used.
+The I2C slave address is configurable with ASEL1 and ASEL0 pins.
+Available addresses are 32/33/34/35h.
+
+ASEL1    ASEL0    Address
+-------------------------
+ GND      GND       32h
+ GND      VEN       33h
+ VEN      GND       34h
+ VEN      VEN       35h
+
+lp5523@32 {
+       compatible = "national,lp5523";
+       reg = <0x32>;
+       clock-mode = /bits/ 8 <1>;
+
+       chan0 {
+               chan-name = "d1";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan1 {
+               chan-name = "d2";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan2 {
+               chan-name = "d3";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan3 {
+               chan-name = "d4";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan4 {
+               chan-name = "d5";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan5 {
+               chan-name = "d6";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan6 {
+               chan-name = "d7";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan7 {
+               chan-name = "d8";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan8 {
+               chan-name = "d9";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+};
+
+example 3) LP5562
+4 channels are defined.
+
+lp5562@30 {
+       compatible = "ti,lp5562";
+       reg = <0x30>;
+       clock-mode = /bits/8 <2>;
+
+       chan0 {
+               chan-name = "R";
+               led-cur = /bits/ 8 <0x20>;
+               max-cur = /bits/ 8 <0x60>;
+       };
+
+       chan1 {
+               chan-name = "G";
+               led-cur = /bits/ 8 <0x20>;
+               max-cur = /bits/ 8 <0x60>;
+       };
+
+       chan2 {
+               chan-name = "B";
+               led-cur = /bits/ 8 <0x20>;
+               max-cur = /bits/ 8 <0x60>;
+       };
+
+       chan3 {
+               chan-name = "W";
+               led-cur = /bits/ 8 <0x20>;
+               max-cur = /bits/ 8 <0x60>;
+       };
+};
+
+example 4) LP8501
+9 channels are defined. The 'pwr-sel' is LP8501 specific property.
+Others are same as LP5523.
+
+lp8501@32 {
+       compatible = "ti,lp8501";
+       reg = <0x32>;
+       clock-mode = /bits/ 8 <2>;
+       pwr-sel = /bits/ 8 <3>; /* D1~9 connected to VOUT */
+
+       chan0 {
+               chan-name = "d1";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan1 {
+               chan-name = "d2";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan2 {
+               chan-name = "d3";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan3 {
+               chan-name = "d4";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan4 {
+               chan-name = "d5";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan5 {
+               chan-name = "d6";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan6 {
+               chan-name = "d7";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan7 {
+               chan-name = "d8";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+
+       chan8 {
+               chan-name = "d9";
+               led-cur = /bits/ 8 <0x14>;
+               max-cur = /bits/ 8 <0x20>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/mfd/lp3943.txt b/Documentation/devicetree/bindings/mfd/lp3943.txt
new file mode 100644 (file)
index 0000000..e8591d6
--- /dev/null
@@ -0,0 +1,33 @@
+TI/National Semiconductor LP3943 MFD driver
+
+Required properties:
+  - compatible: "ti,lp3943"
+  - reg: I2C slave address. From 0x60 to 0x67.
+
+LP3943 consists of two sub-devices, lp3943-gpio and lp3943-pwm.
+
+For the LP3943 GPIO properties please refer to:
+Documentation/devicetree/bindings/gpio/gpio-lp3943.txt
+
+For the LP3943 PWM properties please refer to:
+Documentation/devicetree/bindings/pwm/pwm-lp3943.txt
+
+Example:
+
+lp3943@60 {
+       compatible = "ti,lp3943";
+       reg = <0x60>;
+
+       gpioex: gpio {
+               compatible = "ti,lp3943-gpio";
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       pwm3943: pwm {
+               compatible = "ti,lp3943-pwm";
+               #pwm-cells = <2>;
+               ti,pwm0 = <8 9 10>;
+               ti,pwm1 = <15>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/power_supply/lp8727_charger.txt b/Documentation/devicetree/bindings/power_supply/lp8727_charger.txt
new file mode 100644 (file)
index 0000000..2246bc5
--- /dev/null
@@ -0,0 +1,44 @@
+Binding for TI/National Semiconductor LP8727 Charger
+
+Required properties:
+- compatible: "ti,lp8727"
+- reg: I2C slave address 27h
+
+Optional properties:
+- interrupt-parent: interrupt controller node (see interrupt binding[0])
+- interrupts: interrupt specifier (see interrupt binding[0])
+- debounce-ms: interrupt debounce time. (u32)
+
+AC and USB charging parameters
+- charger-type: "ac" or "usb" (string)
+- eoc-level: value of 'enum lp8727_eoc_level' (u8)
+- charging-current: value of 'enum lp8727_ichg' (u8)
+
+[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Example)
+
+lp8727@27 {
+       compatible = "ti,lp8727";
+       reg = <0x27>;
+
+       /* GPIO 134 is used for LP8728 interrupt pin */
+       interrupt-parent = <&gpio5>;    /* base = 128 */
+       interrupts = <6 0x2>;           /* offset = 6, falling edge type */
+
+       debounce-ms = <300>;
+
+       /* AC charger: 5% EOC and 500mA charging current */
+       ac {
+               charger-type = "ac";
+               eoc-level = /bits/ 8 <0>;
+               charging-current = /bits/ 8 <4>;
+       };
+
+       /* USB charger: 10% EOC and 400mA charging current */
+       usb {
+               charger-type = "usb";
+               eoc-level = /bits/ 8 <1>;
+               charging-current = /bits/ 8 <2>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/regulator/lp872x.txt b/Documentation/devicetree/bindings/regulator/lp872x.txt
new file mode 100644 (file)
index 0000000..7818318
--- /dev/null
@@ -0,0 +1,160 @@
+Binding for TI/National Semiconductor LP872x Driver
+
+Required properties:
+  - compatible: "ti,lp8720" or "ti,lp8725"
+  - reg: I2C slave address. 0x7d = LP8720, 0x7a = LP8725
+
+Optional properties:
+  - ti,general-config: the value of LP872X_GENERAL_CFG register (u8)
+    (LP8720)
+    bit[2]: BUCK output voltage control by external DVS pin or register
+            1 = external pin, 0 = bit7 of register 08h
+    bit[1]: sleep control by external DVS pin or register
+            1 = external pin, 0 = bit6 of register 08h
+    bit[0]: time step unit(usec). 1 = 25, 0 = 50
+
+    (LP8725)
+    bit[7:6]: time step unit(usec). 00 = 32, 01 = 64, 10 = 128, 11 = 256
+    bit[4]:   BUCK2 enable control. 1 = enable, 0 = disable
+    bit[3]:   BUCK2 output voltage register address. 1 = 0Ah, 0 = 0Bh
+    bit[2]:   BUCK1 output voltage control by external DVS pin or register
+              1 = register 08h, 0 = DVS
+    bit[1]:   LDO sleep control. 1 = sleep mode, 0 = normal
+    bit[0]:   BUCK1 enable control, 1 = enable, 0 = disable
+
+    For more details, please see the datasheet.
+
+  - ti,update-config: define it when LP872X_GENERAL_CFG register should be set
+  - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices.
+  - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2.
+  - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH.
+
+  Sub nodes for regulator_init_data
+    LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck)
+    LP8725 has maximum 9 nodes. (child name: ldo1 ~ 5, lilo1,2 and buck1,2)
+    For more details, please see the following binding document.
+    (Documentation/devicetree/bindings/regulator/regulator.txt)
+
+Datasheet
+  - LP8720: http://www.ti.com/lit/ds/symlink/lp8720.pdf
+  - LP8725: http://www.ti.com/lit/ds/symlink/lp8725.pdf
+
+Example 1) LP8720
+
+lp8720@7d {
+       compatible = "ti,lp8720";
+       reg = <0x7d>;
+
+       /* external DVS pin used, timestep is 25usec */
+       ti,general-config = /bits/ 8 <0x03>;
+       ti,update-config;
+
+       /*
+        * The dvs-gpio depends on the processor environment.
+        * For example, following GPIO specifier means GPIO134 in OMAP4.
+        */
+       ti,dvs-gpio = <&gpio5 6 0>;
+       ti,dvs-vsel = /bits/ 8 <1>;             /* SEL_V2 */
+       ti,dvs-state = /bits/ 8 <1>;            /* DVS_HIGH */
+
+       vaf: ldo1 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vmmc: ldo2 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcam_io: ldo3 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+       };
+
+       vcam_core: ldo4 {
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <2850000>;
+               regulator-boot-on;
+       };
+
+       vcam: ldo5 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcc: buck {
+               regulator-name = "VBUCK";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <2300000>;
+       };
+};
+
+Example 2) LP8725
+
+lp8725@7a {
+       compatible = "ti,lp8725";
+       reg = <0x7a>;
+
+       /* Enable BUCK1,2, no DVS, normal LDO mode, timestep is 256usec */
+       ti,general-config = /bits/ 8 <0xdd>;
+       ti,update-config;
+
+       vcam_io: ldo1 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcam_core: ldo2 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcam: ldo3 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcmmb_io: ldo4 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+       };
+
+       vcmmb_core: ldo5 {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+       };
+
+       vaux1: lilo1 {
+               regulator-name = "VAUX1";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vaux2: lilo2 {
+               regulator-name = "VAUX2";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcc1: buck1 {
+               regulator-name = "VBUCK1";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <3000000>;
+               regulator-min-microamp  = <460000>;
+               regulator-max-microamp  = <1370000>;
+               regulator-boot-on;
+       };
+
+       vcc2: buck2 {
+               regulator-name = "VBUCK2";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <3000000>;
+               regulator-min-microamp  = <460000>;
+               regulator-max-microamp  = <1370000>;
+               regulator-boot-on;
+       };
+};
diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
new file mode 100644 (file)
index 0000000..96e83a5
--- /dev/null
@@ -0,0 +1,68 @@
+lp855x bindings
+
+Required properties:
+  - compatible: "ti,lp8550", "ti,lp8551", "ti,lp8552", "ti,lp8553",
+                "ti,lp8555", "ti,lp8556", "ti,lp8557"
+  - reg: I2C slave address (u8)
+  - dev-ctrl: Value of DEVICE CONTROL register (u8). It depends on the device.
+
+Optional properties:
+  - bl-name: Backlight device name (string)
+  - init-brt: Initial value of backlight brightness (u8)
+  - pwm-period: PWM period value. Set only PWM input mode used (u32)
+  - rom-addr: Register address of ROM area to be updated (u8)
+  - rom-val: Register value to be updated (u8)
+
+Example:
+
+       /* LP8555 */
+       backlight@2c {
+               compatible = "ti,lp8555";
+               reg = <0x2c>;
+
+               dev-ctrl = /bits/ 8 <0x00>;
+               pwm-period = <10000>;
+
+               /* 4V OV, 4 output LED0 string enabled */
+               rom_14h {
+                       rom-addr = /bits/ 8 <0x14>;
+                       rom-val = /bits/ 8 <0xcf>;
+               };
+
+               /* Heavy smoothing, 24ms ramp time step */
+               rom_15h {
+                       rom-addr = /bits/ 8 <0x15>;
+                       rom-val = /bits/ 8 <0xc7>;
+               };
+
+               /* 4 output LED1 string enabled */
+               rom_19h {
+                       rom-addr = /bits/ 8 <0x19>;
+                       rom-val = /bits/ 8 <0x0f>;
+               };
+       };
+
+       /* LP8556 */
+       backlight@2c {
+               compatible = "ti,lp8556";
+               reg = <0x2c>;
+
+               bl-name = "lcd-bl";
+               dev-ctrl = /bits/ 8 <0x85>;
+               init-brt = /bits/ 8 <0x10>;
+       };
+
+       /* LP8557 */
+       backlight@2c {
+               compatible = "ti,lp8557";
+               reg = <0x2c>;
+
+               dev-ctrl = /bits/ 8 <0x41>;
+               init-brt = /bits/ 8 <0x0a>;
+
+               /* 4V OV, 4 output LED string enabled */
+               rom_14h {
+                       rom-addr = /bits/ 8 <0x14>;
+                       rom-val = /bits/ 8 <0xcf>;
+               };
+       };
diff --git a/Documentation/leds/leds-lm3556.txt b/Documentation/leds/leds-lm3556.txt
new file mode 100644 (file)
index 0000000..62278e8
--- /dev/null
@@ -0,0 +1,85 @@
+Kernel driver for lm3556
+========================
+
+*Texas Instrument:
+ 1.5 A Synchronous Boost LED Flash Driver w/ High-Side Current Source
+* Datasheet: http://www.national.com/ds/LM/LM3556.pdf
+
+Authors:
+       Daniel Jeong
+       Contact:Daniel Jeong(daniel.jeong-at-ti.com, gshark.jeong-at-gmail.com)
+
+Description
+-----------
+There are 3 functions in LM3556, Flash, Torch and Indicator.
+
+FLASH MODE
+In Flash Mode, the LED current source(LED) provides 16 target current levels
+from 93.75 mA to 1500 mA.The Flash currents are adjusted via the CURRENT
+CONTROL REGISTER(0x09).Flash mode is activated by the ENABLE REGISTER(0x0A),
+or by pulling the STROBE pin HIGH.
+LM3556 Flash can be controlled through sys/class/leds/flash/brightness file
+* if STROBE pin is enabled, below example control brightness only, and
+ON / OFF will be controlled by STROBE pin.
+
+Flash Example:
+OFF     : #echo 0 > sys/class/leds/flash/brightness
+93.75 mA: #echo 1 > sys/class/leds/flash/brightness
+... .....
+1500  mA: #echo 16 > sys/class/leds/flash/brightness
+
+TORCH MODE
+In Torch Mode, the current source(LED) is programmed via the CURRENT CONTROL
+REGISTER(0x09).Torch Mode is activated by the ENABLE REGISTER(0x0A) or by the
+hardware TORCH input.
+LM3556 torch can be controlled through sys/class/leds/torch/brightness file.
+* if TORCH pin is enabled, below example control brightness only,
+and ON / OFF will be controlled by TORCH pin.
+
+Torch Example:
+OFF     : #echo 0 > sys/class/leds/torch/brightness
+46.88 mA: #echo 1 > sys/class/leds/torch/brightness
+... .....
+375 mA  : #echo 8 > sys/class/leds/torch/brightness
+
+INDICATOR MODE
+Indicator pattern can be set through sys/class/leds/indicator/pattern file,
+and 4 patterns are pre-defined in indicator_pattern array.
+According to N-lank, Pulse time and N Period values, different pattern wiill
+be generated.If you want new patterns for your own device, change
+indicator_pattern array with your own values and INDIC_PATTERN_SIZE.
+Please refer datasheet for more detail about N-Blank, Pulse time and N Period.
+
+Indicator pattern example:
+pattern 0: #echo 0 > sys/class/leds/indicator/pattern
+....
+pattern 3: #echo 3 > sys/class/leds/indicator/pattern
+
+Indicator brightness can be controlled through
+sys/class/leds/indicator/brightness file.
+
+Example:
+OFF      : #echo 0 > sys/class/leds/indicator/brightness
+5.86 mA  : #echo 1 > sys/class/leds/indicator/brightness
+........
+46.875mA : #echo 8 > sys/class/leds/indicator/brightness
+
+Notes
+-----
+Driver expects it is registered using the i2c_board_info mechanism.
+To register the chip at address 0x63 on specific adapter, set the platform data
+according to include/linux/platform_data/leds-lm3556.h, set the i2c board info
+
+Example:
+       static struct i2c_board_info board_i2c_ch4[] __initdata = {
+               {
+                        I2C_BOARD_INFO(LM3556_NAME, 0x63),
+                        .platform_data = &lm3556_pdata,
+                },
+       };
+
+and register it in the platform init function
+
+Example:
+       board_register_i2c_bus(4, 400,
+                               board_i2c_ch4, ARRAY_SIZE(board_i2c_ch4));
diff --git a/Documentation/leds/leds-lp5562.txt b/Documentation/leds/leds-lp5562.txt
new file mode 100644 (file)
index 0000000..5a823ff
--- /dev/null
@@ -0,0 +1,120 @@
+Kernel driver for LP5562
+========================
+
+* TI LP5562 LED Driver
+
+Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+
+Description
+
+  LP5562 can drive up to 4 channels. R/G/B and White.
+  LEDs can be controlled directly via the led class control interface.
+
+  All four channels can be also controlled using the engine micro programs.
+  LP5562 has the internal program memory for running various LED patterns.
+  For the details, please refer to 'firmware' section in leds-lp55xx.txt
+
+Device attribute: engine_mux
+
+  3 Engines are allocated in LP5562, but the number of channel is 4.
+  Therefore each channel should be mapped to the engine number.
+  Value : RGB or W
+
+  This attribute is used for programming LED data with the firmware interface.
+  Unlike the LP5521/LP5523/55231, LP5562 has unique feature for the engine mux,
+  so additional sysfs is required.
+
+  LED Map
+  Red   ... Engine 1 (fixed)
+  Green ... Engine 2 (fixed)
+  Blue  ... Engine 3 (fixed)
+  White ... Engine 1 or 2 or 3 (selective)
+
+How to load the program data using engine_mux
+
+  Before loading the LP5562 program data, engine_mux should be written between
+  the engine selection and loading the firmware.
+  Engine mux has two different mode, RGB and W.
+  RGB is used for loading RGB program data, W is used for W program data.
+
+  For example, run blinking green channel pattern,
+  echo 2 > /sys/bus/i2c/devices/xxxx/select_engine     # 2 is for green channel
+  echo "RGB" > /sys/bus/i2c/devices/xxxx/engine_mux    # engine mux for RGB
+  echo 1 > /sys/class/firmware/lp5562/loading
+  echo "4000600040FF6000" > /sys/class/firmware/lp5562/data
+  echo 0 > /sys/class/firmware/lp5562/loading
+  echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+  To run a blinking white pattern,
+  echo 1 or 2 or 3 > /sys/bus/i2c/devices/xxxx/select_engine
+  echo "W" > /sys/bus/i2c/devices/xxxx/engine_mux
+  echo 1 > /sys/class/firmware/lp5562/loading
+  echo "4000600040FF6000" > /sys/class/firmware/lp5562/data
+  echo 0 > /sys/class/firmware/lp5562/loading
+  echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+How to load the predefined patterns
+
+  Please refer to 'leds-lp55xx.txt"
+
+Setting Current of Each Channel
+
+  Like LP5521 and LP5523/55231, LP5562 provides LED current settings.
+  The 'led_current' and 'max_current' are used.
+
+(Example of Platform data)
+
+To configure the platform specific data, lp55xx_platform_data structure is used.
+
+static struct lp55xx_led_config lp5562_led_config[] = {
+       {
+               .name           = "R",
+               .chan_nr        = 0,
+               .led_current    = 20,
+               .max_current    = 40,
+       },
+       {
+               .name           = "G",
+               .chan_nr        = 1,
+               .led_current    = 20,
+               .max_current    = 40,
+       },
+       {
+               .name           = "B",
+               .chan_nr        = 2,
+               .led_current    = 20,
+               .max_current    = 40,
+       },
+       {
+               .name           = "W",
+               .chan_nr        = 3,
+               .led_current    = 20,
+               .max_current    = 40,
+       },
+};
+
+static int lp5562_setup(void)
+{
+       /* setup HW resources */
+}
+
+static void lp5562_release(void)
+{
+       /* Release HW resources */
+}
+
+static void lp5562_enable(bool state)
+{
+       /* Control of chip enable signal */
+}
+
+static struct lp55xx_platform_data lp5562_platform_data = {
+        .led_config     = lp5562_led_config,
+        .num_channels   = ARRAY_SIZE(lp5562_led_config),
+        .setup_resources   = lp5562_setup,
+        .release_resources = lp5562_release,
+        .enable            = lp5562_enable,
+};
+
+If the current is set to 0 in the platform data, that channel is
+disabled and it is not visible in the sysfs.
diff --git a/Documentation/leds/leds-lp55xx.txt b/Documentation/leds/leds-lp55xx.txt
new file mode 100644 (file)
index 0000000..bcea12a
--- /dev/null
@@ -0,0 +1,194 @@
+LP5521/LP5523/LP55231/LP5562/LP8501 Common Driver
+=================================================
+
+Authors: Milo(Woogyom) Kim <milo.kim@ti.com>
+
+Description
+-----------
+LP5521, LP5523/55231, LP5562 and LP8501 have common features as below.
+
+  Register access via the I2C
+  Device initialization/deinitialization
+  Create LED class devices for multiple output channels
+  Device attributes for user-space interface
+  Program memory for running LED patterns
+
+The LP55xx common driver provides these features using exported functions.
+  lp55xx_init_device() / lp55xx_deinit_device()
+  lp55xx_register_leds() / lp55xx_unregister_leds()
+  lp55xx_regsister_sysfs() / lp55xx_unregister_sysfs()
+
+( Driver Structure Data )
+
+In lp55xx common driver, two different data structure is used.
+
+o lp55xx_led
+  control multi output LED channels such as led current, channel index.
+o lp55xx_chip
+  general chip control such like the I2C and platform data.
+
+For example, LP5521 has maximum 3 LED channels.
+LP5523/55231 has 9 output channels.
+
+lp55xx_chip for LP5521 ... lp55xx_led #1
+                           lp55xx_led #2
+                           lp55xx_led #3
+
+lp55xx_chip for LP5523 ... lp55xx_led #1
+                           lp55xx_led #2
+                                 .
+                                 .
+                           lp55xx_led #9
+
+( Chip Dependent Code )
+
+To support device specific configurations, special structure
+'lpxx_device_config' is used.
+
+  Maximum number of channels
+  Reset command, chip enable command
+  Chip specific initialization
+  Brightness control register access
+  Setting LED output current
+  Program memory address access for running patterns
+  Additional device specific attributes
+
+( Firmware Interface )
+
+LP55xx family devices have the internal program memory for running
+various LED patterns.
+This pattern data is saved as a file in the user-land or
+hex byte string is written into the memory through the I2C.
+LP55xx common driver supports the firmware interface.
+
+LP55xx chips have three program engines.
+To load and run the pattern, the programming sequence is following.
+  (1) Select an engine number (1/2/3)
+  (2) Mode change to load
+  (3) Write pattern data into selected area
+  (4) Mode change to run
+
+The LP55xx common driver provides simple interfaces as below.
+select_engine : Select which engine is used for running program
+run_engine    : Start program which is loaded via the firmware interface
+firmware      : Load program data
+
+In case of LP5523, one more command is required, 'enginex_leds'.
+It is used for selecting LED output(s) at each engine number.
+In more details, please refer to 'leds-lp5523.txt'.
+
+For example, run blinking pattern in engine #1 of LP5521
+echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
+echo 1 > /sys/class/firmware/lp5521/loading
+echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
+echo 0 > /sys/class/firmware/lp5521/loading
+echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+For example, run blinking pattern in engine #3 of LP55231
+Two LEDs are configured as pattern output channels.
+echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
+echo 1 > /sys/class/firmware/lp55231/loading
+echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data
+echo 0 > /sys/class/firmware/lp55231/loading
+echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds
+echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+To start blinking patterns in engine #2 and #3 simultaneously,
+for idx in 2 3
+do
+  echo $idx > /sys/class/leds/red/device/select_engine
+  sleep 0.1
+  echo 1 > /sys/class/firmware/lp5521/loading
+  echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
+  echo 0 > /sys/class/firmware/lp5521/loading
+done
+echo 1 > /sys/class/leds/red/device/run_engine
+
+Here is another example for LP5523.
+Full LED strings are selected by 'engine2_leds'.
+echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
+echo 1 > /sys/class/firmware/lp5523/loading
+echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data
+echo 0 > /sys/class/firmware/lp5523/loading
+echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds
+echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+As soon as 'loading' is set to 0, registered callback is called.
+Inside the callback, the selected engine is loaded and memory is updated.
+To run programmed pattern, 'run_engine' attribute should be enabled.
+
+The pattern sqeuence of LP8501 is similar to LP5523.
+However pattern data is specific.
+Ex 1) Engine 1 is used
+echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
+
+Ex 2) Engine 2 and 3 are used at the same time
+echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
+sleep 1
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+sleep 1
+echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
+sleep 1
+echo 1 > /sys/class/firmware/lp8501/loading
+echo "9d0340ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
+echo 0 > /sys/class/firmware/lp8501/loading
+sleep 1
+echo 1 > /sys/class/leds/d1/device/run_engine
+
+( 'run_engine' and 'firmware_cb' )
+The sequence of running the program data is common.
+But each device has own specific register addresses for commands.
+To support this, 'run_engine' and 'firmware_cb' are configurable in each driver.
+run_engine  : Control the selected engine
+firmware_cb : The callback function after loading the firmware is done.
+              Chip specific commands for loading and updating program memory.
+
+( Predefined pattern data )
+
+Without the firmware interface, LP55xx driver provides another method for
+loading a LED pattern. That is 'predefined' pattern.
+A predefined pattern is defined in the platform data and load it(or them)
+via the sysfs if needed.
+To use the predefined pattern concept, 'patterns' and 'num_patterns' should be
+configured.
+
+  Example of predefined pattern data:
+
+  /* mode_1: blinking data */
+  static const u8 mode_1[] = {
+               0x40, 0x00, 0x60, 0x00, 0x40, 0xFF, 0x60, 0x00,
+               };
+
+  /* mode_2: always on */
+  static const u8 mode_2[] = { 0x40, 0xFF, };
+
+  struct lp55xx_predef_pattern board_led_patterns[] = {
+       {
+               .r = mode_1,
+               .size_r = ARRAY_SIZE(mode_1),
+       },
+       {
+               .b = mode_2,
+               .size_b = ARRAY_SIZE(mode_2),
+       },
+  }
+
+  struct lp55xx_platform_data lp5562_pdata = {
+  ...
+       .patterns      = board_led_patterns,
+       .num_patterns  = ARRAY_SIZE(board_led_patterns),
+  };
+
+Then, mode_1 and mode_2 can be run via through the sysfs.
+
+  echo 1 > /sys/bus/i2c/devices/xxxx/led_pattern    # red blinking LED pattern
+  echo 2 > /sys/bus/i2c/devices/xxxx/led_pattern    # blue LED always on
+
+To stop running pattern,
+  echo 0 > /sys/bus/i2c/devices/xxxx/led_pattern
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
new file mode 100644 (file)
index 0000000..903f24d
--- /dev/null
@@ -0,0 +1,837 @@
+#
+# GPIO infrastructure and drivers
+#
+
+config ARCH_HAVE_CUSTOM_GPIO_H
+       bool
+       help
+         Selecting this config option from the architecture Kconfig allows
+         the architecture to provide a custom asm/gpio.h implementation
+         overriding the default implementations.  New uses of this are
+         strongly discouraged.
+
+config ARCH_WANT_OPTIONAL_GPIOLIB
+       bool
+       help
+         Select this config option from the architecture Kconfig, if
+         it is possible to use gpiolib on the architecture, but let the
+         user decide whether to actually build it or not.
+         Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does
+         not depend on GPIOs being available, but rather let the user
+         decide whether he needs it or not.
+
+config ARCH_REQUIRE_GPIOLIB
+       bool
+       select GPIOLIB
+       help
+         Platforms select gpiolib if they use this infrastructure
+         for all their GPIOs, usually starting with ones integrated
+         into SOC processors.
+         Selecting this from the architecture code will cause the gpiolib
+         code to always get built in.
+
+
+menuconfig GPIOLIB
+       bool "GPIO Support"
+       depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB
+       help
+         This enables GPIO support through the generic GPIO library.
+         You only need to enable this, if you also want to enable
+         one or more of the GPIO drivers below.
+
+         If unsure, say N.
+
+if GPIOLIB
+
+config GPIO_DEVRES
+       def_bool y
+       depends on HAS_IOMEM
+
+config OF_GPIO
+       def_bool y
+       depends on OF
+
+config GPIO_ACPI
+       def_bool y
+       depends on ACPI
+
+config DEBUG_GPIO
+       bool "Debug GPIO calls"
+       depends on DEBUG_KERNEL
+       help
+         Say Y here to add some extra checks and diagnostics to GPIO calls.
+         These checks help ensure that GPIOs have been properly initialized
+         before they are used, and that sleeping calls are not made from
+         non-sleeping contexts.  They can make bitbanged serial protocols
+         slower.  The diagnostics help catch the type of setup errors
+         that are most common when setting up new platforms or boards.
+
+config GPIO_SYSFS
+       bool "/sys/class/gpio/... (sysfs interface)"
+       depends on SYSFS
+       help
+         Say Y here to add a sysfs interface for GPIOs.
+
+         This is mostly useful to work around omissions in a system's
+         kernel support.  Those are common in custom and semicustom
+         hardware assembled using standard kernels with a minimum of
+         custom patches.  In those cases, userspace code may import
+         a given GPIO from the kernel, if no kernel driver requested it.
+
+         Kernel drivers may also request that a particular GPIO be
+         exported to userspace; this can be useful when debugging.
+
+config GPIO_GENERIC
+       tristate
+
+# put drivers in the right section, in alphabetical order
+
+config GPIO_DA9052
+       tristate "Dialog DA9052 GPIO"
+       depends on PMIC_DA9052
+       help
+         Say yes here to enable the GPIO driver for the DA9052 chip.
+
+config GPIO_DA9055
+       tristate "Dialog Semiconductor DA9055 GPIO"
+       depends on MFD_DA9055
+       help
+         Say yes here to enable the GPIO driver for the DA9055 chip.
+
+         The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
+         be controller by this driver.
+
+         If driver is built as a module it will be called gpio-da9055.
+
+config GPIO_MAX730X
+       tristate
+
+comment "Memory mapped GPIO drivers:"
+
+config GPIO_CLPS711X
+       tristate "CLPS711X GPIO support"
+       depends on ARCH_CLPS711X || COMPILE_TEST
+       select GPIO_GENERIC
+       help
+         Say yes here to support GPIO on CLPS711X SoCs.
+
+config GPIO_DAVINCI
+       bool "TI Davinci/Keystone GPIO support"
+       default y if ARCH_DAVINCI
+       depends on ARM && (ARCH_DAVINCI || ARCH_KEYSTONE)
+       help
+         Say yes here to enable GPIO support for TI Davinci/Keystone SoCs.
+
+config GPIO_GENERIC_PLATFORM
+       tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
+       select GPIO_GENERIC
+       help
+         Say yes here to support basic platform_device memory-mapped GPIO controllers.
+
+config GPIO_IT8761E
+       tristate "IT8761E GPIO support"
+       depends on X86  # unconditional access to IO space.
+       help
+         Say yes here to support GPIO functionality of IT8761E super I/O chip.
+
+config GPIO_EM
+       tristate "Emma Mobile GPIO"
+       depends on ARM && OF_GPIO
+       help
+         Say yes here to support GPIO on Renesas Emma Mobile SoCs.
+
+config GPIO_EP93XX
+       def_bool y
+       depends on ARCH_EP93XX
+       select GPIO_GENERIC
+
+config GPIO_MM_LANTIQ
+       bool "Lantiq Memory mapped GPIOs"
+       depends on LANTIQ && SOC_XWAY
+       help
+         This enables support for memory mapped GPIOs on the External Bus Unit
+         (EBU) found on Lantiq SoCs. The gpios are output only as they are
+         created by attaching a 16bit latch to the bus.
+
+config GPIO_F7188X
+       tristate "F71882FG and F71889F GPIO support"
+       depends on X86
+       help
+         This option enables support for GPIOs found on Fintek Super-I/O
+         chips F71882FG and F71889F.
+
+         To compile this driver as a module, choose M here: the module will
+         be called f7188x-gpio.
+
+config GPIO_MOXART
+       bool "MOXART GPIO support"
+       depends on ARCH_MOXART
+       help
+         Select this option to enable GPIO driver for
+         MOXA ART SoC devices.
+
+config GPIO_MPC5200
+       def_bool y
+       depends on PPC_MPC52xx
+
+config GPIO_MPC8XXX
+       bool "MPC512x/MPC8xxx GPIO support"
+       depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
+                  FSL_SOC_BOOKE || PPC_86xx
+       help
+         Say Y here if you're going to use hardware that connects to the
+         MPC512x/831x/834x/837x/8572/8610 GPIOs.
+
+config GPIO_MSM_V1
+       tristate "Qualcomm MSM GPIO v1"
+       depends on GPIOLIB && ARCH_MSM && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50)
+       help
+         Say yes here to support the GPIO interface on ARM v6 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
+config GPIO_MSM_V2
+       tristate "Qualcomm MSM GPIO v2"
+       depends on GPIOLIB && OF && ARCH_MSM
+       help
+         Say yes here to support the GPIO interface on ARM v7 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
+config GPIO_MVEBU
+       def_bool y
+       depends on PLAT_ORION
+       depends on OF
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+
+config GPIO_MXC
+       def_bool y
+       depends on ARCH_MXC
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+
+config GPIO_MXS
+       def_bool y
+       depends on ARCH_MXS
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+
+config GPIO_OCTEON
+       tristate "Cavium OCTEON GPIO"
+       depends on GPIOLIB && CAVIUM_OCTEON_SOC
+       default y
+       help
+         Say yes here to support the on-chip GPIO lines on the OCTEON
+         family of SOCs.
+
+config GPIO_PL061
+       bool "PrimeCell PL061 GPIO support"
+       depends on ARM_AMBA
+       select GENERIC_IRQ_CHIP
+       help
+         Say yes here to support the PrimeCell PL061 GPIO device
+
+config GPIO_PXA
+       bool "PXA GPIO support"
+       depends on ARCH_PXA || ARCH_MMP
+       help
+         Say yes here to support the PXA GPIO device
+
+config GPIO_RCAR
+       tristate "Renesas R-Car GPIO"
+       depends on ARM
+       help
+         Say yes here to support GPIO on Renesas R-Car SoCs.
+
+config GPIO_SAMSUNG
+       bool
+       depends on PLAT_SAMSUNG
+       help
+         Legacy GPIO support. Use only for platforms without support for
+         pinctrl.
+
+config GPIO_SCH311X
+       tristate "SMSC SCH311x SuperI/O GPIO"
+       help
+         Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and
+         SCH3116 "Super I/O" chipsets.
+
+         To compile this driver as a module, choose M here: the module will
+         be called gpio-sch311x.
+
+config GPIO_SPEAR_SPICS
+       bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+       depends on PLAT_SPEAR
+       select GENERIC_IRQ_CHIP
+       help
+         Say yes here to support ST SPEAr SPI Chip Select as GPIO device
+
+config GPIO_STA2X11
+       bool "STA2x11/ConneXt GPIO support"
+       depends on MFD_STA2X11
+       select GENERIC_IRQ_CHIP
+       help
+         Say yes here to support the STA2x11/ConneXt GPIO device.
+         The GPIO module has 128 GPIO pins with alternate functions.
+
+config GPIO_TS5500
+       tristate "TS-5500 DIO blocks and compatibles"
+       help
+         This driver supports Digital I/O exposed by pin blocks found on some
+         Technologic Systems platforms. It includes, but is not limited to, 3
+         blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
+         LCD port.
+
+config GPIO_TZ1090
+       bool "Toumaz Xenif TZ1090 GPIO support"
+       depends on SOC_TZ1090
+       select GENERIC_IRQ_CHIP
+       default y
+       help
+         Say yes here to support Toumaz Xenif TZ1090 GPIOs.
+
+config GPIO_TZ1090_PDC
+       bool "Toumaz Xenif TZ1090 PDC GPIO support"
+       depends on SOC_TZ1090
+       default y
+       help
+         Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
+
+config GPIO_XILINX
+       bool "Xilinx GPIO support"
+       depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
+       help
+         Say yes here to support the Xilinx FPGA GPIO device
+
+config GPIO_XTENSA
+       bool "Xtensa GPIO32 support"
+       depends on XTENSA
+       depends on HAVE_XTENSA_GPIO32
+       depends on !SMP
+       help
+         Say yes here to support the Xtensa internal GPIO32 IMPWIRE (input)
+         and EXPSTATE (output) ports
+
+config GPIO_VR41XX
+       tristate "NEC VR4100 series General-purpose I/O Uint support"
+       depends on CPU_VR41XX
+       help
+         Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+
+config GPIO_SCH
+       tristate "Intel SCH/TunnelCreek/Centerton GPIO"
+       depends on PCI && X86
+       select MFD_CORE
+       select LPC_SCH
+       help
+         Say yes here to support GPIO interface on Intel Poulsbo SCH,
+         Intel Tunnel Creek processor or Intel Centerton processor.
+         The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
+         powered by the core power rail and are turned off during sleep
+         modes (S3 and higher). The remaining four GPIOs are powered by
+         the Intel SCH suspend power supply. These GPIOs remain
+         active during S3. The suspend powered GPIOs can be used to wake the
+         system from the Suspend-to-RAM state.
+         The Intel Tunnel Creek processor has 5 GPIOs powered by the
+         core power rail and 9 from suspend power supply.
+         The Intel Centerton processor has a total of 30 GPIO pins.
+         Twenty-one are powered by the core power rail and 9 from the
+         suspend power supply.
+
+config GPIO_ICH
+       tristate "Intel ICH GPIO"
+       depends on PCI && X86
+       select MFD_CORE
+       select LPC_ICH
+       help
+         Say yes here to support the GPIO functionality of a number of Intel
+         ICH-based chipsets.  Currently supported devices: ICH6, ICH7, ICH8
+         ICH9, ICH10, Series 5/3400 (eg Ibex Peak), Series 6/C200 (eg
+         Cougar Point), NM10 (Tiger Point), and 3100 (Whitmore Lake).
+
+         If unsure, say N.
+
+config GPIO_IOP
+       tristate "Intel IOP GPIO"
+       depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
+       help
+         Say yes here to support the GPIO functionality of a number of Intel
+         IOP32X or IOP33X.
+
+         If unsure, say N.
+
+config GPIO_VX855
+       tristate "VIA VX855/VX875 GPIO"
+       depends on PCI
+       select MFD_CORE
+       select MFD_VX855
+       help
+         Support access to the VX855/VX875 GPIO lines through the gpio library.
+
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
+config GPIO_GE_FPGA
+       bool "GE FPGA based GPIO"
+       depends on GE_FPGA
+       help
+         Support for common GPIO functionality provided on some GE Single Board
+         Computers.
+
+         This driver provides basic support (configure as input or output, read
+         and write pin state) for GPIO implemented in a number of GE single
+         board computers.
+
+config GPIO_LYNXPOINT
+       tristate "Intel Lynxpoint GPIO support"
+       depends on ACPI && X86
+       select IRQ_DOMAIN
+       help
+         driver for GPIO functionality on Intel Lynxpoint PCH chipset
+         Requires ACPI device enumeration code to set up a platform device.
+
+config GPIO_GRGPIO
+       tristate "Aeroflex Gaisler GRGPIO support"
+       depends on OF
+       select GPIO_GENERIC
+       select IRQ_DOMAIN
+       help
+         Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB
+         VHDL IP core library.
+
+config GPIO_TB10X
+       bool
+       select GENERIC_IRQ_CHIP
+       select OF_GPIO
+
+comment "I2C GPIO expanders:"
+
+config GPIO_ARIZONA
+       tristate "Wolfson Microelectronics Arizona class devices"
+       depends on MFD_ARIZONA
+       help
+         Support for GPIOs on Wolfson Arizona class devices.
+
+config GPIO_LP3943
+       tristate "TI/National Semiconductor LP3943 GPIO expander"
+       depends on MFD_LP3943
+       help
+         GPIO driver for LP3943 MFD.
+         LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
+         Open drain outputs are required for this usage.
+
+config GPIO_MAX7300
+       tristate "Maxim MAX7300 GPIO expander"
+       depends on I2C
+       select GPIO_MAX730X
+       help
+         GPIO driver for Maxim MAX7300 I2C-based GPIO expander.
+
+config GPIO_MAX732X
+       tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
+       depends on I2C
+       help
+         Say yes here to support the MAX7319, MAX7320-7327 series of I2C
+         Port Expanders. Each IO port on these chips has a fixed role of
+         Input (designated by 'I'), Push-Pull Output ('O'), or Open-Drain
+         Input and Output (designed by 'P'). The combinations are listed
+         below:
+
+         8 bits:       max7319 (8I), max7320 (8O), max7321 (8P),
+                       max7322 (4I4O), max7323 (4P4O)
+
+         16 bits:      max7324 (8I8O), max7325 (8P8O),
+                       max7326 (4I12O), max7327 (4P12O)
+
+         Board setup code must specify the model to use, and the start
+         number for these GPIOs.
+
+config GPIO_MAX732X_IRQ
+       bool "Interrupt controller support for MAX732x"
+       depends on GPIO_MAX732X=y
+       help
+         Say yes here to enable the max732x to be used as an interrupt
+         controller. It requires the driver to be built in the kernel.
+
+config GPIO_MC9S08DZ60
+       bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
+       depends on I2C=y && MACH_MX35_3DS
+       help
+         Select this to enable the MC9S08DZ60 GPIO driver
+
+config GPIO_PCA953X
+       tristate "PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports"
+       depends on I2C
+       help
+         Say yes here to provide access to several register-oriented
+         SMBus I/O expanders, made mostly by NXP or TI.  Compatible
+         models include:
+
+         4 bits:       pca9536, pca9537
+
+         8 bits:       max7310, max7315, pca6107, pca9534, pca9538, pca9554,
+                       pca9556, pca9557, pca9574, tca6408
+
+         16 bits:      max7312, max7313, pca9535, pca9539, pca9555, pca9575,
+                       tca6416
+
+config GPIO_PCA953X_IRQ
+       bool "Interrupt controller support for PCA953x"
+       depends on GPIO_PCA953X=y
+       help
+         Say yes here to enable the pca953x to be used as an interrupt
+         controller. It requires the driver to be built in the kernel.
+
+config GPIO_PCF857X
+       tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
+       depends on I2C
+       select IRQ_DOMAIN
+       help
+         Say yes here to provide access to most "quasi-bidirectional" I2C
+         GPIO expanders used for additional digital outputs or inputs.
+         Most of these parts are from NXP, though TI is a second source for
+         some of them.  Compatible models include:
+
+         8 bits:   pcf8574, pcf8574a, pca8574, pca8574a,
+                   pca9670, pca9672, pca9674, pca9674a,
+                   max7328, max7329
+
+         16 bits:  pcf8575, pcf8575c, pca8575,
+                   pca9671, pca9673, pca9675
+
+         Your board setup code will need to declare the expanders in
+         use, and assign numbers to the GPIOs they expose.  Those GPIOs
+         can then be used from drivers and other kernel code, just like
+         other GPIOs, but only accessible from task contexts.
+
+         This driver provides an in-kernel interface to those GPIOs using
+         platform-neutral GPIO calls.
+
+config GPIO_RC5T583
+       bool "RICOH RC5T583 GPIO"
+       depends on MFD_RC5T583
+       help
+         Select this option to enable GPIO driver for the Ricoh RC5T583
+         chip family.
+         This driver provides the support for driving/reading the gpio pins
+         of RC5T583 device through standard gpio library.
+
+config GPIO_SX150X
+       bool "Semtech SX150x I2C GPIO expander"
+       depends on I2C=y
+       default n
+       help
+         Say yes here to provide support for Semtech SX150-series I2C
+         GPIO expanders. Compatible models include:
+
+         8 bits:  sx1508q
+         16 bits: sx1509q
+
+config GPIO_STMPE
+       bool "STMPE GPIOs"
+       depends on MFD_STMPE
+       help
+         This enables support for the GPIOs found on the STMPE I/O
+         Expanders.
+
+config GPIO_STP_XWAY
+       bool "XWAY STP GPIOs"
+       depends on SOC_XWAY
+       help
+         This enables support for the Serial To Parallel (STP) unit found on
+         XWAY SoC. The STP allows the SoC to drive a shift registers cascade,
+         that can be up to 24 bit. This peripheral is aimed at driving leds.
+         Some of the gpios/leds can be auto updated by the soc with dsl and
+         phy status.
+
+config GPIO_TC3589X
+       bool "TC3589X GPIOs"
+       depends on MFD_TC3589X
+       help
+         This enables support for the GPIOs found on the TC3589X
+         I/O Expander.
+
+config GPIO_TPS65912
+       tristate "TI TPS65912 GPIO"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+         This driver supports TPS65912 gpio chip
+
+config GPIO_TWL4030
+       tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
+       depends on TWL4030_CORE
+       help
+         Say yes here to access the GPIO signals of various multi-function
+         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
+       tristate "WM831x GPIOs"
+       depends on MFD_WM831X
+       help
+         Say yes here to access the GPIO signals of WM831x power management
+         chips from Wolfson Microelectronics.
+
+config GPIO_WM8350
+       tristate "WM8350 GPIOs"
+       depends on MFD_WM8350
+       help
+         Say yes here to access the GPIO signals of WM8350 power management
+         chips from Wolfson Microelectronics.
+
+config GPIO_WM8994
+       tristate "WM8994 GPIOs"
+       depends on MFD_WM8994
+       help
+         Say yes here to access the GPIO signals of WM8994 audio hub
+         CODECs from Wolfson Microelectronics.
+
+config GPIO_ADP5520
+       tristate "GPIO Support for ADP5520 PMIC"
+       depends on PMIC_ADP5520
+       help
+         This option enables support for on-chip GPIO found
+         on Analog Devices ADP5520 PMICs.
+
+config GPIO_ADP5588
+       tristate "ADP5588 I2C GPIO expander"
+       depends on I2C
+       help
+         This option enables support for 18 GPIOs found
+         on Analog Devices ADP5588 GPIO Expanders.
+
+config GPIO_ADP5588_IRQ
+       bool "Interrupt controller support for ADP5588"
+       depends on GPIO_ADP5588=y
+       help
+         Say yes here to enable the adp5588 to be used as an interrupt
+         controller. It requires the driver to be built in the kernel.
+
+config GPIO_ADNP
+       tristate "Avionic Design N-bit GPIO expander"
+       depends on I2C && OF_GPIO
+       help
+         This option enables support for N GPIOs found on Avionic Design
+         I2C GPIO expanders. The register space will be extended by powers
+         of two, so the controller will need to accommodate for that. For
+         example: if a controller provides 48 pins, 6 registers will be
+         enough to represent all pins, but the driver will assume a
+         register layout for 64 pins (8 registers).
+
+comment "PCI GPIO expanders:"
+
+config GPIO_CS5535
+       tristate "AMD CS5535/CS5536 GPIO support"
+       depends on PCI && X86 && MFD_CS5535
+       help
+         The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
+         can be used for quite a number of things.  The CS5535/6 is found on
+         AMD Geode and Lemote Yeeloong devices.
+
+         If unsure, say N.
+
+config GPIO_BT8XX
+       tristate "BT8XX GPIO abuser"
+       depends on PCI && VIDEO_BT848=n
+       help
+         The BT8xx frame grabber chip has 24 GPIO pins than can be abused
+         as a cheap PCI GPIO card.
+
+         This chip can be found on Miro, Hauppauge and STB TV-cards.
+
+         The card needs to be physically altered for using it as a
+         GPIO card. For more information on how to build a GPIO card
+         from a BT8xx TV card, see the documentation file at
+         Documentation/bt8xxgpio.txt
+
+         If unsure, say N.
+
+config GPIO_AMD8111
+       tristate "AMD 8111 GPIO driver"
+       depends on PCI
+       help
+         The AMD 8111 south bridge contains 32 GPIO pins which can be used.
+
+         Note, that usually system firmware/ACPI handles GPIO pins on their
+         own and users might easily break their systems with uncarefull usage
+         of this driver!
+
+         If unsure, say N
+
+config GPIO_INTEL_MID
+       bool "Intel Mid GPIO support"
+       depends on PCI && X86
+       select IRQ_DOMAIN
+       help
+         Say Y here to support Intel Mid GPIO.
+
+config GPIO_PCH
+       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
+       depends on PCI && X86
+       select GENERIC_IRQ_CHIP
+       help
+         This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
+         which is an IOH(Input/Output Hub) for x86 embedded processor.
+         This driver can access PCH GPIO device.
+
+         This driver also can be used for LAPIS Semiconductor IOH(Input/
+         Output Hub), ML7223 and ML7831.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7831 IOH is for general purpose use.
+         ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7223/ML7831 is completely compatible for Intel EG20T PCH.
+
+config GPIO_ML_IOH
+       tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
+       depends on PCI
+       select GENERIC_IRQ_CHIP
+       help
+         ML7213 is companion chip for Intel Atom E6xx series.
+         This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output
+         Hub) which is for IVI(In-Vehicle Infotainment) use.
+         This driver can access the IOH's GPIO device.
+
+config GPIO_SODAVILLE
+       bool "Intel Sodaville GPIO support"
+       depends on X86 && PCI && OF
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+       help
+         Say Y here to support Intel Sodaville GPIO.
+
+config GPIO_TIMBERDALE
+       bool "Support for timberdale GPIO IP"
+       depends on MFD_TIMBERDALE && HAS_IOMEM
+       ---help---
+       Add support for the GPIO IP in the timberdale FPGA.
+
+config GPIO_RDC321X
+       tristate "RDC R-321x GPIO support"
+       depends on PCI
+       select MFD_CORE
+       select MFD_RDC321X
+       help
+         Support for the RDC R321x SoC GPIOs over southbridge
+         PCI configuration space.
+
+comment "SPI GPIO expanders:"
+
+config GPIO_MAX7301
+       tristate "Maxim MAX7301 GPIO expander"
+       depends on SPI_MASTER
+       select GPIO_MAX730X
+       help
+         GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
+
+config GPIO_MCP23S08
+       tristate "Microchip MCP23xxx I/O expander"
+       depends on OF_GPIO
+       depends on (SPI_MASTER && !I2C) || I2C
+       help
+         SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
+         I/O expanders.
+         This provides a GPIO interface supporting inputs and outputs.
+         The I2C versions of the chips can be used as interrupt-controller.
+
+config GPIO_MC33880
+       tristate "Freescale MC33880 high-side/low-side switch"
+       depends on SPI_MASTER
+       help
+         SPI driver for Freescale MC33880 high-side/low-side switch.
+         This provides GPIO interface supporting inputs and outputs.
+
+config GPIO_74X164
+       tristate "74x164 serial-in/parallel-out 8-bits shift register"
+       depends on SPI_MASTER && OF
+       help
+         Driver for 74x164 compatible serial-in/parallel-out 8-outputs
+         shift registers. This driver can be used to provide access
+         to more gpio outputs.
+
+comment "AC97 GPIO expanders:"
+
+config GPIO_UCB1400
+       tristate "Philips UCB1400 GPIO"
+       depends on UCB1400_CORE
+       help
+         This enables support for the Philips UCB1400 GPIO pins.
+         The UCB1400 is an AC97 audio codec.
+
+comment "LPC GPIO expanders:"
+
+config GPIO_KEMPLD
+       tristate "Kontron ETX / COMexpress GPIO"
+       depends on MFD_KEMPLD
+       help
+         This enables support for the PLD GPIO interface on some Kontron ETX
+         and COMexpress (ETXexpress) modules.
+
+         This driver can also be built as a module. If so, the module will be
+         called gpio-kempld.
+
+comment "MODULbus GPIO expanders:"
+
+config GPIO_JANZ_TTL
+       tristate "Janz VMOD-TTL Digital IO Module"
+       depends on MFD_JANZ_CMODIO
+       help
+         This enables support for the Janz VMOD-TTL Digital IO module.
+         This driver provides support for driving the pins in output
+         mode only. Input mode is not supported.
+
+config GPIO_PALMAS
+       bool "TI PALMAS series PMICs GPIO"
+       depends on MFD_PALMAS
+       help
+         Select this option to enable GPIO driver for the TI PALMAS
+         series chip family.
+
+config GPIO_TPS6586X
+       bool "TPS6586X GPIO"
+       depends on MFD_TPS6586X
+       help
+         Select this option to enable GPIO driver for the TPS6586X
+         chip family.
+
+config GPIO_TPS65910
+       bool "TPS65910 GPIO"
+       depends on MFD_TPS65910
+       help
+         Select this option to enable GPIO driver for the TPS65910
+         chip family.
+
+config GPIO_MSIC
+       bool "Intel MSIC mixed signal gpio support"
+       depends on MFD_INTEL_MSIC
+       help
+         Enable support for GPIO on intel MSIC controllers found in
+         intel MID devices
+
+config GPIO_BCM_KONA
+       bool "Broadcom Kona GPIO"
+       depends on OF_GPIO
+       help
+         Turn on GPIO support for Broadcom "Kona" chips.
+
+comment "USB GPIO expanders:"
+
+config GPIO_VIPERBOARD
+       tristate "Viperboard GPIO a & b support"
+       depends on MFD_VIPERBOARD && USB
+       help
+         Say yes here to access the GPIO signals of Nano River
+         Technologies Viperboard. There are two GPIO chips on the
+         board: gpioa and gpiob.
+          See viperboard API specification and Nano
+          River Tech's viperboard.h for detailed meaning
+          of the module parameters.
+
+endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
new file mode 100644 (file)
index 0000000..5d50179
--- /dev/null
@@ -0,0 +1,101 @@
+# generic gpio support: platform drivers, dedicated expander chips, etc
+
+ccflags-$(CONFIG_DEBUG_GPIO)   += -DDEBUG
+
+obj-$(CONFIG_GPIO_DEVRES)      += devres.o
+obj-$(CONFIG_GPIOLIB)          += gpiolib.o
+obj-$(CONFIG_OF_GPIO)          += gpiolib-of.o
+obj-$(CONFIG_GPIO_ACPI)                += gpiolib-acpi.o
+
+# Device drivers. Generally keep list sorted alphabetically
+obj-$(CONFIG_GPIO_GENERIC)     += gpio-generic.o
+
+obj-$(CONFIG_GPIO_74X164)      += gpio-74x164.o
+obj-$(CONFIG_GPIO_ADNP)                += gpio-adnp.o
+obj-$(CONFIG_GPIO_ADP5520)     += gpio-adp5520.o
+obj-$(CONFIG_GPIO_ADP5588)     += gpio-adp5588.o
+obj-$(CONFIG_GPIO_AMD8111)     += gpio-amd8111.o
+obj-$(CONFIG_GPIO_ARIZONA)     += gpio-arizona.o
+obj-$(CONFIG_GPIO_BCM_KONA)    += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BT8XX)       += gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CLPS711X)    += gpio-clps711x.o
+obj-$(CONFIG_GPIO_CS5535)      += gpio-cs5535.o
+obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
+obj-$(CONFIG_GPIO_DA9055)      += gpio-da9055.o
+obj-$(CONFIG_GPIO_DAVINCI)     += gpio-davinci.o
+obj-$(CONFIG_GPIO_EM)          += gpio-em.o
+obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
+obj-$(CONFIG_GPIO_F7188X)      += gpio-f7188x.o
+obj-$(CONFIG_GPIO_GE_FPGA)     += gpio-ge.o
+obj-$(CONFIG_GPIO_GRGPIO)      += gpio-grgpio.o
+obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
+obj-$(CONFIG_GPIO_IOP)         += gpio-iop.o
+obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
+obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_KEMPLD)      += gpio-kempld.o
+obj-$(CONFIG_ARCH_KS8695)      += gpio-ks8695.o
+obj-$(CONFIG_GPIO_INTEL_MID)   += gpio-intel-mid.o
+obj-$(CONFIG_GPIO_LP3943)      += gpio-lp3943.o
+obj-$(CONFIG_ARCH_LPC32XX)     += gpio-lpc32xx.o
+obj-$(CONFIG_GPIO_LYNXPOINT)   += gpio-lynxpoint.o
+obj-$(CONFIG_GPIO_MAX730X)     += gpio-max730x.o
+obj-$(CONFIG_GPIO_MAX7300)     += gpio-max7300.o
+obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
+obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
+obj-$(CONFIG_GPIO_MC33880)     += gpio-mc33880.o
+obj-$(CONFIG_GPIO_MC9S08DZ60)  += gpio-mc9s08dz60.o
+obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
+obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
+obj-$(CONFIG_GPIO_MM_LANTIQ)   += gpio-mm-lantiq.o
+obj-$(CONFIG_GPIO_MOXART)      += gpio-moxart.o
+obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
+obj-$(CONFIG_GPIO_MSIC)                += gpio-msic.o
+obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
+obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
+obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
+obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
+obj-$(CONFIG_GPIO_OCTEON)      += gpio-octeon.o
+obj-$(CONFIG_ARCH_OMAP)                += gpio-omap.o
+obj-$(CONFIG_GPIO_PCA953X)     += gpio-pca953x.o
+obj-$(CONFIG_GPIO_PCF857X)     += gpio-pcf857x.o
+obj-$(CONFIG_GPIO_PCH)         += gpio-pch.o
+obj-$(CONFIG_GPIO_PL061)       += gpio-pl061.o
+obj-$(CONFIG_GPIO_PXA)         += gpio-pxa.o
+obj-$(CONFIG_GPIO_RC5T583)     += gpio-rc5t583.o
+obj-$(CONFIG_GPIO_RDC321X)     += gpio-rdc321x.o
+obj-$(CONFIG_GPIO_RCAR)                += gpio-rcar.o
+obj-$(CONFIG_GPIO_SAMSUNG)     += gpio-samsung.o
+obj-$(CONFIG_ARCH_SA1100)      += gpio-sa1100.o
+obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
+obj-$(CONFIG_GPIO_SCH311X)     += gpio-sch311x.o
+obj-$(CONFIG_GPIO_SODAVILLE)   += gpio-sodaville.o
+obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
+obj-$(CONFIG_GPIO_STA2X11)     += gpio-sta2x11.o
+obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
+obj-$(CONFIG_GPIO_STP_XWAY)    += gpio-stp-xway.o
+obj-$(CONFIG_GPIO_SX150X)      += gpio-sx150x.o
+obj-$(CONFIG_GPIO_TB10X)       += gpio-tb10x.o
+obj-$(CONFIG_GPIO_TC3589X)     += gpio-tc3589x.o
+obj-$(CONFIG_ARCH_TEGRA)       += gpio-tegra.o
+obj-$(CONFIG_GPIO_TIMBERDALE)  += gpio-timberdale.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
+obj-$(CONFIG_GPIO_PALMAS)      += gpio-palmas.o
+obj-$(CONFIG_GPIO_TPS6586X)    += gpio-tps6586x.o
+obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
+obj-$(CONFIG_GPIO_TS5500)      += gpio-ts5500.o
+obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
+obj-$(CONFIG_GPIO_TWL6040)     += gpio-twl6040.o
+obj-$(CONFIG_GPIO_TZ1090)      += gpio-tz1090.o
+obj-$(CONFIG_GPIO_TZ1090_PDC)  += gpio-tz1090-pdc.o
+obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VIPERBOARD)  += gpio-viperboard.o
+obj-$(CONFIG_GPIO_VR41XX)      += gpio-vr41xx.o
+obj-$(CONFIG_GPIO_VX855)       += gpio-vx855.o
+obj-$(CONFIG_GPIO_WM831X)      += gpio-wm831x.o
+obj-$(CONFIG_GPIO_WM8350)      += gpio-wm8350.o
+obj-$(CONFIG_GPIO_WM8994)      += gpio-wm8994.o
+obj-$(CONFIG_GPIO_XILINX)      += gpio-xilinx.o
+obj-$(CONFIG_GPIO_XTENSA)      += gpio-xtensa.o
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
new file mode 100644 (file)
index 0000000..a0341c9
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * TI/National Semiconductor LP3943 GPIO driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo 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 as published by
+ * the Free Software Foundation; version 2.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum lp3943_gpios {
+       LP3943_GPIO1,
+       LP3943_GPIO2,
+       LP3943_GPIO3,
+       LP3943_GPIO4,
+       LP3943_GPIO5,
+       LP3943_GPIO6,
+       LP3943_GPIO7,
+       LP3943_GPIO8,
+       LP3943_GPIO9,
+       LP3943_GPIO10,
+       LP3943_GPIO11,
+       LP3943_GPIO12,
+       LP3943_GPIO13,
+       LP3943_GPIO14,
+       LP3943_GPIO15,
+       LP3943_GPIO16,
+       LP3943_MAX_GPIO,
+};
+
+struct lp3943_gpio {
+       struct gpio_chip chip;
+       struct lp3943 *lp3943;
+       u16 input_mask;         /* 1 = GPIO is input direction, 0 = output */
+};
+
+static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip)
+{
+       return container_of(_chip, struct lp3943_gpio, chip);
+}
+
+static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+       /* Return an error if the pin is already assigned */
+       if (test_and_set_bit(offset, &lp3943->pin_used))
+               return -EBUSY;
+
+       return 0;
+}
+
+static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+       clear_bit(offset, &lp3943->pin_used);
+}
+
+static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
+                               u8 val)
+{
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+       const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+
+       return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
+                                 val << mux[offset].shift);
+}
+
+static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       lp3943_gpio->input_mask |= BIT(offset);
+
+       return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
+}
+
+static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
+                                    struct gpio_chip *chip, unsigned offset)
+{
+       u8 addr, read;
+       int err;
+
+       switch (offset) {
+       case LP3943_GPIO1 ... LP3943_GPIO8:
+               addr = LP3943_REG_GPIO_A;
+               break;
+       case LP3943_GPIO9 ... LP3943_GPIO16:
+               addr = LP3943_REG_GPIO_B;
+               offset = offset - 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
+       if (err)
+               return err;
+
+       return !!(read & BIT(offset));
+}
+
+static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
+                                     struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+       const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+       u8 read;
+       int err;
+
+       err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
+       if (err)
+               return err;
+
+       read = (read & mux[offset].mask) >> mux[offset].shift;
+
+       if (read == LP3943_GPIO_OUT_HIGH)
+               return 1;
+       else if (read == LP3943_GPIO_OUT_LOW)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       /*
+        * Limitation:
+        *   LP3943 doesn't have the GPIO direction register. It provides
+        *   only input and output status registers.
+        *   So, direction info is required to handle the 'get' operation.
+        *   This variable is updated whenever the direction is changed and
+        *   it is used here.
+        */
+
+       if (lp3943_gpio->input_mask & BIT(offset))
+               return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
+       else
+               return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
+}
+
+static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       u8 data;
+
+       if (value)
+               data = LP3943_GPIO_OUT_HIGH;
+       else
+               data = LP3943_GPIO_OUT_LOW;
+
+       lp3943_gpio_set_mode(lp3943_gpio, offset, data);
+}
+
+static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int value)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       lp3943_gpio_set(chip, offset, value);
+       lp3943_gpio->input_mask &= ~BIT(offset);
+
+       return 0;
+}
+
+static const struct gpio_chip lp3943_gpio_chip = {
+       .label                  = "lp3943",
+       .owner                  = THIS_MODULE,
+       .request                = lp3943_gpio_request,
+       .free                   = lp3943_gpio_free,
+       .direction_input        = lp3943_gpio_direction_input,
+       .get                    = lp3943_gpio_get,
+       .direction_output       = lp3943_gpio_direction_output,
+       .set                    = lp3943_gpio_set,
+       .base                   = -1,
+       .ngpio                  = LP3943_MAX_GPIO,
+       .can_sleep              = 1,
+};
+
+static int lp3943_gpio_probe(struct platform_device *pdev)
+{
+       struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+       struct lp3943_gpio *lp3943_gpio;
+
+       lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
+                               GFP_KERNEL);
+       if (!lp3943_gpio)
+               return -ENOMEM;
+
+       lp3943_gpio->lp3943 = lp3943;
+       lp3943_gpio->chip = lp3943_gpio_chip;
+       lp3943_gpio->chip.dev = &pdev->dev;
+
+       platform_set_drvdata(pdev, lp3943_gpio);
+
+       return gpiochip_add(&lp3943_gpio->chip);
+}
+
+static int lp3943_gpio_remove(struct platform_device *pdev)
+{
+       struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
+
+       return gpiochip_remove(&lp3943_gpio->chip);
+}
+
+static const struct of_device_id lp3943_gpio_of_match[] = {
+       { .compatible = "ti,lp3943-gpio", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
+
+static struct platform_driver lp3943_gpio_driver = {
+       .probe = lp3943_gpio_probe,
+       .remove = lp3943_gpio_remove,
+       .driver = {
+               .name = "lp3943-gpio",
+               .owner = THIS_MODULE,
+               .of_match_table = lp3943_gpio_of_match,
+       },
+};
+module_platform_driver(lp3943_gpio_driver);
+
+MODULE_DESCRIPTION("LP3943 GPIO driver");
+MODULE_ALIAS("platform:lp3943-gpio");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
new file mode 100644 (file)
index 0000000..72156c1
--- /dev/null
@@ -0,0 +1,493 @@
+config LEDS_GPIO_REGISTER
+       bool
+       help
+         This option provides the function gpio_led_register_device.
+         As this function is used by arch code it must not be compiled as a
+         module.
+
+menuconfig NEW_LEDS
+       bool "LED Support"
+       help
+         Say Y to enable Linux LED support.  This allows control of supported
+         LEDs from both userspace and optionally, by kernel events (triggers).
+
+         This is not related to standard keyboard LEDs which are controlled
+         via the input system.
+
+if NEW_LEDS
+
+config LEDS_CLASS
+       tristate "LED Class Support"
+       help
+         This option enables the led sysfs class in /sys/class/leds.  You'll
+         need this to do anything useful with LEDs.  If unsure, say N.
+
+comment "LED drivers"
+
+config LEDS_88PM860X
+       tristate "LED Support for Marvell 88PM860x PMIC"
+       depends on LEDS_CLASS
+       depends on MFD_88PM860X
+       help
+         This option enables support for on-chip LED drivers found on Marvell
+         Semiconductor 88PM8606 PMIC.
+
+config LEDS_ATMEL_PWM
+       tristate "LED Support using Atmel PWM outputs"
+       depends on LEDS_CLASS
+       depends on ATMEL_PWM
+       help
+         This option enables support for LEDs driven using outputs
+         of the dedicated PWM controller found on newer Atmel SOCs.
+
+config LEDS_LM3530
+       tristate "LCD Backlight driver for LM3530"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for the LCD backlight using
+         LM3530 ambient light sensor chip. This ALS chip can be
+         controlled manually or using PWM input or using ambient
+         light automatically.
+
+config LEDS_LM3533
+       tristate "LED support for LM3533"
+       depends on LEDS_CLASS
+       depends on MFD_LM3533
+       help
+         This option enables support for the LEDs on National Semiconductor /
+         TI LM3533 Lighting Power chips.
+
+         The LEDs can be controlled directly, through PWM input, or by the
+         ambient-light-sensor interface. The chip supports
+         hardware-accelerated blinking with maximum on and off periods of 9.8
+         and 77 seconds respectively.
+
+config LEDS_LM3642
+       tristate "LED support for LM3642 Chip"
+       depends on LEDS_CLASS && I2C
+       select REGMAP_I2C
+       help
+         This option enables support for LEDs connected to LM3642.
+         The LM3642 is a 4MHz fixed-frequency synchronous boost
+         converter plus 1.5A constant current driver for a high-current
+         white LED.
+
+
+config LEDS_LOCOMO
+       tristate "LED Support for Locomo device"
+       depends on LEDS_CLASS
+       depends on SHARP_LOCOMO
+       help
+         This option enables support for the LEDs on Sharp Locomo.
+         Zaurus models SL-5500 and SL-5600.
+
+config LEDS_MIKROTIK_RB532
+       tristate "LED Support for Mikrotik Routerboard 532"
+       depends on LEDS_CLASS
+       depends on MIKROTIK_RB532
+       help
+         This option enables support for the so called "User LED" of
+         Mikrotik's Routerboard 532.
+
+config LEDS_S3C24XX
+       tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+       depends on LEDS_CLASS
+       depends on ARCH_S3C24XX
+       help
+         This option enables support for LEDs connected to GPIO lines
+         on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
+
+config LEDS_NET48XX
+       tristate "LED Support for Soekris net48xx series Error LED"
+       depends on LEDS_CLASS
+       depends on SCx200_GPIO
+       help
+         This option enables support for the Soekris net4801 and net4826 error
+         LED.
+
+config LEDS_FSG
+       tristate "LED Support for the Freecom FSG-3"
+       depends on LEDS_CLASS
+       depends on MACH_FSG
+       help
+         This option enables support for the LEDs on the Freecom FSG-3.
+
+config LEDS_WRAP
+       tristate "LED Support for the WRAP series LEDs"
+       depends on LEDS_CLASS
+       depends on SCx200_GPIO
+       help
+         This option enables support for the PCEngines WRAP programmable LEDs.
+
+config LEDS_COBALT_QUBE
+       tristate "LED Support for the Cobalt Qube series front LED"
+       depends on LEDS_CLASS
+       depends on MIPS_COBALT
+       help
+         This option enables support for the front LED on Cobalt Qube series
+
+config LEDS_COBALT_RAQ
+       bool "LED Support for the Cobalt Raq series"
+       depends on LEDS_CLASS=y && MIPS_COBALT
+       select LEDS_TRIGGERS
+       help
+         This option enables support for the Cobalt Raq series LEDs.
+
+config LEDS_SUNFIRE
+       tristate "LED support for SunFire servers."
+       depends on LEDS_CLASS
+       depends on SPARC64
+       select LEDS_TRIGGERS
+       help
+         This option enables support for the Left, Middle, and Right
+         LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
+
+config LEDS_HP6XX
+       tristate "LED Support for the HP Jornada 6xx"
+       depends on LEDS_CLASS
+       depends on SH_HP6XX
+       help
+         This option enables LED support for the handheld
+         HP Jornada 620/660/680/690.
+
+config LEDS_PCA9532
+       tristate "LED driver for PCA9532 dimmer"
+       depends on LEDS_CLASS
+       depends on I2C && INPUT
+       help
+         This option enables support for NXP pca9532
+         LED controller. It is generally only useful
+         as a platform driver
+
+config LEDS_PCA9532_GPIO
+       bool "Enable GPIO support for PCA9532"
+       depends on LEDS_PCA9532
+       depends on GPIOLIB
+       help
+         Allow unused pins on PCA9532 to be used as gpio.
+
+         To use a pin as gpio pca9532_type in pca9532_platform data needs to
+         set to PCA9532_TYPE_GPIO.
+
+config LEDS_GPIO
+       tristate "LED Support for GPIO connected LEDs"
+       depends on LEDS_CLASS
+       depends on GPIOLIB
+       help
+         This option enables support for the LEDs connected to GPIO
+         outputs. To be useful the particular board must have LEDs
+         and they must be connected to the GPIO lines.  The LEDs must be
+         defined as platform devices and/or OpenFirmware platform devices.
+         The code to use these bindings can be selected below.
+
+config LEDS_LP3944
+       tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for LEDs connected to the National
+         Semiconductor LP3944 Lighting Management Unit (LMU) also known as
+         Fun Light Chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called leds-lp3944.
+
+config LEDS_LP55XX_COMMON
+       tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
+       depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
+       select FW_LOADER
+       help
+         This option supports common operations for LP5521/5523/55231/5562/8501
+         devices.
+
+config LEDS_LP5521
+       tristate "LED Support for N.S. LP5521 LED driver chip"
+       depends on LEDS_CLASS && I2C
+       select LEDS_LP55XX_COMMON
+       help
+         If you say yes here you get support for the National Semiconductor
+         LP5521 LED driver. It is 3 channel chip with programmable engines.
+         Driver provides direct control via LED class and interface for
+         programming the engines.
+
+config LEDS_LP5523
+       tristate "LED Support for TI/National LP5523/55231 LED driver chip"
+       depends on LEDS_CLASS && I2C
+       select LEDS_LP55XX_COMMON
+       help
+         If you say yes here you get support for TI/National Semiconductor
+         LP5523/55231 LED driver.
+         It is 9 channel chip with programmable engines.
+         Driver provides direct control via LED class and interface for
+         programming the engines.
+
+config LEDS_LP5562
+       tristate "LED Support for TI LP5562 LED driver chip"
+       depends on LEDS_CLASS && I2C
+       select LEDS_LP55XX_COMMON
+       help
+         If you say yes here you get support for TI LP5562 LED driver.
+         It is 4 channels chip with programmable engines.
+         Driver provides direct control via LED class and interface for
+         programming the engines.
+
+config LEDS_LP8501
+       tristate "LED Support for TI LP8501 LED driver chip"
+       depends on LEDS_CLASS && I2C
+       select LEDS_LP55XX_COMMON
+       help
+         If you say yes here you get support for TI LP8501 LED driver.
+         It is 9 channel chip with programmable engines.
+         Driver provides direct control via LED class and interface for
+         programming the engines.
+         It is similar as LP5523, but output power selection is available.
+         And register layout and engine program schemes are different.
+
+config LEDS_LP8788
+       tristate "LED support for the TI LP8788 PMIC"
+       depends on LEDS_CLASS
+       depends on MFD_LP8788
+       help
+         This option enables support for the Keyboard LEDs on the LP8788 PMIC.
+
+config LEDS_CLEVO_MAIL
+       tristate "Mail LED on Clevo notebook"
+       depends on LEDS_CLASS
+       depends on X86 && SERIO_I8042 && DMI
+       help
+         This driver makes the mail LED accessible from userspace
+         programs through the leds subsystem. This LED have three
+         known mode: off, blink at 0.5Hz and blink at 1Hz.
+
+         The driver supports two kinds of interface: using ledtrig-timer
+         or through /sys/class/leds/clevo::mail/brightness. As this LED
+         cannot change it's brightness it blinks instead. The brightness
+         value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
+         blink at 1Hz.
+
+         This module can drive the mail LED for the following notebooks:
+
+               Clevo D400P
+               Clevo D410J
+               Clevo D410V
+               Clevo D400V/D470V (not tested, but might work)
+               Clevo M540N
+               Clevo M5x0N (not tested, but might work)
+               Positivo Mobile (Clevo M5x0V)
+
+         If your model is not listed here you can try the "nodetect"
+         module parameter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called leds-clevo-mail.
+
+config LEDS_PCA955X
+       tristate "LED Support for PCA955x I2C chips"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for LEDs connected to PCA955x
+         LED driver chips accessed via the I2C bus.  Supported
+         devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+
+config LEDS_PCA963X
+       tristate "LED support for PCA963x I2C chip"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for LEDs connected to the PCA963x
+         LED driver chip accessed via the I2C bus. Supported
+         devices include PCA9633 and PCA9634
+
+config LEDS_PCA9685
+       tristate "LED support for PCA9685 I2C chip"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for LEDs connected to the PCA9685
+         LED driver chip accessed via the I2C bus.
+         The PCA9685 offers 12-bit PWM (4095 levels of brightness) on
+         16 individual channels.
+
+config LEDS_WM831X_STATUS
+       tristate "LED support for status LEDs on WM831x PMICs"
+       depends on LEDS_CLASS
+       depends on MFD_WM831X
+       help
+         This option enables support for the status LEDs of the WM831x
+          series of PMICs.
+
+config LEDS_WM8350
+       tristate "LED Support for WM8350 AudioPlus PMIC"
+       depends on LEDS_CLASS
+       depends on MFD_WM8350
+       help
+         This option enables support for LEDs driven by the Wolfson
+         Microelectronics WM8350 AudioPlus PMIC.
+
+config LEDS_DA903X
+       tristate "LED Support for DA9030/DA9034 PMIC"
+       depends on LEDS_CLASS
+       depends on PMIC_DA903X
+       help
+         This option enables support for on-chip LED drivers found
+         on Dialog Semiconductor DA9030/DA9034 PMICs.
+
+config LEDS_DA9052
+       tristate "Dialog DA9052/DA9053 LEDS"
+       depends on LEDS_CLASS
+       depends on PMIC_DA9052
+       help
+         This option enables support for on-chip LED drivers found
+         on Dialog Semiconductor DA9052-BC and DA9053-AA/Bx PMICs.
+
+config LEDS_DAC124S085
+       tristate "LED Support for DAC124S085 SPI DAC"
+       depends on LEDS_CLASS
+       depends on SPI
+       help
+         This option enables support for DAC124S085 SPI DAC from NatSemi,
+         which can be used to control up to four LEDs.
+
+config LEDS_PWM
+       tristate "PWM driven LED Support"
+       depends on LEDS_CLASS
+       depends on PWM
+       help
+         This option enables support for pwm driven LEDs
+
+config LEDS_REGULATOR
+       tristate "REGULATOR driven LED support"
+       depends on LEDS_CLASS
+       depends on REGULATOR
+       help
+         This option enables support for regulator driven LEDs.
+
+config LEDS_BD2802
+       tristate "LED driver for BD2802 RGB LED"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for BD2802GU RGB LED driver chips
+         accessed via the I2C bus.
+
+config LEDS_INTEL_SS4200
+       tristate "LED driver for Intel NAS SS4200 series"
+       depends on LEDS_CLASS
+       depends on PCI && DMI
+       help
+         This option enables support for the Intel SS4200 series of
+         Network Attached Storage servers.  You may control the hard
+         drive or power LEDs on the front panel.  Using this driver
+         can stop the front LED from blinking after startup.
+
+config LEDS_LT3593
+       tristate "LED driver for LT3593 controllers"
+       depends on LEDS_CLASS
+       depends on GPIOLIB
+       help
+         This option enables support for LEDs driven by a Linear Technology
+         LT3593 controller. This controller uses a special one-wire pulse
+         coding protocol to set the brightness.
+
+config LEDS_ADP5520
+       tristate "LED Support for ADP5520/ADP5501 PMIC"
+       depends on LEDS_CLASS
+       depends on PMIC_ADP5520
+       help
+         This option enables support for on-chip LED drivers found
+         on Analog Devices ADP5520/ADP5501 PMICs.
+
+         To compile this driver as a module, choose M here: the module will
+         be called leds-adp5520.
+
+config LEDS_DELL_NETBOOKS
+       tristate "External LED on Dell Business Netbooks"
+       depends on LEDS_CLASS
+       depends on X86 && ACPI_WMI
+       help
+         This adds support for the Latitude 2100 and similar
+         notebooks that have an external LED.
+
+config LEDS_MC13783
+       tristate "LED Support for MC13XXX PMIC"
+       depends on LEDS_CLASS
+       depends on MFD_MC13XXX
+       help
+         This option enable support for on-chip LED drivers found
+         on Freescale Semiconductor MC13783/MC13892 PMIC.
+
+config LEDS_NS2
+       tristate "LED support for Network Space v2 GPIO LEDs"
+       depends on LEDS_CLASS
+       depends on ARCH_KIRKWOOD
+       default y
+       help
+         This option enable support for the dual-GPIO LED found on the
+         Network Space v2 board (and parents). This include Internet Space v2,
+         Network Space (Max) v2 and d2 Network v2 boards.
+
+config LEDS_NETXBIG
+       tristate "LED support for Big Network series LEDs"
+       depends on LEDS_CLASS
+       depends on ARCH_KIRKWOOD
+       default y
+       help
+         This option enable support for LEDs found on the LaCie 2Big
+         and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
+         controlled through a GPIO extension bus.
+
+config LEDS_ASIC3
+       bool "LED support for the HTC ASIC3"
+       depends on LEDS_CLASS=y
+       depends on MFD_ASIC3
+       default y
+       help
+         This option enables support for the LEDs on the HTC ASIC3. The HTC
+         ASIC3 LED GPIOs are inputs, not outputs, thus the leds-gpio driver
+         cannot be used. This driver supports hardware blinking with an on+off
+         period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
+
+config LEDS_TCA6507
+       tristate "LED Support for TCA6507 I2C chip"
+       depends on LEDS_CLASS && I2C
+       help
+         This option enables support for LEDs connected to TC6507
+         LED driver chips accessed via the I2C bus.
+         Driver support brightness control and hardware-assisted blinking.
+
+config LEDS_MAX8997
+       tristate "LED support for MAX8997 PMIC"
+       depends on LEDS_CLASS && MFD_MAX8997
+       help
+         This option enables support for on-chip LED drivers on
+         MAXIM MAX8997 PMIC.
+
+config LEDS_LM355x
+       tristate "LED support for LM355x Chips, LM3554 and LM3556"
+       depends on LEDS_CLASS && I2C
+       select REGMAP_I2C
+       help
+         This option enables support for LEDs connected to LM355x.
+         LM355x includes Torch, Flash and Indicator functions.
+
+config LEDS_OT200
+       tristate "LED support for the Bachmann OT200"
+       depends on LEDS_CLASS && HAS_IOMEM
+       help
+         This option enables support for the LEDs on the Bachmann OT200.
+         Say Y to enable LEDs on the Bachmann OT200.
+
+config LEDS_BLINKM
+       tristate "LED support for the BlinkM I2C RGB LED"
+       depends on LEDS_CLASS
+       depends on I2C
+       help
+         This option enables support for the BlinkM RGB LED connected
+         through I2C. Say Y to enable support for the BlinkM LED.
+
+comment "LED Triggers"
+source "drivers/leds/trigger/Kconfig"
+
+endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
new file mode 100644 (file)
index 0000000..3cd76db
--- /dev/null
@@ -0,0 +1,62 @@
+
+# LED Core
+obj-$(CONFIG_NEW_LEDS)                 += led-core.o
+obj-$(CONFIG_LEDS_CLASS)               += led-class.o
+obj-$(CONFIG_LEDS_TRIGGERS)            += led-triggers.o
+
+# LED Platform Drivers
+obj-$(CONFIG_LEDS_88PM860X)            += leds-88pm860x.o
+obj-$(CONFIG_LEDS_ATMEL_PWM)           += leds-atmel-pwm.o
+obj-$(CONFIG_LEDS_BD2802)              += leds-bd2802.o
+obj-$(CONFIG_LEDS_LOCOMO)              += leds-locomo.o
+obj-$(CONFIG_LEDS_LM3530)              += leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3533)              += leds-lm3533.o
+obj-$(CONFIG_LEDS_LM3642)              += leds-lm3642.o
+obj-$(CONFIG_LEDS_MIKROTIK_RB532)      += leds-rb532.o
+obj-$(CONFIG_LEDS_S3C24XX)             += leds-s3c24xx.o
+obj-$(CONFIG_LEDS_NET48XX)             += leds-net48xx.o
+obj-$(CONFIG_LEDS_WRAP)                        += leds-wrap.o
+obj-$(CONFIG_LEDS_COBALT_QUBE)         += leds-cobalt-qube.o
+obj-$(CONFIG_LEDS_COBALT_RAQ)          += leds-cobalt-raq.o
+obj-$(CONFIG_LEDS_SUNFIRE)             += leds-sunfire.o
+obj-$(CONFIG_LEDS_PCA9532)             += leds-pca9532.o
+obj-$(CONFIG_LEDS_GPIO_REGISTER)       += leds-gpio-register.o
+obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o
+obj-$(CONFIG_LEDS_LP3944)              += leds-lp3944.o
+obj-$(CONFIG_LEDS_LP55XX_COMMON)       += leds-lp55xx-common.o
+obj-$(CONFIG_LEDS_LP5521)              += leds-lp5521.o
+obj-$(CONFIG_LEDS_LP5523)              += leds-lp5523.o
+obj-$(CONFIG_LEDS_LP5562)              += leds-lp5562.o
+obj-$(CONFIG_LEDS_LP8501)              += leds-lp8501.o
+obj-$(CONFIG_LEDS_LP8788)              += leds-lp8788.o
+obj-$(CONFIG_LEDS_TCA6507)             += leds-tca6507.o
+obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
+obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
+obj-$(CONFIG_LEDS_OT200)               += leds-ot200.o
+obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
+obj-$(CONFIG_LEDS_PCA955X)             += leds-pca955x.o
+obj-$(CONFIG_LEDS_PCA963X)             += leds-pca963x.o
+obj-$(CONFIG_LEDS_PCA9685)             += leds-pca9685.o
+obj-$(CONFIG_LEDS_DA903X)              += leds-da903x.o
+obj-$(CONFIG_LEDS_DA9052)              += leds-da9052.o
+obj-$(CONFIG_LEDS_WM831X_STATUS)       += leds-wm831x-status.o
+obj-$(CONFIG_LEDS_WM8350)              += leds-wm8350.o
+obj-$(CONFIG_LEDS_PWM)                 += leds-pwm.o
+obj-$(CONFIG_LEDS_REGULATOR)           += leds-regulator.o
+obj-$(CONFIG_LEDS_INTEL_SS4200)                += leds-ss4200.o
+obj-$(CONFIG_LEDS_LT3593)              += leds-lt3593.o
+obj-$(CONFIG_LEDS_ADP5520)             += leds-adp5520.o
+obj-$(CONFIG_LEDS_DELL_NETBOOKS)       += dell-led.o
+obj-$(CONFIG_LEDS_MC13783)             += leds-mc13783.o
+obj-$(CONFIG_LEDS_NS2)                 += leds-ns2.o
+obj-$(CONFIG_LEDS_NETXBIG)             += leds-netxbig.o
+obj-$(CONFIG_LEDS_ASIC3)               += leds-asic3.o
+obj-$(CONFIG_LEDS_MAX8997)             += leds-max8997.o
+obj-$(CONFIG_LEDS_LM355x)              += leds-lm355x.o
+obj-$(CONFIG_LEDS_BLINKM)              += leds-blinkm.o
+
+# LED SPI Drivers
+obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
+
+# LED Triggers
+obj-$(CONFIG_LEDS_TRIGGERS)            += trigger/
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
new file mode 100644 (file)
index 0000000..591eb5e
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+* Simple driver for Texas Instruments LM355x LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm355x.h>
+
+enum lm355x_type {
+       CHIP_LM3554 = 0,
+       CHIP_LM3556,
+};
+
+enum lm355x_regs {
+       REG_FLAG = 0,
+       REG_TORCH_CFG,
+       REG_TORCH_CTRL,
+       REG_STROBE_CFG,
+       REG_FLASH_CTRL,
+       REG_INDI_CFG,
+       REG_INDI_CTRL,
+       REG_OPMODE,
+       REG_MAX,
+};
+
+/* operation mode */
+enum lm355x_mode {
+       MODE_SHDN = 0,
+       MODE_INDIC,
+       MODE_TORCH,
+       MODE_FLASH
+};
+
+/* register map info. */
+struct lm355x_reg_data {
+       u8 regno;
+       u8 mask;
+       u8 shift;
+};
+
+struct lm355x_chip_data {
+       struct device *dev;
+       enum lm355x_type type;
+
+       struct led_classdev cdev_flash;
+       struct led_classdev cdev_torch;
+       struct led_classdev cdev_indicator;
+
+       struct work_struct work_flash;
+       struct work_struct work_torch;
+       struct work_struct work_indicator;
+
+       u8 br_flash;
+       u8 br_torch;
+       u8 br_indicator;
+
+       struct lm355x_platform_data *pdata;
+       struct regmap *regmap;
+       struct mutex lock;
+
+       unsigned int last_flag;
+       struct lm355x_reg_data *regs;
+};
+
+/* specific indicator function for lm3556 */
+enum lm3556_indic_pulse_time {
+       PULSE_TIME_0_MS = 0,
+       PULSE_TIME_32_MS,
+       PULSE_TIME_64_MS,
+       PULSE_TIME_92_MS,
+       PULSE_TIME_128_MS,
+       PULSE_TIME_160_MS,
+       PULSE_TIME_196_MS,
+       PULSE_TIME_224_MS,
+       PULSE_TIME_256_MS,
+       PULSE_TIME_288_MS,
+       PULSE_TIME_320_MS,
+       PULSE_TIME_352_MS,
+       PULSE_TIME_384_MS,
+       PULSE_TIME_416_MS,
+       PULSE_TIME_448_MS,
+       PULSE_TIME_480_MS,
+};
+
+enum lm3556_indic_n_blank {
+       INDIC_N_BLANK_0 = 0,
+       INDIC_N_BLANK_1,
+       INDIC_N_BLANK_2,
+       INDIC_N_BLANK_3,
+       INDIC_N_BLANK_4,
+       INDIC_N_BLANK_5,
+       INDIC_N_BLANK_6,
+       INDIC_N_BLANK_7,
+       INDIC_N_BLANK_8,
+       INDIC_N_BLANK_9,
+       INDIC_N_BLANK_10,
+       INDIC_N_BLANK_11,
+       INDIC_N_BLANK_12,
+       INDIC_N_BLANK_13,
+       INDIC_N_BLANK_14,
+       INDIC_N_BLANK_15,
+};
+
+enum lm3556_indic_period {
+       INDIC_PERIOD_0 = 0,
+       INDIC_PERIOD_1,
+       INDIC_PERIOD_2,
+       INDIC_PERIOD_3,
+       INDIC_PERIOD_4,
+       INDIC_PERIOD_5,
+       INDIC_PERIOD_6,
+       INDIC_PERIOD_7,
+};
+
+#define INDIC_PATTERN_SIZE 4
+
+struct indicator {
+       u8 blinking;
+       u8 period_cnt;
+};
+
+/* indicator pattern data only for lm3556 */
+static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
+       [0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1},
+       [1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2},
+       [2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4},
+       [3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7},
+};
+
+static struct lm355x_reg_data lm3554_regs[REG_MAX] = {
+       [REG_FLAG] = {0xD0, 0xBF, 0},
+       [REG_TORCH_CFG] = {0xE0, 0x80, 7},
+       [REG_TORCH_CTRL] = {0xA0, 0x38, 3},
+       [REG_STROBE_CFG] = {0xE0, 0x04, 2},
+       [REG_FLASH_CTRL] = {0xB0, 0x78, 3},
+       [REG_INDI_CFG] = {0xE0, 0x08, 3},
+       [REG_INDI_CTRL] = {0xA0, 0xC0, 6},
+       [REG_OPMODE] = {0xA0, 0x03, 0},
+};
+
+static struct lm355x_reg_data lm3556_regs[REG_MAX] = {
+       [REG_FLAG] = {0x0B, 0xFF, 0},
+       [REG_TORCH_CFG] = {0x0A, 0x10, 4},
+       [REG_TORCH_CTRL] = {0x09, 0x70, 4},
+       [REG_STROBE_CFG] = {0x0A, 0x20, 5},
+       [REG_FLASH_CTRL] = {0x09, 0x0F, 0},
+       [REG_INDI_CFG] = {0xFF, 0xFF, 0},
+       [REG_INDI_CTRL] = {0x09, 0x70, 4},
+       [REG_OPMODE] = {0x0A, 0x03, 0},
+};
+
+static char lm355x_name[][I2C_NAME_SIZE] = {
+       [CHIP_LM3554] = LM3554_NAME,
+       [CHIP_LM3556] = LM3556_NAME,
+};
+
+/* chip initialize */
+static int lm355x_chip_init(struct lm355x_chip_data *chip)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm355x_platform_data *pdata = chip->pdata;
+
+       /* input and output pins configuration */
+       switch (chip->type) {
+       case CHIP_LM3554:
+               reg_val = pdata->pin_tx2 | pdata->ntc_pin;
+               ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
+               if (ret < 0)
+                       goto out;
+               reg_val = pdata->pass_mode;
+               ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
+               if (ret < 0)
+                       goto out;
+               break;
+
+       case CHIP_LM3556:
+               reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
+               ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
+               if (ret < 0)
+                       goto out;
+               break;
+       default:
+               return -ENODATA;
+       }
+
+       return ret;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return ret;
+}
+
+/* chip control */
+static void lm355x_control(struct lm355x_chip_data *chip,
+                          u8 brightness, enum lm355x_mode opmode)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm355x_platform_data *pdata = chip->pdata;
+       struct lm355x_reg_data *preg = chip->regs;
+
+       ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag);
+       if (ret < 0)
+               goto out;
+       if (chip->last_flag & preg[REG_FLAG].mask)
+               dev_info(chip->dev, "%s Last FLAG is 0x%x\n",
+                        lm355x_name[chip->type],
+                        chip->last_flag & preg[REG_FLAG].mask);
+       /* brightness 0 means shutdown */
+       if (!brightness)
+               opmode = MODE_SHDN;
+
+       switch (opmode) {
+       case MODE_TORCH:
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno,
+                                      preg[REG_TORCH_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_TORCH_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) {
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_TORCH_CFG].regno,
+                                              preg[REG_TORCH_CFG].mask,
+                                              0x01 <<
+                                              preg[REG_TORCH_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+                       dev_info(chip->dev,
+                                "torch brt is set - ext. torch pin mode\n");
+               }
+               break;
+
+       case MODE_FLASH:
+
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno,
+                                      preg[REG_FLASH_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_FLASH_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) {
+                       if (chip->type == CHIP_LM3554)
+                               reg_val = 0x00;
+                       else
+                               reg_val = 0x01;
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_STROBE_CFG].regno,
+                                              preg[REG_STROBE_CFG].mask,
+                                              reg_val <<
+                                              preg[REG_STROBE_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+                       dev_info(chip->dev,
+                                "flash brt is set - ext. strobe pin mode\n");
+               }
+               break;
+
+       case MODE_INDIC:
+               ret =
+                   regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno,
+                                      preg[REG_INDI_CTRL].mask,
+                                      (brightness - 1)
+                                      << preg[REG_INDI_CTRL].shift);
+               if (ret < 0)
+                       goto out;
+
+               if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) {
+                       ret =
+                           regmap_update_bits(chip->regmap,
+                                              preg[REG_INDI_CFG].regno,
+                                              preg[REG_INDI_CFG].mask,
+                                              0x01 <<
+                                              preg[REG_INDI_CFG].shift);
+                       if (ret < 0)
+                               goto out;
+                       opmode = MODE_SHDN;
+               }
+               break;
+       case MODE_SHDN:
+               break;
+       default:
+               return;
+       }
+       /* operation mode control */
+       ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
+                                preg[REG_OPMODE].mask,
+                                opmode << preg[REG_OPMODE].shift);
+       if (ret < 0)
+               goto out;
+       return;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return;
+}
+
+/* torch */
+static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_torch);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_torch, MODE_TORCH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_torch_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_torch);
+
+       chip->br_torch = brightness;
+       schedule_work(&chip->work_torch);
+}
+
+/* flash */
+static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_flash);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_flash, MODE_FLASH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
+                                        enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_flash);
+
+       chip->br_flash = brightness;
+       schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
+{
+       struct lm355x_chip_data *chip =
+           container_of(work, struct lm355x_chip_data, work_indicator);
+
+       mutex_lock(&chip->lock);
+       lm355x_control(chip, chip->br_indicator, MODE_INDIC);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
+                                           enum led_brightness brightness)
+{
+       struct lm355x_chip_data *chip =
+           container_of(cdev, struct lm355x_chip_data, cdev_indicator);
+
+       chip->br_indicator = brightness;
+       schedule_work(&chip->work_indicator);
+}
+
+/* indicator pattern only for lm3556*/
+static ssize_t lm3556_indicator_pattern_store(struct device *dev,
+                                             struct device_attribute *attr,
+                                             const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm355x_chip_data *chip =
+           container_of(led_cdev, struct lm355x_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out;
+       if (state > INDIC_PATTERN_SIZE - 1)
+               state = INDIC_PATTERN_SIZE - 1;
+
+       ret = regmap_write(chip->regmap, 0x04,
+                          indicator_pattern[state].blinking);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_write(chip->regmap, 0x05,
+                          indicator_pattern[state].period_cnt);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return ret;
+}
+
+static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
+
+static const struct regmap_config lm355x_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = 0xFF,
+};
+
+/* module initialize */
+static int lm355x_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lm355x_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct lm355x_chip_data *chip;
+
+       int err;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "i2c functionality check fail.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "needs Platform Data.\n");
+               return -ENODATA;
+       }
+
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct lm355x_chip_data), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &client->dev;
+       chip->type = id->driver_data;
+       switch (id->driver_data) {
+       case CHIP_LM3554:
+               chip->regs = lm3554_regs;
+               break;
+       case CHIP_LM3556:
+               chip->regs = lm3556_regs;
+               break;
+       default:
+               return -ENOSYS;
+       }
+       chip->pdata = pdata;
+
+       chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap);
+       if (IS_ERR(chip->regmap)) {
+               err = PTR_ERR(chip->regmap);
+               dev_err(&client->dev,
+                       "Failed to allocate register map: %d\n", err);
+               return err;
+       }
+
+       mutex_init(&chip->lock);
+       i2c_set_clientdata(client, chip);
+
+       err = lm355x_chip_init(chip);
+       if (err < 0)
+               goto err_out;
+
+       /* flash */
+       INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
+       chip->cdev_flash.name = "flash";
+       chip->cdev_flash.max_brightness = 16;
+       chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
+       chip->cdev_flash.default_trigger = "flash";
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_flash);
+       if (err < 0)
+               goto err_out;
+       /* torch */
+       INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
+       chip->cdev_torch.name = "torch";
+       chip->cdev_torch.max_brightness = 8;
+       chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
+       chip->cdev_torch.default_trigger = "torch";
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_torch);
+       if (err < 0)
+               goto err_create_torch_file;
+       /* indicator */
+       INIT_WORK(&chip->work_indicator,
+                 lm355x_deferred_indicator_brightness_set);
+       chip->cdev_indicator.name = "indicator";
+       if (id->driver_data == CHIP_LM3554)
+               chip->cdev_indicator.max_brightness = 4;
+       else
+               chip->cdev_indicator.max_brightness = 8;
+       chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_indicator);
+       if (err < 0)
+               goto err_create_indicator_file;
+       /* indicator pattern control only for LM3554 */
+       if (id->driver_data == CHIP_LM3556) {
+               err =
+                   device_create_file(chip->cdev_indicator.dev,
+                                      &dev_attr_pattern);
+               if (err < 0)
+                       goto err_create_pattern_file;
+       }
+
+       dev_info(&client->dev, "%s is initialized\n",
+                lm355x_name[id->driver_data]);
+       return 0;
+
+err_create_pattern_file:
+       led_classdev_unregister(&chip->cdev_indicator);
+err_create_indicator_file:
+       led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+       led_classdev_unregister(&chip->cdev_flash);
+err_out:
+       return err;
+}
+
+static int lm355x_remove(struct i2c_client *client)
+{
+       struct lm355x_chip_data *chip = i2c_get_clientdata(client);
+       struct lm355x_reg_data *preg = chip->regs;
+
+       regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
+       if (chip->type == CHIP_LM3556)
+               device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
+       led_classdev_unregister(&chip->cdev_indicator);
+       flush_work(&chip->work_indicator);
+       led_classdev_unregister(&chip->cdev_torch);
+       flush_work(&chip->work_torch);
+       led_classdev_unregister(&chip->cdev_flash);
+       flush_work(&chip->work_flash);
+       dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
+
+       return 0;
+}
+
+static const struct i2c_device_id lm355x_id[] = {
+       {LM3554_NAME, CHIP_LM3554},
+       {LM3556_NAME, CHIP_LM3556},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm355x_id);
+
+static struct i2c_driver lm355x_i2c_driver = {
+       .driver = {
+                  .name = LM355x_NAME,
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .probe = lm355x_probe,
+       .remove = lm355x_remove,
+       .id_table = lm355x_id,
+};
+
+module_i2c_driver(lm355x_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
new file mode 100644 (file)
index 0000000..ceb6b3c
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+* Simple driver for Texas Instruments LM3642 LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm3642.h>
+
+#define        REG_FILT_TIME                   (0x0)
+#define        REG_IVFM_MODE                   (0x1)
+#define        REG_TORCH_TIME                  (0x6)
+#define        REG_FLASH                       (0x8)
+#define        REG_I_CTRL                      (0x9)
+#define        REG_ENABLE                      (0xA)
+#define        REG_FLAG                        (0xB)
+#define        REG_MAX                         (0xB)
+
+#define        UVLO_EN_SHIFT                   (7)
+#define        IVM_D_TH_SHIFT                  (2)
+#define        TORCH_RAMP_UP_TIME_SHIFT        (3)
+#define        TORCH_RAMP_DN_TIME_SHIFT        (0)
+#define        INDUCTOR_I_LIMIT_SHIFT          (6)
+#define        FLASH_RAMP_TIME_SHIFT           (3)
+#define        FLASH_TOUT_TIME_SHIFT           (0)
+#define        TORCH_I_SHIFT                   (4)
+#define        FLASH_I_SHIFT                   (0)
+#define        IVFM_SHIFT                      (7)
+#define        TX_PIN_EN_SHIFT                 (6)
+#define        STROBE_PIN_EN_SHIFT             (5)
+#define        TORCH_PIN_EN_SHIFT              (4)
+#define        MODE_BITS_SHIFT                 (0)
+
+#define        UVLO_EN_MASK                    (0x1)
+#define        IVM_D_TH_MASK                   (0x7)
+#define        TORCH_RAMP_UP_TIME_MASK         (0x7)
+#define        TORCH_RAMP_DN_TIME_MASK         (0x7)
+#define        INDUCTOR_I_LIMIT_MASK           (0x1)
+#define        FLASH_RAMP_TIME_MASK            (0x7)
+#define        FLASH_TOUT_TIME_MASK            (0x7)
+#define        TORCH_I_MASK                    (0x7)
+#define        FLASH_I_MASK                    (0xF)
+#define        IVFM_MASK                       (0x1)
+#define        TX_PIN_EN_MASK                  (0x1)
+#define        STROBE_PIN_EN_MASK              (0x1)
+#define        TORCH_PIN_EN_MASK               (0x1)
+#define        MODE_BITS_MASK                  (0x73)
+#define EX_PIN_CONTROL_MASK            (0x71)
+#define EX_PIN_ENABLE_MASK             (0x70)
+
+enum lm3642_mode {
+       MODES_STASNDBY = 0,
+       MODES_INDIC,
+       MODES_TORCH,
+       MODES_FLASH
+};
+
+struct lm3642_chip_data {
+       struct device *dev;
+
+       struct led_classdev cdev_flash;
+       struct led_classdev cdev_torch;
+       struct led_classdev cdev_indicator;
+
+       struct work_struct work_flash;
+       struct work_struct work_torch;
+       struct work_struct work_indicator;
+
+       u8 br_flash;
+       u8 br_torch;
+       u8 br_indicator;
+
+       enum lm3642_torch_pin_enable torch_pin;
+       enum lm3642_strobe_pin_enable strobe_pin;
+       enum lm3642_tx_pin_enable tx_pin;
+
+       struct lm3642_platform_data *pdata;
+       struct regmap *regmap;
+       struct mutex lock;
+
+       unsigned int last_flag;
+};
+
+/* chip initialize */
+static int lm3642_chip_init(struct lm3642_chip_data *chip)
+{
+       int ret;
+       struct lm3642_platform_data *pdata = chip->pdata;
+
+       /* set enable register */
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
+                                pdata->tx_pin);
+       if (ret < 0)
+               dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
+       return ret;
+}
+
+/* chip control */
+static int lm3642_control(struct lm3642_chip_data *chip,
+                         u8 brightness, enum lm3642_mode opmode)
+{
+       int ret;
+
+       ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
+               goto out;
+       }
+
+       if (chip->last_flag)
+               dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
+
+       /* brightness 0 means off-state */
+       if (!brightness)
+               opmode = MODES_STASNDBY;
+
+       switch (opmode) {
+       case MODES_TORCH:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        TORCH_I_MASK << TORCH_I_SHIFT,
+                                        (brightness - 1) << TORCH_I_SHIFT);
+
+               if (chip->torch_pin)
+                       opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
+               break;
+
+       case MODES_FLASH:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        FLASH_I_MASK << FLASH_I_SHIFT,
+                                        (brightness - 1) << FLASH_I_SHIFT);
+
+               if (chip->strobe_pin)
+                       opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
+               break;
+
+       case MODES_INDIC:
+               ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+                                        TORCH_I_MASK << TORCH_I_SHIFT,
+                                        (brightness - 1) << TORCH_I_SHIFT);
+               break;
+
+       case MODES_STASNDBY:
+
+               break;
+
+       default:
+               return ret;
+       }
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
+               goto out;
+       }
+
+       if (chip->tx_pin)
+               opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
+
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                MODE_BITS_MASK << MODE_BITS_SHIFT,
+                                opmode << MODE_BITS_SHIFT);
+out:
+       return ret;
+}
+
+/* torch */
+
+/* torch pin config for lm3642*/
+static ssize_t lm3642_torch_pin_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm3642_chip_data *chip =
+           container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out_strtoint;
+       if (state != 0)
+               state = 0x01 << TORCH_PIN_EN_SHIFT;
+
+       chip->torch_pin = state;
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
+                                state);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return ret;
+out_strtoint:
+       dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+       return ret;
+}
+
+static DEVICE_ATTR(torch_pin, S_IWUSR, NULL, lm3642_torch_pin_store);
+
+static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_torch);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_torch, MODES_TORCH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_torch_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_torch);
+
+       chip->br_torch = brightness;
+       schedule_work(&chip->work_torch);
+}
+
+/* flash */
+
+/* strobe pin config for lm3642*/
+static ssize_t lm3642_strobe_pin_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+       struct lm3642_chip_data *chip =
+           container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out_strtoint;
+       if (state != 0)
+               state = 0x01 << STROBE_PIN_EN_SHIFT;
+
+       chip->strobe_pin = state;
+       ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+                                STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
+                                state);
+       if (ret < 0)
+               goto out;
+
+       return size;
+out:
+       dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+       return ret;
+out_strtoint:
+       dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+       return ret;
+}
+
+static DEVICE_ATTR(strobe_pin, S_IWUSR, NULL, lm3642_strobe_pin_store);
+
+static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_flash);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_flash, MODES_FLASH);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
+                                        enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_flash);
+
+       chip->br_flash = brightness;
+       schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
+{
+       struct lm3642_chip_data *chip =
+           container_of(work, struct lm3642_chip_data, work_indicator);
+
+       mutex_lock(&chip->lock);
+       lm3642_control(chip, chip->br_indicator, MODES_INDIC);
+       mutex_unlock(&chip->lock);
+}
+
+static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
+                                           enum led_brightness brightness)
+{
+       struct lm3642_chip_data *chip =
+           container_of(cdev, struct lm3642_chip_data, cdev_indicator);
+
+       chip->br_indicator = brightness;
+       schedule_work(&chip->work_indicator);
+}
+
+static const struct regmap_config lm3642_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = REG_MAX,
+};
+
+static int lm3642_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct lm3642_chip_data *chip;
+
+       int err;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "i2c functionality check fail.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "needs Platform Data.\n");
+               return -ENODATA;
+       }
+
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct lm3642_chip_data), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &client->dev;
+       chip->pdata = pdata;
+
+       chip->tx_pin = pdata->tx_pin;
+       chip->torch_pin = pdata->torch_pin;
+       chip->strobe_pin = pdata->strobe_pin;
+
+       chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
+       if (IS_ERR(chip->regmap)) {
+               err = PTR_ERR(chip->regmap);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                       err);
+               return err;
+       }
+
+       mutex_init(&chip->lock);
+       i2c_set_clientdata(client, chip);
+
+       err = lm3642_chip_init(chip);
+       if (err < 0)
+               goto err_out;
+
+       /* flash */
+       INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
+       chip->cdev_flash.name = "flash";
+       chip->cdev_flash.max_brightness = 16;
+       chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
+       chip->cdev_flash.default_trigger = "flash";
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_flash);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register flash\n");
+               goto err_out;
+       }
+       err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to create strobe-pin file\n");
+               goto err_create_flash_pin_file;
+       }
+
+       /* torch */
+       INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
+       chip->cdev_torch.name = "torch";
+       chip->cdev_torch.max_brightness = 8;
+       chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
+       chip->cdev_torch.default_trigger = "torch";
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_torch);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register torch\n");
+               goto err_create_torch_file;
+       }
+       err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to create torch-pin file\n");
+               goto err_create_torch_pin_file;
+       }
+
+       /* indicator */
+       INIT_WORK(&chip->work_indicator,
+                 lm3642_deferred_indicator_brightness_set);
+       chip->cdev_indicator.name = "indicator";
+       chip->cdev_indicator.max_brightness = 8;
+       chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
+       err = led_classdev_register((struct device *)
+                                   &client->dev, &chip->cdev_indicator);
+       if (err < 0) {
+               dev_err(chip->dev, "failed to register indicator\n");
+               goto err_create_indicator_file;
+       }
+
+       dev_info(&client->dev, "LM3642 is initialized\n");
+       return 0;
+
+err_create_indicator_file:
+       device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+err_create_torch_pin_file:
+       led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+       device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+err_create_flash_pin_file:
+       led_classdev_unregister(&chip->cdev_flash);
+err_out:
+       return err;
+}
+
+static int lm3642_remove(struct i2c_client *client)
+{
+       struct lm3642_chip_data *chip = i2c_get_clientdata(client);
+
+       led_classdev_unregister(&chip->cdev_indicator);
+       flush_work(&chip->work_indicator);
+       device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+       led_classdev_unregister(&chip->cdev_torch);
+       flush_work(&chip->work_torch);
+       device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+       led_classdev_unregister(&chip->cdev_flash);
+       flush_work(&chip->work_flash);
+       regmap_write(chip->regmap, REG_ENABLE, 0);
+       return 0;
+}
+
+static const struct i2c_device_id lm3642_id[] = {
+       {LM3642_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3642_id);
+
+static struct i2c_driver lm3642_i2c_driver = {
+       .driver = {
+                  .name = LM3642_NAME,
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .probe = lm3642_probe,
+       .remove = lm3642_remove,
+       .id_table = lm3642_id,
+};
+
+module_i2c_driver(lm3642_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
new file mode 100644 (file)
index 0000000..bf006f4
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * LP5562 LED driver
+ *
+ * Copyright (C) 2013 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/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_data/leds-lp55xx.h>
+#include <linux/slab.h>
+
+#include "leds-lp55xx-common.h"
+
+#define LP5562_PROGRAM_LENGTH          32
+#define LP5562_MAX_LEDS                        4
+
+/* ENABLE Register 00h */
+#define LP5562_REG_ENABLE              0x00
+#define LP5562_EXEC_ENG1_M             0x30
+#define LP5562_EXEC_ENG2_M             0x0C
+#define LP5562_EXEC_ENG3_M             0x03
+#define LP5562_EXEC_M                  0x3F
+#define LP5562_MASTER_ENABLE           0x40    /* Chip master enable */
+#define LP5562_LOGARITHMIC_PWM         0x80    /* Logarithmic PWM adjustment */
+#define LP5562_EXEC_RUN                        0x2A
+#define LP5562_ENABLE_DEFAULT  \
+       (LP5562_MASTER_ENABLE | LP5562_LOGARITHMIC_PWM)
+#define LP5562_ENABLE_RUN_PROGRAM      \
+       (LP5562_ENABLE_DEFAULT | LP5562_EXEC_RUN)
+
+/* OPMODE Register 01h */
+#define LP5562_REG_OP_MODE             0x01
+#define LP5562_MODE_ENG1_M             0x30
+#define LP5562_MODE_ENG2_M             0x0C
+#define LP5562_MODE_ENG3_M             0x03
+#define LP5562_LOAD_ENG1               0x10
+#define LP5562_LOAD_ENG2               0x04
+#define LP5562_LOAD_ENG3               0x01
+#define LP5562_RUN_ENG1                        0x20
+#define LP5562_RUN_ENG2                        0x08
+#define LP5562_RUN_ENG3                        0x02
+#define LP5562_ENG1_IS_LOADING(mode)   \
+       ((mode & LP5562_MODE_ENG1_M) == LP5562_LOAD_ENG1)
+#define LP5562_ENG2_IS_LOADING(mode)   \
+       ((mode & LP5562_MODE_ENG2_M) == LP5562_LOAD_ENG2)
+#define LP5562_ENG3_IS_LOADING(mode)   \
+       ((mode & LP5562_MODE_ENG3_M) == LP5562_LOAD_ENG3)
+
+/* BRIGHTNESS Registers */
+#define LP5562_REG_R_PWM               0x04
+#define LP5562_REG_G_PWM               0x03
+#define LP5562_REG_B_PWM               0x02
+#define LP5562_REG_W_PWM               0x0E
+
+/* CURRENT Registers */
+#define LP5562_REG_R_CURRENT           0x07
+#define LP5562_REG_G_CURRENT           0x06
+#define LP5562_REG_B_CURRENT           0x05
+#define LP5562_REG_W_CURRENT           0x0F
+
+/* CONFIG Register 08h */
+#define LP5562_REG_CONFIG              0x08
+#define LP5562_PWM_HF                  0x40
+#define LP5562_PWRSAVE_EN              0x20
+#define LP5562_CLK_INT                 0x01    /* Internal clock */
+#define LP5562_DEFAULT_CFG             (LP5562_PWM_HF | LP5562_PWRSAVE_EN)
+
+/* RESET Register 0Dh */
+#define LP5562_REG_RESET               0x0D
+#define LP5562_RESET                   0xFF
+
+/* PROGRAM ENGINE Registers */
+#define LP5562_REG_PROG_MEM_ENG1       0x10
+#define LP5562_REG_PROG_MEM_ENG2       0x30
+#define LP5562_REG_PROG_MEM_ENG3       0x50
+
+/* LEDMAP Register 70h */
+#define LP5562_REG_ENG_SEL             0x70
+#define LP5562_ENG_SEL_PWM             0
+#define LP5562_ENG_FOR_RGB_M           0x3F
+#define LP5562_ENG_SEL_RGB             0x1B    /* R:ENG1, G:ENG2, B:ENG3 */
+#define LP5562_ENG_FOR_W_M             0xC0
+#define LP5562_ENG1_FOR_W              0x40    /* W:ENG1 */
+#define LP5562_ENG2_FOR_W              0x80    /* W:ENG2 */
+#define LP5562_ENG3_FOR_W              0xC0    /* W:ENG3 */
+
+/* Program Commands */
+#define LP5562_CMD_DISABLE             0x00
+#define LP5562_CMD_LOAD                        0x15
+#define LP5562_CMD_RUN                 0x2A
+#define LP5562_CMD_DIRECT              0x3F
+#define LP5562_PATTERN_OFF             0
+
+static inline void lp5562_wait_opmode_done(void)
+{
+       /* operation mode change needs to be longer than 153 us */
+       usleep_range(200, 300);
+}
+
+static inline void lp5562_wait_enable_done(void)
+{
+       /* it takes more 488 us to update ENABLE register */
+       usleep_range(500, 600);
+}
+
+static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current)
+{
+       u8 addr[] = {
+               LP5562_REG_R_CURRENT,
+               LP5562_REG_G_CURRENT,
+               LP5562_REG_B_CURRENT,
+               LP5562_REG_W_CURRENT,
+       };
+
+       led->led_current = led_current;
+       lp55xx_write(led->chip, addr[led->chan_nr], led_current);
+}
+
+static void lp5562_load_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP5562_MODE_ENG1_M,
+               [LP55XX_ENGINE_2] = LP5562_MODE_ENG2_M,
+               [LP55XX_ENGINE_3] = LP5562_MODE_ENG3_M,
+       };
+
+       u8 val[] = {
+               [LP55XX_ENGINE_1] = LP5562_LOAD_ENG1,
+               [LP55XX_ENGINE_2] = LP5562_LOAD_ENG2,
+               [LP55XX_ENGINE_3] = LP5562_LOAD_ENG3,
+       };
+
+       lp55xx_update_bits(chip, LP5562_REG_OP_MODE, mask[idx], val[idx]);
+
+       lp5562_wait_opmode_done();
+}
+
+static void lp5562_stop_engine(struct lp55xx_chip *chip)
+{
+       lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DISABLE);
+       lp5562_wait_opmode_done();
+}
+
+static void lp5562_run_engine(struct lp55xx_chip *chip, bool start)
+{
+       int ret;
+       u8 mode;
+       u8 exec;
+
+       /* stop engine */
+       if (!start) {
+               lp55xx_write(chip, LP5562_REG_ENABLE, LP5562_ENABLE_DEFAULT);
+               lp5562_wait_enable_done();
+               lp5562_stop_engine(chip);
+               lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM);
+               lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT);
+               lp5562_wait_opmode_done();
+               return;
+       }
+
+       /*
+        * To run the engine,
+        * operation mode and enable register should updated at the same time
+        */
+
+       ret = lp55xx_read(chip, LP5562_REG_OP_MODE, &mode);
+       if (ret)
+               return;
+
+       ret = lp55xx_read(chip, LP5562_REG_ENABLE, &exec);
+       if (ret)
+               return;
+
+       /* change operation mode to RUN only when each engine is loading */
+       if (LP5562_ENG1_IS_LOADING(mode)) {
+               mode = (mode & ~LP5562_MODE_ENG1_M) | LP5562_RUN_ENG1;
+               exec = (exec & ~LP5562_EXEC_ENG1_M) | LP5562_RUN_ENG1;
+       }
+
+       if (LP5562_ENG2_IS_LOADING(mode)) {
+               mode = (mode & ~LP5562_MODE_ENG2_M) | LP5562_RUN_ENG2;
+               exec = (exec & ~LP5562_EXEC_ENG2_M) | LP5562_RUN_ENG2;
+       }
+
+       if (LP5562_ENG3_IS_LOADING(mode)) {
+               mode = (mode & ~LP5562_MODE_ENG3_M) | LP5562_RUN_ENG3;
+               exec = (exec & ~LP5562_EXEC_ENG3_M) | LP5562_RUN_ENG3;
+       }
+
+       lp55xx_write(chip, LP5562_REG_OP_MODE, mode);
+       lp5562_wait_opmode_done();
+
+       lp55xx_update_bits(chip, LP5562_REG_ENABLE, LP5562_EXEC_M, exec);
+       lp5562_wait_enable_done();
+}
+
+static int lp5562_update_firmware(struct lp55xx_chip *chip,
+                                       const u8 *data, size_t size)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 pattern[LP5562_PROGRAM_LENGTH] = {0};
+       u8 addr[] = {
+               [LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1,
+               [LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2,
+               [LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3,
+       };
+       unsigned cmd;
+       char c[3];
+       int program_size;
+       int nrchars;
+       int offset = 0;
+       int ret;
+       int i;
+
+       /* clear program memory before updating */
+       for (i = 0; i < LP5562_PROGRAM_LENGTH; i++)
+               lp55xx_write(chip, addr[idx] + i, 0);
+
+       i = 0;
+       while ((offset < size - 1) && (i < LP5562_PROGRAM_LENGTH)) {
+               /* separate sscanfs because length is working only for %s */
+               ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
+               if (ret != 1)
+                       goto err;
+
+               ret = sscanf(c, "%2x", &cmd);
+               if (ret != 1)
+                       goto err;
+
+               pattern[i] = (u8)cmd;
+               offset += nrchars;
+               i++;
+       }
+
+       /* Each instruction is 16bit long. Check that length is even */
+       if (i % 2)
+               goto err;
+
+       program_size = i;
+       for (i = 0; i < program_size; i++)
+               lp55xx_write(chip, addr[idx] + i, pattern[i]);
+
+       return 0;
+
+err:
+       dev_err(&chip->cl->dev, "wrong pattern format\n");
+       return -EINVAL;
+}
+
+static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
+{
+       const struct firmware *fw = chip->fw;
+
+       if (fw->size > LP5562_PROGRAM_LENGTH) {
+               dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
+                       fw->size);
+               return;
+       }
+
+       /*
+        * Program momery sequence
+        *  1) set engine mode to "LOAD"
+        *  2) write firmware data into program memory
+        */
+
+       lp5562_load_engine(chip);
+       lp5562_update_firmware(chip, fw->data, fw->size);
+}
+
+static int lp5562_post_init_device(struct lp55xx_chip *chip)
+{
+       int ret;
+       u8 cfg = LP5562_DEFAULT_CFG;
+
+       /* Set all PWMs to direct control mode */
+       ret = lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT);
+       if (ret)
+               return ret;
+
+       lp5562_wait_opmode_done();
+
+       /* Update configuration for the clock setting */
+       if (!lp55xx_is_extclk_used(chip))
+               cfg |= LP5562_CLK_INT;
+
+       ret = lp55xx_write(chip, LP5562_REG_CONFIG, cfg);
+       if (ret)
+               return ret;
+
+       /* Initialize all channels PWM to zero -> leds off */
+       lp55xx_write(chip, LP5562_REG_R_PWM, 0);
+       lp55xx_write(chip, LP5562_REG_G_PWM, 0);
+       lp55xx_write(chip, LP5562_REG_B_PWM, 0);
+       lp55xx_write(chip, LP5562_REG_W_PWM, 0);
+
+       /* Set LED map as register PWM by default */
+       lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM);
+
+       return 0;
+}
+
+static void lp5562_led_brightness_work(struct work_struct *work)
+{
+       struct lp55xx_led *led = container_of(work, struct lp55xx_led,
+                                             brightness_work);
+       struct lp55xx_chip *chip = led->chip;
+       u8 addr[] = {
+               LP5562_REG_R_PWM,
+               LP5562_REG_G_PWM,
+               LP5562_REG_B_PWM,
+               LP5562_REG_W_PWM,
+       };
+
+       mutex_lock(&chip->lock);
+       lp55xx_write(chip, addr[led->chan_nr], led->brightness);
+       mutex_unlock(&chip->lock);
+}
+
+static void lp5562_write_program_memory(struct lp55xx_chip *chip,
+                                       u8 base, const u8 *rgb, int size)
+{
+       int i;
+
+       if (!rgb || size <= 0)
+               return;
+
+       for (i = 0; i < size; i++)
+               lp55xx_write(chip, base + i, *(rgb + i));
+
+       lp55xx_write(chip, base + i, 0);
+       lp55xx_write(chip, base + i + 1, 0);
+}
+
+/* check the size of program count */
+static inline bool _is_pc_overflow(struct lp55xx_predef_pattern *ptn)
+{
+       return (ptn->size_r >= LP5562_PROGRAM_LENGTH ||
+               ptn->size_g >= LP5562_PROGRAM_LENGTH ||
+               ptn->size_b >= LP5562_PROGRAM_LENGTH);
+}
+
+static int lp5562_run_predef_led_pattern(struct lp55xx_chip *chip, int mode)
+{
+       struct lp55xx_predef_pattern *ptn;
+       int i;
+
+       if (mode == LP5562_PATTERN_OFF) {
+               lp5562_run_engine(chip, false);
+               return 0;
+       }
+
+       ptn = chip->pdata->patterns + (mode - 1);
+       if (!ptn || _is_pc_overflow(ptn)) {
+               dev_err(&chip->cl->dev, "invalid pattern data\n");
+               return -EINVAL;
+       }
+
+       lp5562_stop_engine(chip);
+
+       /* Set LED map as RGB */
+       lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_RGB);
+
+       /* Load engines */
+       for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) {
+               chip->engine_idx = i;
+               lp5562_load_engine(chip);
+       }
+
+       /* Clear program registers */
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1, 0);
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1 + 1, 0);
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2, 0);
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2 + 1, 0);
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3, 0);
+       lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3 + 1, 0);
+
+       /* Program engines */
+       lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG1,
+                               ptn->r, ptn->size_r);
+       lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG2,
+                               ptn->g, ptn->size_g);
+       lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG3,
+                               ptn->b, ptn->size_b);
+
+       /* Run engines */
+       lp5562_run_engine(chip, true);
+
+       return 0;
+}
+
+static ssize_t lp5562_store_pattern(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       struct lp55xx_predef_pattern *ptn = chip->pdata->patterns;
+       int num_patterns = chip->pdata->num_patterns;
+       unsigned long mode;
+       int ret;
+
+       ret = kstrtoul(buf, 0, &mode);
+       if (ret)
+               return ret;
+
+       if (mode > num_patterns || !ptn)
+               return -EINVAL;
+
+       mutex_lock(&chip->lock);
+       ret = lp5562_run_predef_led_pattern(chip, mode);
+       mutex_unlock(&chip->lock);
+
+       if (ret)
+               return ret;
+
+       return len;
+}
+
+static ssize_t lp5562_store_engine_mux(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t len)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       u8 mask;
+       u8 val;
+
+       /* LED map
+        * R ... Engine 1 (fixed)
+        * G ... Engine 2 (fixed)
+        * B ... Engine 3 (fixed)
+        * W ... Engine 1 or 2 or 3
+        */
+
+       if (sysfs_streq(buf, "RGB")) {
+               mask = LP5562_ENG_FOR_RGB_M;
+               val = LP5562_ENG_SEL_RGB;
+       } else if (sysfs_streq(buf, "W")) {
+               enum lp55xx_engine_index idx = chip->engine_idx;
+
+               mask = LP5562_ENG_FOR_W_M;
+               switch (idx) {
+               case LP55XX_ENGINE_1:
+                       val = LP5562_ENG1_FOR_W;
+                       break;
+               case LP55XX_ENGINE_2:
+                       val = LP5562_ENG2_FOR_W;
+                       break;
+               case LP55XX_ENGINE_3:
+                       val = LP5562_ENG3_FOR_W;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+       } else {
+               dev_err(dev, "choose RGB or W\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&chip->lock);
+       lp55xx_update_bits(chip, LP5562_REG_ENG_SEL, mask, val);
+       mutex_unlock(&chip->lock);
+
+       return len;
+}
+
+static LP55XX_DEV_ATTR_WO(led_pattern, lp5562_store_pattern);
+static LP55XX_DEV_ATTR_WO(engine_mux, lp5562_store_engine_mux);
+
+static struct attribute *lp5562_attributes[] = {
+       &dev_attr_led_pattern.attr,
+       &dev_attr_engine_mux.attr,
+       NULL,
+};
+
+static const struct attribute_group lp5562_group = {
+       .attrs = lp5562_attributes,
+};
+
+/* Chip specific configurations */
+static struct lp55xx_device_config lp5562_cfg = {
+       .max_channel  = LP5562_MAX_LEDS,
+       .reset = {
+               .addr = LP5562_REG_RESET,
+               .val  = LP5562_RESET,
+       },
+       .enable = {
+               .addr = LP5562_REG_ENABLE,
+               .val  = LP5562_ENABLE_DEFAULT,
+       },
+       .post_init_device   = lp5562_post_init_device,
+       .set_led_current    = lp5562_set_led_current,
+       .brightness_work_fn = lp5562_led_brightness_work,
+       .run_engine         = lp5562_run_engine,
+       .firmware_cb        = lp5562_firmware_loaded,
+       .dev_attr_group     = &lp5562_group,
+};
+
+static int lp5562_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int ret;
+       struct lp55xx_chip *chip;
+       struct lp55xx_led *led;
+       struct lp55xx_platform_data *pdata;
+       struct device_node *np = client->dev.of_node;
+
+       if (!dev_get_platdata(&client->dev)) {
+               if (np) {
+                       ret = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (ret < 0)
+                               return ret;
+               } else {
+                       dev_err(&client->dev, "no platform data\n");
+                       return -EINVAL;
+               }
+       }
+       pdata = dev_get_platdata(&client->dev);
+
+       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       led = devm_kzalloc(&client->dev,
+                       sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+       if (!led)
+               return -ENOMEM;
+
+       chip->cl = client;
+       chip->pdata = pdata;
+       chip->cfg = &lp5562_cfg;
+
+       mutex_init(&chip->lock);
+
+       i2c_set_clientdata(client, led);
+
+       ret = lp55xx_init_device(chip);
+       if (ret)
+               goto err_init;
+
+       ret = lp55xx_register_leds(led, chip);
+       if (ret)
+               goto err_register_leds;
+
+       ret = lp55xx_register_sysfs(chip);
+       if (ret) {
+               dev_err(&client->dev, "registering sysfs failed\n");
+               goto err_register_sysfs;
+       }
+
+       return 0;
+
+err_register_sysfs:
+       lp55xx_unregister_leds(led, chip);
+err_register_leds:
+       lp55xx_deinit_device(chip);
+err_init:
+       return ret;
+}
+
+static int lp5562_remove(struct i2c_client *client)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(client);
+       struct lp55xx_chip *chip = led->chip;
+
+       lp5562_stop_engine(chip);
+
+       lp55xx_unregister_sysfs(chip);
+       lp55xx_unregister_leds(led, chip);
+       lp55xx_deinit_device(chip);
+
+       return 0;
+}
+
+static const struct i2c_device_id lp5562_id[] = {
+       { "lp5562", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp5562_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_lp5562_leds_match[] = {
+       { .compatible = "ti,lp5562", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, of_lp5562_leds_match);
+#endif
+
+static struct i2c_driver lp5562_driver = {
+       .driver = {
+               .name   = "lp5562",
+               .of_match_table = of_match_ptr(of_lp5562_leds_match),
+       },
+       .probe          = lp5562_probe,
+       .remove         = lp5562_remove,
+       .id_table       = lp5562_id,
+};
+
+module_i2c_driver(lp5562_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP5562 LED Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
new file mode 100644 (file)
index 0000000..88317b4
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ * LP5521/LP5523/LP55231/LP5562 Common Driver
+ *
+ * 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.
+ *
+ * Derived from leds-lp5521.c, leds-lp5523.c
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_data/leds-lp55xx.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "leds-lp55xx-common.h"
+
+/* External clock rate */
+#define LP55XX_CLK_32K                 32768
+
+static struct lp55xx_led *cdev_to_lp55xx_led(struct led_classdev *cdev)
+{
+       return container_of(cdev, struct lp55xx_led, cdev);
+}
+
+static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
+{
+       return cdev_to_lp55xx_led(dev_get_drvdata(dev));
+}
+
+static void lp55xx_reset_device(struct lp55xx_chip *chip)
+{
+       struct lp55xx_device_config *cfg = chip->cfg;
+       u8 addr = cfg->reset.addr;
+       u8 val  = cfg->reset.val;
+
+       /* no error checking here because no ACK from the device after reset */
+       lp55xx_write(chip, addr, val);
+}
+
+static int lp55xx_detect_device(struct lp55xx_chip *chip)
+{
+       struct lp55xx_device_config *cfg = chip->cfg;
+       u8 addr = cfg->enable.addr;
+       u8 val  = cfg->enable.val;
+       int ret;
+
+       ret = lp55xx_write(chip, addr, val);
+       if (ret)
+               return ret;
+
+       usleep_range(1000, 2000);
+
+       ret = lp55xx_read(chip, addr, &val);
+       if (ret)
+               return ret;
+
+       if (val != cfg->enable.val)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int lp55xx_post_init_device(struct lp55xx_chip *chip)
+{
+       struct lp55xx_device_config *cfg = chip->cfg;
+
+       if (!cfg->post_init_device)
+               return 0;
+
+       return cfg->post_init_device(chip);
+}
+
+static ssize_t lp55xx_show_current(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+       struct lp55xx_led *led = dev_to_lp55xx_led(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current);
+}
+
+static ssize_t lp55xx_store_current(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t len)
+{
+       struct lp55xx_led *led = dev_to_lp55xx_led(dev);
+       struct lp55xx_chip *chip = led->chip;
+       unsigned long curr;
+
+       if (kstrtoul(buf, 0, &curr))
+               return -EINVAL;
+
+       if (curr > led->max_current)
+               return -EINVAL;
+
+       if (!chip->cfg->set_led_current)
+               return len;
+
+       mutex_lock(&chip->lock);
+       chip->cfg->set_led_current(led, (u8)curr);
+       mutex_unlock(&chip->lock);
+
+       return len;
+}
+
+static ssize_t lp55xx_show_max_current(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+       struct lp55xx_led *led = dev_to_lp55xx_led(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current);
+}
+
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current,
+               lp55xx_store_current);
+static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL);
+
+static struct attribute *lp55xx_led_attributes[] = {
+       &dev_attr_led_current.attr,
+       &dev_attr_max_current.attr,
+       NULL,
+};
+
+static struct attribute_group lp55xx_led_attr_group = {
+       .attrs = lp55xx_led_attributes
+};
+
+static void lp55xx_set_brightness(struct led_classdev *cdev,
+                            enum led_brightness brightness)
+{
+       struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);
+
+       led->brightness = (u8)brightness;
+       schedule_work(&led->brightness_work);
+}
+
+static int lp55xx_init_led(struct lp55xx_led *led,
+                       struct lp55xx_chip *chip, int chan)
+{
+       struct lp55xx_platform_data *pdata = chip->pdata;
+       struct lp55xx_device_config *cfg = chip->cfg;
+       struct device *dev = &chip->cl->dev;
+       char name[32];
+       int ret;
+       int max_channel = cfg->max_channel;
+
+       if (chan >= max_channel) {
+               dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
+               return -EINVAL;
+       }
+
+       if (pdata->led_config[chan].led_current == 0)
+               return 0;
+
+       led->led_current = pdata->led_config[chan].led_current;
+       led->max_current = pdata->led_config[chan].max_current;
+       led->chan_nr = pdata->led_config[chan].chan_nr;
+       led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
+
+       if (led->chan_nr >= max_channel) {
+               dev_err(dev, "Use channel numbers between 0 and %d\n",
+                       max_channel - 1);
+               return -EINVAL;
+       }
+
+       led->cdev.brightness_set = lp55xx_set_brightness;
+
+       if (pdata->led_config[chan].name) {
+               led->cdev.name = pdata->led_config[chan].name;
+       } else {
+               snprintf(name, sizeof(name), "%s:channel%d",
+                       pdata->label ? : chip->cl->name, chan);
+               led->cdev.name = name;
+       }
+
+       /*
+        * register led class device for each channel and
+        * add device attributes
+        */
+
+       ret = led_classdev_register(dev, &led->cdev);
+       if (ret) {
+               dev_err(dev, "led register err: %d\n", ret);
+               return ret;
+       }
+
+       ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group);
+       if (ret) {
+               dev_err(dev, "led sysfs err: %d\n", ret);
+               led_classdev_unregister(&led->cdev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
+{
+       struct lp55xx_chip *chip = context;
+       struct device *dev = &chip->cl->dev;
+       enum lp55xx_engine_index idx = chip->engine_idx;
+
+       if (!fw) {
+               dev_err(dev, "firmware request failed\n");
+               goto out;
+       }
+
+       /* handling firmware data is chip dependent */
+       mutex_lock(&chip->lock);
+
+       chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD;
+       chip->fw = fw;
+       if (chip->cfg->firmware_cb)
+               chip->cfg->firmware_cb(chip);
+
+       mutex_unlock(&chip->lock);
+
+out:
+       /* firmware should be released for other channel use */
+       release_firmware(chip->fw);
+}
+
+static int lp55xx_request_firmware(struct lp55xx_chip *chip)
+{
+       const char *name = chip->cl->name;
+       struct device *dev = &chip->cl->dev;
+
+       return request_firmware_nowait(THIS_MODULE, true, name, dev,
+                               GFP_KERNEL, chip, lp55xx_firmware_loaded);
+}
+
+static ssize_t lp55xx_show_engine_select(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+
+       return sprintf(buf, "%d\n", chip->engine_idx);
+}
+
+static ssize_t lp55xx_store_engine_select(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t len)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       unsigned long val;
+       int ret;
+
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       /* select the engine to be run */
+
+       switch (val) {
+       case LP55XX_ENGINE_1:
+       case LP55XX_ENGINE_2:
+       case LP55XX_ENGINE_3:
+               mutex_lock(&chip->lock);
+               chip->engine_idx = val;
+               ret = lp55xx_request_firmware(chip);
+               mutex_unlock(&chip->lock);
+               break;
+       default:
+               dev_err(dev, "%lu: invalid engine index. (1, 2, 3)\n", val);
+               return -EINVAL;
+       }
+
+       if (ret) {
+               dev_err(dev, "request firmware err: %d\n", ret);
+               return ret;
+       }
+
+       return len;
+}
+
+static inline void lp55xx_run_engine(struct lp55xx_chip *chip, bool start)
+{
+       if (chip->cfg->run_engine)
+               chip->cfg->run_engine(chip, start);
+}
+
+static ssize_t lp55xx_store_engine_run(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t len)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       unsigned long val;
+
+       if (kstrtoul(buf, 0, &val))
+               return -EINVAL;
+
+       /* run or stop the selected engine */
+
+       if (val <= 0) {
+               lp55xx_run_engine(chip, false);
+               return len;
+       }
+
+       mutex_lock(&chip->lock);
+       lp55xx_run_engine(chip, true);
+       mutex_unlock(&chip->lock);
+
+       return len;
+}
+
+static DEVICE_ATTR(select_engine, S_IRUGO | S_IWUSR,
+                  lp55xx_show_engine_select, lp55xx_store_engine_select);
+static DEVICE_ATTR(run_engine, S_IWUSR, NULL, lp55xx_store_engine_run);
+
+static struct attribute *lp55xx_engine_attributes[] = {
+       &dev_attr_select_engine.attr,
+       &dev_attr_run_engine.attr,
+       NULL,
+};
+
+static const struct attribute_group lp55xx_engine_attr_group = {
+       .attrs = lp55xx_engine_attributes,
+};
+
+int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val)
+{
+       return i2c_smbus_write_byte_data(chip->cl, reg, val);
+}
+EXPORT_SYMBOL_GPL(lp55xx_write);
+
+int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val)
+{
+       s32 ret;
+
+       ret = i2c_smbus_read_byte_data(chip->cl, reg);
+       if (ret < 0)
+               return ret;
+
+       *val = ret;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lp55xx_read);
+
+int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg, u8 mask, u8 val)
+{
+       int ret;
+       u8 tmp;
+
+       ret = lp55xx_read(chip, reg, &tmp);
+       if (ret)
+               return ret;
+
+       tmp &= ~mask;
+       tmp |= val & mask;
+
+       return lp55xx_write(chip, reg, tmp);
+}
+EXPORT_SYMBOL_GPL(lp55xx_update_bits);
+
+bool lp55xx_is_extclk_used(struct lp55xx_chip *chip)
+{
+       struct clk *clk;
+       int err;
+
+       clk = devm_clk_get(&chip->cl->dev, "32k_clk");
+       if (IS_ERR(clk))
+               goto use_internal_clk;
+
+       err = clk_prepare_enable(clk);
+       if (err)
+               goto use_internal_clk;
+
+       if (clk_get_rate(clk) != LP55XX_CLK_32K) {
+               clk_disable_unprepare(clk);
+               goto use_internal_clk;
+       }
+
+       dev_info(&chip->cl->dev, "%dHz external clock used\n",  LP55XX_CLK_32K);
+
+       chip->clk = clk;
+       return true;
+
+use_internal_clk:
+       dev_info(&chip->cl->dev, "internal clock used\n");
+       return false;
+}
+EXPORT_SYMBOL_GPL(lp55xx_is_extclk_used);
+
+int lp55xx_init_device(struct lp55xx_chip *chip)
+{
+       struct lp55xx_platform_data *pdata;
+       struct lp55xx_device_config *cfg;
+       struct device *dev = &chip->cl->dev;
+       int ret = 0;
+
+       WARN_ON(!chip);
+
+       pdata = chip->pdata;
+       cfg = chip->cfg;
+
+       if (!pdata || !cfg)
+               return -EINVAL;
+
+       if (gpio_is_valid(pdata->enable_gpio)) {
+               ret = devm_gpio_request_one(dev, pdata->enable_gpio,
+                                           GPIOF_DIR_OUT, "lp5523_enable");
+               if (ret < 0) {
+                       dev_err(dev, "could not acquire enable gpio (err=%d)\n",
+                               ret);
+                       goto err;
+               }
+
+               gpio_set_value(pdata->enable_gpio, 0);
+               usleep_range(1000, 2000); /* Keep enable down at least 1ms */
+               gpio_set_value(pdata->enable_gpio, 1);
+               usleep_range(1000, 2000); /* 500us abs min. */
+       }
+
+       lp55xx_reset_device(chip);
+
+       /*
+        * Exact value is not available. 10 - 20ms
+        * appears to be enough for reset.
+        */
+       usleep_range(10000, 20000);
+
+       ret = lp55xx_detect_device(chip);
+       if (ret) {
+               dev_err(dev, "device detection err: %d\n", ret);
+               goto err;
+       }
+
+       /* chip specific initialization */
+       ret = lp55xx_post_init_device(chip);
+       if (ret) {
+               dev_err(dev, "post init device err: %d\n", ret);
+               goto err_post_init;
+       }
+
+       return 0;
+
+err_post_init:
+       lp55xx_deinit_device(chip);
+err:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(lp55xx_init_device);
+
+void lp55xx_deinit_device(struct lp55xx_chip *chip)
+{
+       struct lp55xx_platform_data *pdata = chip->pdata;
+
+       if (chip->clk)
+               clk_disable_unprepare(chip->clk);
+
+       if (gpio_is_valid(pdata->enable_gpio))
+               gpio_set_value(pdata->enable_gpio, 0);
+}
+EXPORT_SYMBOL_GPL(lp55xx_deinit_device);
+
+int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
+{
+       struct lp55xx_platform_data *pdata = chip->pdata;
+       struct lp55xx_device_config *cfg = chip->cfg;
+       int num_channels = pdata->num_channels;
+       struct lp55xx_led *each;
+       u8 led_current;
+       int ret;
+       int i;
+
+       if (!cfg->brightness_work_fn) {
+               dev_err(&chip->cl->dev, "empty brightness configuration\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_channels; i++) {
+
+               /* do not initialize channels that are not connected */
+               if (pdata->led_config[i].led_current == 0)
+                       continue;
+
+               led_current = pdata->led_config[i].led_current;
+               each = led + i;
+               ret = lp55xx_init_led(each, chip, i);
+               if (ret)
+                       goto err_init_led;
+
+               INIT_WORK(&each->brightness_work, cfg->brightness_work_fn);
+
+               chip->num_leds++;
+               each->chip = chip;
+
+               /* setting led current at each channel */
+               if (cfg->set_led_current)
+                       cfg->set_led_current(each, led_current);
+       }
+
+       return 0;
+
+err_init_led:
+       lp55xx_unregister_leds(led, chip);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(lp55xx_register_leds);
+
+void lp55xx_unregister_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
+{
+       int i;
+       struct lp55xx_led *each;
+
+       for (i = 0; i < chip->num_leds; i++) {
+               each = led + i;
+               led_classdev_unregister(&each->cdev);
+               flush_work(&each->brightness_work);
+       }
+}
+EXPORT_SYMBOL_GPL(lp55xx_unregister_leds);
+
+int lp55xx_register_sysfs(struct lp55xx_chip *chip)
+{
+       struct device *dev = &chip->cl->dev;
+       struct lp55xx_device_config *cfg = chip->cfg;
+       int ret;
+
+       if (!cfg->run_engine || !cfg->firmware_cb)
+               goto dev_specific_attrs;
+
+       ret = sysfs_create_group(&dev->kobj, &lp55xx_engine_attr_group);
+       if (ret)
+               return ret;
+
+dev_specific_attrs:
+       return cfg->dev_attr_group ?
+               sysfs_create_group(&dev->kobj, cfg->dev_attr_group) : 0;
+}
+EXPORT_SYMBOL_GPL(lp55xx_register_sysfs);
+
+void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
+{
+       struct device *dev = &chip->cl->dev;
+       struct lp55xx_device_config *cfg = chip->cfg;
+
+       if (cfg->dev_attr_group)
+               sysfs_remove_group(&dev->kobj, cfg->dev_attr_group);
+
+       sysfs_remove_group(&dev->kobj, &lp55xx_engine_attr_group);
+}
+EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
+
+int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
+{
+       struct device_node *child;
+       struct lp55xx_platform_data *pdata;
+       struct lp55xx_led_config *cfg;
+       int num_channels;
+       int i = 0;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       num_channels = of_get_child_count(np);
+       if (num_channels == 0) {
+               dev_err(dev, "no LED channels\n");
+               return -EINVAL;
+       }
+
+       cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL);
+       if (!cfg)
+               return -ENOMEM;
+
+       pdata->led_config = &cfg[0];
+       pdata->num_channels = num_channels;
+
+       for_each_child_of_node(np, child) {
+               cfg[i].chan_nr = i;
+
+               of_property_read_string(child, "chan-name", &cfg[i].name);
+               of_property_read_u8(child, "led-cur", &cfg[i].led_current);
+               of_property_read_u8(child, "max-cur", &cfg[i].max_current);
+               cfg[i].default_trigger =
+                       of_get_property(child, "linux,default-trigger", NULL);
+
+               i++;
+       }
+
+       of_property_read_string(np, "label", &pdata->label);
+       of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
+
+       pdata->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+       /* LP8501 specific */
+       of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
+
+       dev->platform_data = pdata;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
+
+MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
+MODULE_DESCRIPTION("LP55xx Common Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h
new file mode 100644 (file)
index 0000000..cceab48
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * LP55XX Common Driver Header
+ *
+ * Copyright (C) 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.
+ *
+ * Derived from leds-lp5521.c, leds-lp5523.c
+ */
+
+#ifndef _LEDS_LP55XX_COMMON_H
+#define _LEDS_LP55XX_COMMON_H
+
+enum lp55xx_engine_index {
+       LP55XX_ENGINE_INVALID,
+       LP55XX_ENGINE_1,
+       LP55XX_ENGINE_2,
+       LP55XX_ENGINE_3,
+       LP55XX_ENGINE_MAX = LP55XX_ENGINE_3,
+};
+
+enum lp55xx_engine_mode {
+       LP55XX_ENGINE_DISABLED,
+       LP55XX_ENGINE_LOAD,
+       LP55XX_ENGINE_RUN,
+};
+
+#define LP55XX_DEV_ATTR_RW(name, show, store)  \
+       DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show, store)
+#define LP55XX_DEV_ATTR_RO(name, show)         \
+       DEVICE_ATTR(name, S_IRUGO, show, NULL)
+#define LP55XX_DEV_ATTR_WO(name, store)                \
+       DEVICE_ATTR(name, S_IWUSR, NULL, store)
+
+#define show_mode(nr)                                                  \
+static ssize_t show_engine##nr##_mode(struct device *dev,              \
+                                   struct device_attribute *attr,      \
+                                   char *buf)                          \
+{                                                                      \
+       return show_engine_mode(dev, attr, buf, nr);                    \
+}
+
+#define store_mode(nr)                                                 \
+static ssize_t store_engine##nr##_mode(struct device *dev,             \
+                                    struct device_attribute *attr,     \
+                                    const char *buf, size_t len)       \
+{                                                                      \
+       return store_engine_mode(dev, attr, buf, len, nr);              \
+}
+
+#define show_leds(nr)                                                  \
+static ssize_t show_engine##nr##_leds(struct device *dev,              \
+                           struct device_attribute *attr,              \
+                           char *buf)                                  \
+{                                                                      \
+       return show_engine_leds(dev, attr, buf, nr);                    \
+}
+
+#define store_leds(nr)                                         \
+static ssize_t store_engine##nr##_leds(struct device *dev,     \
+                            struct device_attribute *attr,     \
+                            const char *buf, size_t len)       \
+{                                                              \
+       return store_engine_leds(dev, attr, buf, len, nr);      \
+}
+
+#define store_load(nr)                                                 \
+static ssize_t store_engine##nr##_load(struct device *dev,             \
+                                    struct device_attribute *attr,     \
+                                    const char *buf, size_t len)       \
+{                                                                      \
+       return store_engine_load(dev, attr, buf, len, nr);              \
+}
+
+struct lp55xx_led;
+struct lp55xx_chip;
+
+/*
+ * struct lp55xx_reg
+ * @addr : Register address
+ * @val  : Register value
+ */
+struct lp55xx_reg {
+       u8 addr;
+       u8 val;
+};
+
+/*
+ * struct lp55xx_device_config
+ * @reset              : Chip specific reset command
+ * @enable             : Chip specific enable command
+ * @max_channel        : Maximum number of channels
+ * @post_init_device   : Chip specific initialization code
+ * @brightness_work_fn : Brightness work function
+ * @set_led_current    : LED current set function
+ * @firmware_cb        : Call function when the firmware is loaded
+ * @run_engine         : Run internal engine for pattern
+ * @dev_attr_group     : Device specific attributes
+ */
+struct lp55xx_device_config {
+       const struct lp55xx_reg reset;
+       const struct lp55xx_reg enable;
+       const int max_channel;
+
+       /* define if the device has specific initialization process */
+       int (*post_init_device) (struct lp55xx_chip *chip);
+
+       /* access brightness register */
+       void (*brightness_work_fn)(struct work_struct *work);
+
+       /* current setting function */
+       void (*set_led_current) (struct lp55xx_led *led, u8 led_current);
+
+       /* access program memory when the firmware is loaded */
+       void (*firmware_cb)(struct lp55xx_chip *chip);
+
+       /* used for running firmware LED patterns */
+       void (*run_engine) (struct lp55xx_chip *chip, bool start);
+
+       /* additional device specific attributes */
+       const struct attribute_group *dev_attr_group;
+};
+
+/*
+ * struct lp55xx_engine
+ * @mode       : Engine mode
+ * @led_mux    : Mux bits for LED selection. Only used in LP5523
+ */
+struct lp55xx_engine {
+       enum lp55xx_engine_mode mode;
+       u16 led_mux;
+};
+
+/*
+ * struct lp55xx_chip
+ * @cl         : I2C communication for access registers
+ * @pdata      : Platform specific data
+ * @lock       : Lock for user-space interface
+ * @num_leds   : Number of registered LEDs
+ * @cfg        : Device specific configuration data
+ * @engine_idx : Selected engine number
+ * @engines    : Engine structure for the device attribute R/W interface
+ * @fw         : Firmware data for running a LED pattern
+ */
+struct lp55xx_chip {
+       struct i2c_client *cl;
+       struct clk *clk;
+       struct lp55xx_platform_data *pdata;
+       struct mutex lock;      /* lock for user-space interface */
+       int num_leds;
+       struct lp55xx_device_config *cfg;
+       enum lp55xx_engine_index engine_idx;
+       struct lp55xx_engine engines[LP55XX_ENGINE_MAX];
+       const struct firmware *fw;
+};
+
+/*
+ * struct lp55xx_led
+ * @chan_nr         : Channel number
+ * @cdev            : LED class device
+ * @led_current     : Current setting at each led channel
+ * @max_current     : Maximun current at each led channel
+ * @brightness_work : Workqueue for brightness control
+ * @brightness      : Brightness value
+ * @chip            : The lp55xx chip data
+ */
+struct lp55xx_led {
+       int chan_nr;
+       struct led_classdev cdev;
+       u8 led_current;
+       u8 max_current;
+       struct work_struct brightness_work;
+       u8 brightness;
+       struct lp55xx_chip *chip;
+};
+
+/* register access */
+extern int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val);
+extern int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val);
+extern int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg,
+                       u8 mask, u8 val);
+
+/* external clock detection */
+extern bool lp55xx_is_extclk_used(struct lp55xx_chip *chip);
+
+/* common device init/deinit functions */
+extern int lp55xx_init_device(struct lp55xx_chip *chip);
+extern void lp55xx_deinit_device(struct lp55xx_chip *chip);
+
+/* common LED class device functions */
+extern int lp55xx_register_leds(struct lp55xx_led *led,
+                               struct lp55xx_chip *chip);
+extern void lp55xx_unregister_leds(struct lp55xx_led *led,
+                               struct lp55xx_chip *chip);
+
+/* common device attributes functions */
+extern int lp55xx_register_sysfs(struct lp55xx_chip *chip);
+extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip);
+
+/* common device tree population function */
+extern int lp55xx_of_populate_pdata(struct device *dev,
+                                   struct device_node *np);
+
+#endif /* _LEDS_LP55XX_COMMON_H */
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
new file mode 100644 (file)
index 0000000..00f068b
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * TI LP8501 9 channel LED Driver
+ *
+ * Copyright (C) 2013 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/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_data/leds-lp55xx.h>
+#include <linux/slab.h>
+
+#include "leds-lp55xx-common.h"
+
+#define LP8501_PROGRAM_LENGTH          32
+#define LP8501_MAX_LEDS                        9
+
+/* Registers */
+#define LP8501_REG_ENABLE              0x00
+#define LP8501_ENABLE                  BIT(6)
+#define LP8501_EXEC_M                  0x3F
+#define LP8501_EXEC_ENG1_M             0x30
+#define LP8501_EXEC_ENG2_M             0x0C
+#define LP8501_EXEC_ENG3_M             0x03
+#define LP8501_RUN_ENG1                        0x20
+#define LP8501_RUN_ENG2                        0x08
+#define LP8501_RUN_ENG3                        0x02
+
+#define LP8501_REG_OP_MODE             0x01
+#define LP8501_MODE_ENG1_M             0x30
+#define LP8501_MODE_ENG2_M             0x0C
+#define LP8501_MODE_ENG3_M             0x03
+#define LP8501_LOAD_ENG1               0x10
+#define LP8501_LOAD_ENG2               0x04
+#define LP8501_LOAD_ENG3               0x01
+
+#define LP8501_REG_PWR_CONFIG          0x05
+#define LP8501_PWR_CONFIG_M            0x03
+
+#define LP8501_REG_LED_PWM_BASE                0x16
+
+#define LP8501_REG_LED_CURRENT_BASE    0x26
+
+#define LP8501_REG_CONFIG              0x36
+#define LP8501_PWM_PSAVE               BIT(7)
+#define LP8501_AUTO_INC                        BIT(6)
+#define LP8501_PWR_SAVE                        BIT(5)
+#define LP8501_CP_AUTO                 0x18
+#define LP8501_INT_CLK                 BIT(0)
+#define LP8501_DEFAULT_CFG     \
+       (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO)
+
+#define LP8501_REG_RESET               0x3D
+#define LP8501_RESET                   0xFF
+
+#define LP8501_REG_PROG_PAGE_SEL       0x4F
+#define LP8501_PAGE_ENG1               0
+#define LP8501_PAGE_ENG2               1
+#define LP8501_PAGE_ENG3               2
+
+#define LP8501_REG_PROG_MEM            0x50
+
+#define LP8501_ENG1_IS_LOADING(mode)   \
+       ((mode & LP8501_MODE_ENG1_M) == LP8501_LOAD_ENG1)
+#define LP8501_ENG2_IS_LOADING(mode)   \
+       ((mode & LP8501_MODE_ENG2_M) == LP8501_LOAD_ENG2)
+#define LP8501_ENG3_IS_LOADING(mode)   \
+       ((mode & LP8501_MODE_ENG3_M) == LP8501_LOAD_ENG3)
+
+static inline void lp8501_wait_opmode_done(void)
+{
+       usleep_range(1000, 2000);
+}
+
+static void lp8501_set_led_current(struct lp55xx_led *led, u8 led_current)
+{
+       led->led_current = led_current;
+       lp55xx_write(led->chip, LP8501_REG_LED_CURRENT_BASE + led->chan_nr,
+               led_current);
+}
+
+static int lp8501_post_init_device(struct lp55xx_chip *chip)
+{
+       int ret;
+       u8 val = LP8501_DEFAULT_CFG;
+
+       ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE);
+       if (ret)
+               return ret;
+
+       /* Chip startup time is 500 us, 1 - 2 ms gives some margin */
+       usleep_range(1000, 2000);
+
+       if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT)
+               val |= LP8501_INT_CLK;
+
+       ret = lp55xx_write(chip, LP8501_REG_CONFIG, val);
+       if (ret)
+               return ret;
+
+       /* Power selection for each output */
+       return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG,
+                               LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel);
+}
+
+static void lp8501_load_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M,
+               [LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M,
+               [LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M,
+       };
+
+       u8 val[] = {
+               [LP55XX_ENGINE_1] = LP8501_LOAD_ENG1,
+               [LP55XX_ENGINE_2] = LP8501_LOAD_ENG2,
+               [LP55XX_ENGINE_3] = LP8501_LOAD_ENG3,
+       };
+
+       u8 page_sel[] = {
+               [LP55XX_ENGINE_1] = LP8501_PAGE_ENG1,
+               [LP55XX_ENGINE_2] = LP8501_PAGE_ENG2,
+               [LP55XX_ENGINE_3] = LP8501_PAGE_ENG3,
+       };
+
+       lp55xx_update_bits(chip, LP8501_REG_OP_MODE, mask[idx], val[idx]);
+
+       lp8501_wait_opmode_done();
+
+       lp55xx_write(chip, LP8501_REG_PROG_PAGE_SEL, page_sel[idx]);
+}
+
+static void lp8501_stop_engine(struct lp55xx_chip *chip)
+{
+       lp55xx_write(chip, LP8501_REG_OP_MODE, 0);
+       lp8501_wait_opmode_done();
+}
+
+static void lp8501_turn_off_channels(struct lp55xx_chip *chip)
+{
+       int i;
+
+       for (i = 0; i < LP8501_MAX_LEDS; i++)
+               lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + i, 0);
+}
+
+static void lp8501_run_engine(struct lp55xx_chip *chip, bool start)
+{
+       int ret;
+       u8 mode;
+       u8 exec;
+
+       /* stop engine */
+       if (!start) {
+               lp8501_stop_engine(chip);
+               lp8501_turn_off_channels(chip);
+               return;
+       }
+
+       /*
+        * To run the engine,
+        * operation mode and enable register should updated at the same time
+        */
+
+       ret = lp55xx_read(chip, LP8501_REG_OP_MODE, &mode);
+       if (ret)
+               return;
+
+       ret = lp55xx_read(chip, LP8501_REG_ENABLE, &exec);
+       if (ret)
+               return;
+
+       /* change operation mode to RUN only when each engine is loading */
+       if (LP8501_ENG1_IS_LOADING(mode)) {
+               mode = (mode & ~LP8501_MODE_ENG1_M) | LP8501_RUN_ENG1;
+               exec = (exec & ~LP8501_EXEC_ENG1_M) | LP8501_RUN_ENG1;
+       }
+
+       if (LP8501_ENG2_IS_LOADING(mode)) {
+               mode = (mode & ~LP8501_MODE_ENG2_M) | LP8501_RUN_ENG2;
+               exec = (exec & ~LP8501_EXEC_ENG2_M) | LP8501_RUN_ENG2;
+       }
+
+       if (LP8501_ENG3_IS_LOADING(mode)) {
+               mode = (mode & ~LP8501_MODE_ENG3_M) | LP8501_RUN_ENG3;
+               exec = (exec & ~LP8501_EXEC_ENG3_M) | LP8501_RUN_ENG3;
+       }
+
+       lp55xx_write(chip, LP8501_REG_OP_MODE, mode);
+       lp8501_wait_opmode_done();
+
+       lp55xx_update_bits(chip, LP8501_REG_ENABLE, LP8501_EXEC_M, exec);
+}
+
+static int lp8501_update_program_memory(struct lp55xx_chip *chip,
+                                       const u8 *data, size_t size)
+{
+       u8 pattern[LP8501_PROGRAM_LENGTH] = {0};
+       unsigned cmd;
+       char c[3];
+       int update_size;
+       int nrchars;
+       int offset = 0;
+       int ret;
+       int i;
+
+       /* clear program memory before updating */
+       for (i = 0; i < LP8501_PROGRAM_LENGTH; i++)
+               lp55xx_write(chip, LP8501_REG_PROG_MEM + i, 0);
+
+       i = 0;
+       while ((offset < size - 1) && (i < LP8501_PROGRAM_LENGTH)) {
+               /* separate sscanfs because length is working only for %s */
+               ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
+               if (ret != 1)
+                       goto err;
+
+               ret = sscanf(c, "%2x", &cmd);
+               if (ret != 1)
+                       goto err;
+
+               pattern[i] = (u8)cmd;
+               offset += nrchars;
+               i++;
+       }
+
+       /* Each instruction is 16bit long. Check that length is even */
+       if (i % 2)
+               goto err;
+
+       update_size = i;
+       for (i = 0; i < update_size; i++)
+               lp55xx_write(chip, LP8501_REG_PROG_MEM + i, pattern[i]);
+
+       return 0;
+
+err:
+       dev_err(&chip->cl->dev, "wrong pattern format\n");
+       return -EINVAL;
+}
+
+static void lp8501_firmware_loaded(struct lp55xx_chip *chip)
+{
+       const struct firmware *fw = chip->fw;
+
+       if (fw->size > LP8501_PROGRAM_LENGTH) {
+               dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
+                       fw->size);
+               return;
+       }
+
+       /*
+        * Program memory sequence
+        *  1) set engine mode to "LOAD"
+        *  2) write firmware data into program memory
+        */
+
+       lp8501_load_engine(chip);
+       lp8501_update_program_memory(chip, fw->data, fw->size);
+}
+
+static void lp8501_led_brightness_work(struct work_struct *work)
+{
+       struct lp55xx_led *led = container_of(work, struct lp55xx_led,
+                                             brightness_work);
+       struct lp55xx_chip *chip = led->chip;
+
+       mutex_lock(&chip->lock);
+       lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
+                    led->brightness);
+       mutex_unlock(&chip->lock);
+}
+
+/* Chip specific configurations */
+static struct lp55xx_device_config lp8501_cfg = {
+       .reset = {
+               .addr = LP8501_REG_RESET,
+               .val  = LP8501_RESET,
+       },
+       .enable = {
+               .addr = LP8501_REG_ENABLE,
+               .val  = LP8501_ENABLE,
+       },
+       .max_channel  = LP8501_MAX_LEDS,
+       .post_init_device   = lp8501_post_init_device,
+       .brightness_work_fn = lp8501_led_brightness_work,
+       .set_led_current    = lp8501_set_led_current,
+       .firmware_cb        = lp8501_firmware_loaded,
+       .run_engine         = lp8501_run_engine,
+};
+
+static int lp8501_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int ret;
+       struct lp55xx_chip *chip;
+       struct lp55xx_led *led;
+       struct lp55xx_platform_data *pdata;
+       struct device_node *np = client->dev.of_node;
+
+       if (!dev_get_platdata(&client->dev)) {
+               if (np) {
+                       ret = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (ret < 0)
+                               return ret;
+               } else {
+                       dev_err(&client->dev, "no platform data\n");
+                       return -EINVAL;
+               }
+       }
+       pdata = dev_get_platdata(&client->dev);
+
+       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       led = devm_kzalloc(&client->dev,
+                       sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+       if (!led)
+               return -ENOMEM;
+
+       chip->cl = client;
+       chip->pdata = pdata;
+       chip->cfg = &lp8501_cfg;
+
+       mutex_init(&chip->lock);
+
+       i2c_set_clientdata(client, led);
+
+       ret = lp55xx_init_device(chip);
+       if (ret)
+               goto err_init;
+
+       dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
+
+       ret = lp55xx_register_leds(led, chip);
+       if (ret)
+               goto err_register_leds;
+
+       ret = lp55xx_register_sysfs(chip);
+       if (ret) {
+               dev_err(&client->dev, "registering sysfs failed\n");
+               goto err_register_sysfs;
+       }
+
+       return 0;
+
+err_register_sysfs:
+       lp55xx_unregister_leds(led, chip);
+err_register_leds:
+       lp55xx_deinit_device(chip);
+err_init:
+       return ret;
+}
+
+static int lp8501_remove(struct i2c_client *client)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(client);
+       struct lp55xx_chip *chip = led->chip;
+
+       lp8501_stop_engine(chip);
+       lp55xx_unregister_sysfs(chip);
+       lp55xx_unregister_leds(led, chip);
+       lp55xx_deinit_device(chip);
+
+       return 0;
+}
+
+static const struct i2c_device_id lp8501_id[] = {
+       { "lp8501",  0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp8501_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_lp8501_leds_match[] = {
+       { .compatible = "ti,lp8501", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, of_lp8501_leds_match);
+#endif
+
+static struct i2c_driver lp8501_driver = {
+       .driver = {
+               .name   = "lp8501",
+               .of_match_table = of_match_ptr(of_lp8501_leds_match),
+       },
+       .probe          = lp8501_probe,
+       .remove         = lp8501_remove,
+       .id_table       = lp8501_id,
+};
+
+module_i2c_driver(lp8501_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP8501 LED drvier");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
new file mode 100644 (file)
index 0000000..7c2cb38
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * TI LP8788 MFD - keyled driver
+ *
+ * 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/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/mutex.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/mfd/lp8788-isink.h>
+
+#define MAX_BRIGHTNESS                 LP8788_ISINK_MAX_PWM
+#define DEFAULT_LED_NAME               "keyboard-backlight"
+
+struct lp8788_led {
+       struct lp8788 *lp;
+       struct mutex lock;
+       struct work_struct work;
+       struct led_classdev led_dev;
+       enum lp8788_isink_number isink_num;
+       enum led_brightness brightness;
+       int on;
+};
+
+struct lp8788_led_config {
+       enum lp8788_isink_scale scale;
+       enum lp8788_isink_number num;
+       int iout;
+};
+
+static struct lp8788_led_config default_led_config = {
+       .scale = LP8788_ISINK_SCALE_100mA,
+       .num   = LP8788_ISINK_3,
+       .iout  = 0,
+};
+
+static int lp8788_led_init_device(struct lp8788_led *led,
+                               struct lp8788_led_platform_data *pdata)
+{
+       struct lp8788_led_config *cfg = &default_led_config;
+       u8 addr, mask, val;
+       int ret;
+
+       if (pdata) {
+               cfg->scale = pdata->scale;
+               cfg->num = pdata->num;
+               cfg->iout = pdata->iout_code;
+       }
+
+       led->isink_num = cfg->num;
+
+       /* scale configuration */
+       addr = LP8788_ISINK_CTRL;
+       mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
+       val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
+       ret = lp8788_update_bits(led->lp, addr, mask, val);
+       if (ret)
+               return ret;
+
+       /* current configuration */
+       addr = lp8788_iout_addr[cfg->num];
+       mask = lp8788_iout_mask[cfg->num];
+       val = cfg->iout;
+
+       return lp8788_update_bits(led->lp, addr, mask, val);
+}
+
+static void lp8788_led_enable(struct lp8788_led *led,
+                       enum lp8788_isink_number num, int on)
+{
+       u8 mask = 1 << num;
+       u8 val = on << num;
+
+       if (lp8788_update_bits(led->lp, LP8788_ISINK_CTRL, mask, val))
+               return;
+
+       led->on = on;
+}
+
+static void lp8788_led_work(struct work_struct *work)
+{
+       struct lp8788_led *led = container_of(work, struct lp8788_led, work);
+       enum lp8788_isink_number num = led->isink_num;
+       int enable;
+       u8 val = led->brightness;
+
+       mutex_lock(&led->lock);
+
+       switch (num) {
+       case LP8788_ISINK_1:
+       case LP8788_ISINK_2:
+       case LP8788_ISINK_3:
+               lp8788_write_byte(led->lp, lp8788_pwm_addr[num], val);
+               break;
+       default:
+               mutex_unlock(&led->lock);
+               return;
+       }
+
+       enable = (val > 0) ? 1 : 0;
+       if (enable != led->on)
+               lp8788_led_enable(led, num, enable);
+
+       mutex_unlock(&led->lock);
+}
+
+static void lp8788_brightness_set(struct led_classdev *led_cdev,
+                               enum led_brightness brt_val)
+{
+       struct lp8788_led *led =
+                       container_of(led_cdev, struct lp8788_led, led_dev);
+
+       led->brightness = brt_val;
+       schedule_work(&led->work);
+}
+
+static int lp8788_led_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       struct lp8788_led_platform_data *led_pdata;
+       struct lp8788_led *led;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       led = devm_kzalloc(dev, sizeof(struct lp8788_led), GFP_KERNEL);
+       if (!led)
+               return -ENOMEM;
+
+       led->lp = lp;
+       led->led_dev.max_brightness = MAX_BRIGHTNESS;
+       led->led_dev.brightness_set = lp8788_brightness_set;
+
+       led_pdata = lp->pdata ? lp->pdata->led_pdata : NULL;
+
+       if (!led_pdata || !led_pdata->name)
+               led->led_dev.name = DEFAULT_LED_NAME;
+       else
+               led->led_dev.name = led_pdata->name;
+
+       mutex_init(&led->lock);
+       INIT_WORK(&led->work, lp8788_led_work);
+
+       platform_set_drvdata(pdev, led);
+
+       ret = lp8788_led_init_device(led, led_pdata);
+       if (ret) {
+               dev_err(dev, "led init device err: %d\n", ret);
+               return ret;
+       }
+
+       ret = led_classdev_register(dev, &led->led_dev);
+       if (ret) {
+               dev_err(dev, "led register err: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int lp8788_led_remove(struct platform_device *pdev)
+{
+       struct lp8788_led *led = platform_get_drvdata(pdev);
+
+       led_classdev_unregister(&led->led_dev);
+       flush_work(&led->work);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_led_driver = {
+       .probe = lp8788_led_probe,
+       .remove = lp8788_led_remove,
+       .driver = {
+               .name = LP8788_DEV_KEYLED,
+               .owner = THIS_MODULE,
+       },
+};
+module_platform_driver(lp8788_led_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP8788 Keyboard LED Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-keyled");
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
new file mode 100644 (file)
index 0000000..4aa9c53
--- /dev/null
@@ -0,0 +1,698 @@
+#
+# Multimedia Video device configuration
+#
+
+if VIDEO_V4L2
+
+config VIDEO_IR_I2C
+       tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT
+       depends on I2C && RC_CORE
+       default y
+       ---help---
+         Most boards have an IR chip directly connected via GPIO. However,
+         some video boards have the IR connected via I2C bus.
+
+         If your board doesn't have an I2C IR chip, you may disable this
+         option.
+
+         In doubt, say Y.
+
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders, decoders, sensors and other helper chips"
+       visible if !MEDIA_SUBDRV_AUTOSELECT
+
+comment "Audio decoders, processors and mixers"
+
+config VIDEO_TVAUDIO
+       tristate "Simple audio decoder chips"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for several audio decoder chips found on some bt8xx boards:
+         Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
+                  tea6320, tea6420, tda8425, ta8874z.
+         Microchip: pic16c54 based design on ProVideo PV951 board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvaudio.
+
+config VIDEO_TDA7432
+       tristate "Philips TDA7432 audio processor"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for tda7432 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda7432.
+
+config VIDEO_TDA9840
+       tristate "Philips TDA9840 audio processor"
+       depends on I2C
+       ---help---
+         Support for tda9840 audio decoder chip found on some Zoran boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda9840.
+
+config VIDEO_TEA6415C
+       tristate "Philips TEA6415C audio processor"
+       depends on I2C
+       ---help---
+         Support for tea6415c audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6415c.
+
+config VIDEO_TEA6420
+       tristate "Philips TEA6420 audio processor"
+       depends on I2C
+       ---help---
+         Support for tea6420 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6420.
+
+config VIDEO_MSP3400
+       tristate "Micronas MSP34xx audio decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Micronas MSP34xx series of audio decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called msp3400.
+
+config VIDEO_CS5345
+       tristate "Cirrus Logic CS5345 audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Cirrus Logic CS5345 24-bit, 192 kHz
+         stereo A/D converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cs5345.
+
+config VIDEO_CS53L32A
+       tristate "Cirrus Logic CS53L32A audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Cirrus Logic CS53L32A low voltage
+         stereo A/D converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cs53l32a.
+
+config VIDEO_TLV320AIC23B
+       tristate "Texas Instruments TLV320AIC23B audio codec"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TLV320AIC23B audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tlv320aic23b.
+
+config VIDEO_UDA1342
+       tristate "Philips UDA1342 audio codec"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips UDA1342 audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called uda1342.
+
+config VIDEO_WM8775
+       tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Wolfson Microelectronics WM8775 high
+         performance stereo A/D Converter with a 4 channel input mixer.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8775.
+
+config VIDEO_WM8739
+       tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Wolfson Microelectronics WM8739
+         stereo A/D Converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8739.
+
+config VIDEO_VP27SMPX
+       tristate "Panasonic VP27's internal MPX"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the internal MPX of the Panasonic VP27s tuner.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vp27smpx.
+
+config VIDEO_SONY_BTF_MPX
+       tristate "Sony BTF's internal MPX"
+       depends on VIDEO_V4L2 && I2C
+       help
+         Support for the internal MPX of the Sony BTF-PG472Z tuner.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sony-btf-mpx.
+
+comment "RDS decoders"
+
+config VIDEO_SAA6588
+       tristate "SAA6588 Radio Chip RDS decoder support"
+       depends on VIDEO_V4L2 && I2C
+
+       help
+         Support for this Radio Data System (RDS) decoder. This allows
+         seeing radio station identification transmitted using this
+         standard.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa6588.
+
+comment "Video decoders"
+
+config VIDEO_ADV7180
+       tristate "Analog Devices ADV7180 decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7180 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7180.
+
+config VIDEO_ADV7183
+       tristate "Analog Devices ADV7183 decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         V4l2 subdevice driver for the Analog Devices
+         ADV7183 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7183.
+
+config VIDEO_ADV7604
+       tristate "Analog Devices ADV7604 decoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices ADV7604 video decoder.
+
+         This is a Analog Devices Component/Graphics Digitizer
+         with 4:1 Multiplexed HDMI Receiver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7604.
+
+config VIDEO_ADV7842
+       tristate "Analog Devices ADV7842 decoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices ADV7842 video decoder.
+
+         This is a Analog Devices Component/Graphics/SD Digitizer
+         with 2:1 Multiplexed HDMI Receiver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7842.
+
+config VIDEO_BT819
+       tristate "BT819A VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT819A video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt819.
+
+config VIDEO_BT856
+       tristate "BT856 VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT856 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt856.
+
+config VIDEO_BT866
+       tristate "BT866 VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT866 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt866.
+
+config VIDEO_KS0127
+       tristate "KS0127 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for KS0127 video decoder.
+
+         This chip is used on AverMedia AVS6EYES Zoran-based MJPEG
+         cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ks0127.
+
+config VIDEO_ML86V7667
+       tristate "OKI ML86V7667 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the OKI Semiconductor ML86V7667 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ml86v7667.
+
+config VIDEO_SAA7110
+       tristate "Philips SAA7110 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7110 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7110.
+
+config VIDEO_SAA711X
+       tristate "Philips SAA7111/3/4/5 video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7111/3/4/5 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7115.
+
+config VIDEO_SAA7191
+       tristate "Philips SAA7191 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7191 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7191.
+
+config VIDEO_TVP514X
+       tristate "Texas Instruments TVP514x video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the TI TVP5146/47
+         decoder. It is currently working with the TI OMAP3 camera
+         controller.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp514x.
+
+config VIDEO_TVP5150
+       tristate "Texas Instruments TVP5150 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TVP5150 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp5150.
+
+config VIDEO_TVP7002
+       tristate "Texas Instruments TVP7002 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TVP7002 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp7002.
+
+config VIDEO_TW2804
+       tristate "Techwell TW2804 multiple video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Techwell tw2804 multiple video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tw2804.
+
+config VIDEO_TW9903
+       tristate "Techwell TW9903 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Techwell tw9903 multi-standard video decoder
+         with high quality down scaler.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tw9903.
+
+config VIDEO_TW9906
+       tristate "Techwell TW9906 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Techwell tw9906 enhanced multi-standard comb filter
+         video decoder with YCbCr input support.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tw9906.
+
+config VIDEO_VPX3220
+       tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for VPX322x video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vpx3220.
+
+comment "Video and audio decoders"
+
+config VIDEO_SAA717X
+       tristate "Philips SAA7171/3/4 audio/video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7171/3/4 audio/video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa717x.
+
+source "drivers/media/i2c/cx25840/Kconfig"
+
+comment "Video encoders"
+
+config VIDEO_SAA7127
+       tristate "Philips SAA7127/9 digital video encoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7127/9 digital video encoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7127.
+
+config VIDEO_SAA7185
+       tristate "Philips SAA7185 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7185 video encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7185.
+
+config VIDEO_ADV7170
+       tristate "Analog Devices ADV7170 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7170 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7170.
+
+config VIDEO_ADV7175
+       tristate "Analog Devices ADV7175 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7175 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7175.
+
+config VIDEO_ADV7343
+       tristate "ADV7343 video encoder"
+       depends on I2C
+       help
+         Support for Analog Devices I2C bus based ADV7343 encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7343.
+
+config VIDEO_ADV7393
+       tristate "ADV7393 video encoder"
+       depends on I2C
+       help
+         Support for Analog Devices I2C bus based ADV7393 encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7393.
+
+config VIDEO_ADV7511
+       tristate "Analog Devices ADV7511 encoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices ADV7511 video encoder.
+
+         This is a Analog Devices HDMI transmitter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7511.
+
+config VIDEO_AD9389B
+       tristate "Analog Devices AD9389B encoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices AD9389B video encoder.
+
+         This is a Analog Devices HDMI transmitter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ad9389b.
+
+config VIDEO_AK881X
+       tristate "AK8813/AK8814 video encoders"
+       depends on I2C
+       help
+         Video output driver for AKM AK8813 and AK8814 TV encoders
+
+config VIDEO_THS8200
+       tristate "Texas Instruments THS8200 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments THS8200 video encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ths8200.
+
+comment "Camera sensor devices"
+
+config VIDEO_APTINA_PLL
+       tristate
+
+config VIDEO_SMIAPP_PLL
+       tristate
+
+config VIDEO_OV7640
+       tristate "OmniVision OV7640 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV7640 camera.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ov7640.
+
+config VIDEO_OV7670
+       tristate "OmniVision OV7670 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV7670 VGA camera.  It currently only works with the M88ALP01
+         controller.
+
+config VIDEO_OV9650
+       tristate "OmniVision OV9650/OV9652 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for the Omnivision
+         OV9650 and OV9652 camera sensors.
+
+config VIDEO_VS6624
+       tristate "ST VS6624 sensor support"
+       depends on VIDEO_V4L2 && I2C
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the ST VS6624
+         camera.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vs6624.
+
+config VIDEO_MT9M032
+       tristate "MT9M032 camera sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       select VIDEO_APTINA_PLL
+       ---help---
+         This driver supports MT9M032 camera sensors from Aptina, monochrome
+         models only.
+
+config VIDEO_MT9P031
+       tristate "Aptina MT9P031 support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       select VIDEO_APTINA_PLL
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Aptina
+         (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+       tristate "Aptina MT9T001 support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Aptina
+         (Micron) mt0t001 3 Mpixel camera.
+
+config VIDEO_MT9V011
+       tristate "Micron mt9v011 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Micron
+         mt0v011 1.3 Mpixel camera.  It currently only works with the
+         em28xx driver.
+
+config VIDEO_MT9V032
+       tristate "Micron MT9V032 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Micron
+         MT9V032 752x480 CMOS sensor.
+
+config VIDEO_SR030PC30
+       tristate "Siliconfile SR030PC30 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+       tristate "Siliconfile NOON010PC30 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/i2c/m5mols/Kconfig"
+
+config VIDEO_S5K6AA
+       tristate "Samsung S5K6AAFX sensor support"
+       depends on MEDIA_CAMERA_SUPPORT
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+         camera sensor with an embedded SoC image signal processor.
+
+config VIDEO_S5K4ECGX
+        tristate "Samsung S5K4ECGX sensor support"
+        depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+        ---help---
+          This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
+          camera sensor with an embedded SoC image signal processor.
+
+config VIDEO_S5K5BAF
+       tristate "Samsung S5K5BAF sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for Samsung S5K5BAF 2M
+         camera sensor with an embedded SoC image signal processor.
+
+source "drivers/media/i2c/smiapp/Kconfig"
+
+config VIDEO_S5C73M3
+       tristate "Samsung S5C73M3 sensor support"
+       depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for Samsung S5C73M3
+         8 Mpixel camera.
+
+comment "Flash devices"
+
+config VIDEO_ADP1653
+       tristate "ADP1653 flash support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a driver for the ADP1653 flash controller. It is used for
+         example in Nokia N900.
+
+config VIDEO_AS3645A
+       tristate "AS3645A flash driver support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a driver for the AS3645A and LM3555 flash controllers. It has
+         build in control for flash, torch and indicator LEDs.
+
+config VIDEO_LM3560
+       tristate "LM3560 dual flash driver support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       depends on MEDIA_CAMERA_SUPPORT
+       select REGMAP_I2C
+       ---help---
+         This is a driver for the lm3560 dual flash controllers. It controls
+         flash, torch LEDs.
+
+comment "Video improvement chips"
+
+config VIDEO_UPD64031A
+       tristate "NEC Electronics uPD64031A Ghost Reduction"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the NEC Electronics uPD64031A Ghost Reduction
+         video chip. It is most often found in NTSC TV cards made for
+         Japan and is used to reduce the 'ghosting' effect that can
+         be present in analog TV broadcasts.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64031a.
+
+config VIDEO_UPD64083
+       tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+         separation video chip. It is used to improve the quality of
+         the colors of a composite signal.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64083.
+
+comment "Audio/Video compression chips"
+
+config VIDEO_SAA6752HS
+       tristate "Philips SAA6752HS MPEG-2 Audio/Video Encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA6752HS MPEG-2 video and MPEG-audio/AC-3
+         audio encoder with multiplexer.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa6752hs.
+
+comment "Miscellaneous helper chips"
+
+config VIDEO_THS7303
+       tristate "THS7303/53 Video Amplifier"
+       depends on VIDEO_V4L2 && I2C
+       help
+         Support for TI THS7303/53 video amplifier
+
+         To compile this driver as a module, choose M here: the
+         module will be called ths7303.
+
+config VIDEO_M52790
+       tristate "Mitsubishi M52790 A/V switch"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+        Support for the Mitsubishi M52790 A/V switch.
+
+        To compile this driver as a module, choose M here: the
+        module will be called m52790.
+endmenu
+
+menu "Sensors used on soc_camera driver"
+
+if SOC_CAMERA
+       source "drivers/media/i2c/soc_camera/Kconfig"
+endif
+
+endmenu
+
+endif
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
new file mode 100644 (file)
index 0000000..48888ae
--- /dev/null
@@ -0,0 +1,78 @@
+msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
+obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
+
+obj-$(CONFIG_VIDEO_SMIAPP)     += smiapp/
+obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
+obj-y                          += soc_camera/
+
+obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
+obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
+obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
+obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
+obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
+obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
+obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
+obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
+obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
+obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
+obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
+obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
+obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
+obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
+obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
+obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o
+obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
+obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o
+obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
+obj-$(CONFIG_VIDEO_VS6624)  += vs6624.o
+obj-$(CONFIG_VIDEO_BT819) += bt819.o
+obj-$(CONFIG_VIDEO_BT856) += bt856.o
+obj-$(CONFIG_VIDEO_BT866) += bt866.o
+obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
+obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
+obj-$(CONFIG_VIDEO_THS8200) += ths8200.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
+obj-$(CONFIG_VIDEO_TW2804) += tw2804.o
+obj-$(CONFIG_VIDEO_TW9903) += tw9903.o
+obj-$(CONFIG_VIDEO_TW9906) += tw9906.o
+obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
+obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_M52790) += m52790.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
+obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
+obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
+obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
+obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
+obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
+obj-$(CONFIG_VIDEO_SR030PC30)  += sr030pc30.o
+obj-$(CONFIG_VIDEO_NOON010PC30)        += noon010pc30.o
+obj-$(CONFIG_VIDEO_S5K6AA)     += s5k6aa.o
+obj-$(CONFIG_VIDEO_S5K4ECGX)   += s5k4ecgx.o
+obj-$(CONFIG_VIDEO_S5K5BAF)    += s5k5baf.o
+obj-$(CONFIG_VIDEO_S5C73M3)    += s5c73m3/
+obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
+obj-$(CONFIG_VIDEO_AS3645A)    += as3645a.o
+obj-$(CONFIG_VIDEO_LM3560)     += lm3560.o
+obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
+obj-$(CONFIG_VIDEO_AK881X)             += ak881x.o
+obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_ML86V7667)  += ml86v7667.o
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
new file mode 100644 (file)
index 0000000..d98ca3a
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * drivers/media/i2c/lm3560.c
+ * General device driver for TI lm3560, FLASH LED Driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Contact: Daniel Jeong <gshark.jeong@gmail.com>
+ *                     Ldd-Mlp <ldd-mlp@list.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/videodev2.h>
+#include <media/lm3560.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+/* registers definitions */
+#define REG_ENABLE             0x10
+#define REG_TORCH_BR   0xa0
+#define REG_FLASH_BR   0xb0
+#define REG_FLASH_TOUT 0xc0
+#define REG_FLAG               0xd0
+#define REG_CONFIG1            0xe0
+
+/* Fault Mask */
+#define FAULT_TIMEOUT  (1<<0)
+#define FAULT_OVERTEMP (1<<1)
+#define FAULT_SHORT_CIRCUIT    (1<<2)
+
+enum led_enable {
+       MODE_SHDN = 0x0,
+       MODE_TORCH = 0x2,
+       MODE_FLASH = 0x3,
+};
+
+/* struct lm3560_flash
+ *
+ * @pdata: platform data
+ * @regmap: reg. map for i2c
+ * @lock: muxtex for serial access.
+ * @led_mode: V4L2 LED mode
+ * @ctrls_led: V4L2 contols
+ * @subdev_led: V4L2 subdev
+ */
+struct lm3560_flash {
+       struct device *dev;
+       struct lm3560_platform_data *pdata;
+       struct regmap *regmap;
+       struct mutex lock;
+
+       enum v4l2_flash_led_mode led_mode;
+       struct v4l2_ctrl_handler ctrls_led[LM3560_LED_MAX];
+       struct v4l2_subdev subdev_led[LM3560_LED_MAX];
+};
+
+#define to_lm3560_flash(_ctrl, _no)    \
+       container_of(_ctrl->handler, struct lm3560_flash, ctrls_led[_no])
+
+/* enable mode control */
+static int lm3560_mode_ctrl(struct lm3560_flash *flash)
+{
+       int rval = -EINVAL;
+
+       switch (flash->led_mode) {
+       case V4L2_FLASH_LED_MODE_NONE:
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_ENABLE, 0x03, MODE_SHDN);
+               break;
+       case V4L2_FLASH_LED_MODE_TORCH:
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_ENABLE, 0x03, MODE_TORCH);
+               break;
+       case V4L2_FLASH_LED_MODE_FLASH:
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_ENABLE, 0x03, MODE_FLASH);
+               break;
+       }
+       return rval;
+}
+
+/* led1/2  enable/disable */
+static int lm3560_enable_ctrl(struct lm3560_flash *flash,
+                             enum lm3560_led_id led_no, bool on)
+{
+       int rval;
+
+       if (led_no == LM3560_LED0) {
+               if (on == true)
+                       rval = regmap_update_bits(flash->regmap,
+                                                 REG_ENABLE, 0x08, 0x08);
+               else
+                       rval = regmap_update_bits(flash->regmap,
+                                                 REG_ENABLE, 0x08, 0x00);
+       } else {
+               if (on == true)
+                       rval = regmap_update_bits(flash->regmap,
+                                                 REG_ENABLE, 0x10, 0x10);
+               else
+                       rval = regmap_update_bits(flash->regmap,
+                                                 REG_ENABLE, 0x10, 0x00);
+       }
+       return rval;
+}
+
+/* torch1/2 brightness control */
+static int lm3560_torch_brt_ctrl(struct lm3560_flash *flash,
+                                enum lm3560_led_id led_no, unsigned int brt)
+{
+       int rval;
+       u8 br_bits;
+
+       if (brt < LM3560_TORCH_BRT_MIN)
+               return lm3560_enable_ctrl(flash, led_no, false);
+       else
+               rval = lm3560_enable_ctrl(flash, led_no, true);
+
+       br_bits = LM3560_TORCH_BRT_uA_TO_REG(brt);
+       if (led_no == LM3560_LED0)
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_TORCH_BR, 0x07, br_bits);
+       else
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_TORCH_BR, 0x38, br_bits << 3);
+
+       return rval;
+}
+
+/* flash1/2 brightness control */
+static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash,
+                                enum lm3560_led_id led_no, unsigned int brt)
+{
+       int rval;
+       u8 br_bits;
+
+       if (brt < LM3560_FLASH_BRT_MIN)
+               return lm3560_enable_ctrl(flash, led_no, false);
+       else
+               rval = lm3560_enable_ctrl(flash, led_no, true);
+
+       br_bits = LM3560_FLASH_BRT_uA_TO_REG(brt);
+       if (led_no == LM3560_LED0)
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_FLASH_BR, 0x0f, br_bits);
+       else
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_FLASH_BR, 0xf0, br_bits << 4);
+
+       return rval;
+}
+
+/* V4L2 controls  */
+static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
+{
+       struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
+       int rval = -EINVAL;
+
+       mutex_lock(&flash->lock);
+
+       if (ctrl->id == V4L2_CID_FLASH_FAULT) {
+               s32 fault = 0;
+               unsigned int reg_val;
+               rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
+               if (rval < 0)
+                       goto out;
+               if (reg_val & FAULT_SHORT_CIRCUIT)
+                       fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+               if (reg_val & FAULT_OVERTEMP)
+                       fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+               if (reg_val & FAULT_TIMEOUT)
+                       fault |= V4L2_FLASH_FAULT_TIMEOUT;
+               ctrl->cur.val = fault;
+       }
+
+out:
+       mutex_unlock(&flash->lock);
+       return rval;
+}
+
+static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
+{
+       struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
+       u8 tout_bits;
+       int rval = -EINVAL;
+
+       mutex_lock(&flash->lock);
+
+       switch (ctrl->id) {
+       case V4L2_CID_FLASH_LED_MODE:
+               flash->led_mode = ctrl->val;
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+                       rval = lm3560_mode_ctrl(flash);
+               break;
+
+       case V4L2_CID_FLASH_STROBE_SOURCE:
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_CONFIG1, 0x04, (ctrl->val) << 2);
+               if (rval < 0)
+                       goto err_out;
+               break;
+
+       case V4L2_CID_FLASH_STROBE:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
+                       rval = -EBUSY;
+                       goto err_out;
+               }
+               flash->led_mode = V4L2_FLASH_LED_MODE_FLASH;
+               rval = lm3560_mode_ctrl(flash);
+               break;
+
+       case V4L2_CID_FLASH_STROBE_STOP:
+               if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
+                       rval = -EBUSY;
+                       goto err_out;
+               }
+               flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+               rval = lm3560_mode_ctrl(flash);
+               break;
+
+       case V4L2_CID_FLASH_TIMEOUT:
+               tout_bits = LM3560_FLASH_TOUT_ms_TO_REG(ctrl->val);
+               rval = regmap_update_bits(flash->regmap,
+                                         REG_FLASH_TOUT, 0x1f, tout_bits);
+               break;
+
+       case V4L2_CID_FLASH_INTENSITY:
+               rval = lm3560_flash_brt_ctrl(flash, led_no, ctrl->val);
+               break;
+
+       case V4L2_CID_FLASH_TORCH_INTENSITY:
+               rval = lm3560_torch_brt_ctrl(flash, led_no, ctrl->val);
+               break;
+       }
+
+err_out:
+       mutex_unlock(&flash->lock);
+       return rval;
+}
+
+static int lm3560_led1_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+       return lm3560_get_ctrl(ctrl, LM3560_LED1);
+}
+
+static int lm3560_led1_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+       return lm3560_set_ctrl(ctrl, LM3560_LED1);
+}
+
+static int lm3560_led0_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+       return lm3560_get_ctrl(ctrl, LM3560_LED0);
+}
+
+static int lm3560_led0_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+       return lm3560_set_ctrl(ctrl, LM3560_LED0);
+}
+
+static const struct v4l2_ctrl_ops lm3560_led_ctrl_ops[LM3560_LED_MAX] = {
+       [LM3560_LED0] = {
+                        .g_volatile_ctrl = lm3560_led0_get_ctrl,
+                        .s_ctrl = lm3560_led0_set_ctrl,
+                        },
+       [LM3560_LED1] = {
+                        .g_volatile_ctrl = lm3560_led1_get_ctrl,
+                        .s_ctrl = lm3560_led1_set_ctrl,
+                        }
+};
+
+static int lm3560_init_controls(struct lm3560_flash *flash,
+                               enum lm3560_led_id led_no)
+{
+       struct v4l2_ctrl *fault;
+       u32 max_flash_brt = flash->pdata->max_flash_brt[led_no];
+       u32 max_torch_brt = flash->pdata->max_torch_brt[led_no];
+       struct v4l2_ctrl_handler *hdl = &flash->ctrls_led[led_no];
+       const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no];
+
+       v4l2_ctrl_handler_init(hdl, 8);
+       /* flash mode */
+       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_LED_MODE,
+                              V4L2_FLASH_LED_MODE_TORCH, ~0x7,
+                              V4L2_FLASH_LED_MODE_NONE);
+       flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+
+       /* flash source */
+       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_FLASH_STROBE_SOURCE,
+                              0x1, ~0x3, V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
+
+       /* flash strobe */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+       /* flash strobe stop */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+
+       /* flash strobe timeout */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TIMEOUT,
+                         LM3560_FLASH_TOUT_MIN,
+                         flash->pdata->max_flash_timeout,
+                         LM3560_FLASH_TOUT_STEP,
+                         flash->pdata->max_flash_timeout);
+
+       /* flash brt */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY,
+                         LM3560_FLASH_BRT_MIN, max_flash_brt,
+                         LM3560_FLASH_BRT_STEP, max_flash_brt);
+
+       /* torch brt */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY,
+                         LM3560_TORCH_BRT_MIN, max_torch_brt,
+                         LM3560_TORCH_BRT_STEP, max_torch_brt);
+
+       /* fault */
+       fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0,
+                                 V4L2_FLASH_FAULT_OVER_VOLTAGE
+                                 | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+                                 | V4L2_FLASH_FAULT_SHORT_CIRCUIT
+                                 | V4L2_FLASH_FAULT_TIMEOUT, 0, 0);
+       if (fault != NULL)
+               fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+       if (hdl->error)
+               return hdl->error;
+
+       flash->subdev_led[led_no].ctrl_handler = hdl;
+       return 0;
+}
+
+/* initialize device */
+static const struct v4l2_subdev_ops lm3560_ops = {
+       .core = NULL,
+};
+
+static const struct regmap_config lm3560_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = 0xFF,
+};
+
+static int lm3560_subdev_init(struct lm3560_flash *flash,
+                             enum lm3560_led_id led_no, char *led_name)
+{
+       struct i2c_client *client = to_i2c_client(flash->dev);
+       int rval;
+
+       v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops);
+       flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       strcpy(flash->subdev_led[led_no].name, led_name);
+       rval = lm3560_init_controls(flash, led_no);
+       if (rval)
+               goto err_out;
+       rval = media_entity_init(&flash->subdev_led[led_no].entity, 0, NULL, 0);
+       if (rval < 0)
+               goto err_out;
+       flash->subdev_led[led_no].entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+       return rval;
+
+err_out:
+       v4l2_ctrl_handler_free(&flash->ctrls_led[led_no]);
+       return rval;
+}
+
+static int lm3560_init_device(struct lm3560_flash *flash)
+{
+       int rval;
+       unsigned int reg_val;
+
+       /* set peak current */
+       rval = regmap_update_bits(flash->regmap,
+                                 REG_FLASH_TOUT, 0x60, flash->pdata->peak);
+       if (rval < 0)
+               return rval;
+       /* output disable */
+       flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+       rval = lm3560_mode_ctrl(flash);
+       if (rval < 0)
+               return rval;
+       /* Reset faults */
+       rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
+       return rval;
+}
+
+static int lm3560_probe(struct i2c_client *client,
+                       const struct i2c_device_id *devid)
+{
+       struct lm3560_flash *flash;
+       struct lm3560_platform_data *pdata = dev_get_platdata(&client->dev);
+       int rval;
+
+       flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
+       if (flash == NULL)
+               return -ENOMEM;
+
+       flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap);
+       if (IS_ERR(flash->regmap)) {
+               rval = PTR_ERR(flash->regmap);
+               return rval;
+       }
+
+       /* if there is no platform data, use chip default value */
+       if (pdata == NULL) {
+               pdata =
+                   kzalloc(sizeof(struct lm3560_platform_data), GFP_KERNEL);
+               if (pdata == NULL)
+                       return -ENODEV;
+               pdata->peak = LM3560_PEAK_3600mA;
+               pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
+               /* led 1 */
+               pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX;
+               pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX;
+               /* led 2 */
+               pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX;
+               pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX;
+       }
+       flash->pdata = pdata;
+       flash->dev = &client->dev;
+       mutex_init(&flash->lock);
+
+       rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
+       if (rval < 0)
+               return rval;
+
+       rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
+       if (rval < 0)
+               return rval;
+
+       rval = lm3560_init_device(flash);
+       if (rval < 0)
+               return rval;
+
+       i2c_set_clientdata(client, flash);
+
+       return 0;
+}
+
+static int lm3560_remove(struct i2c_client *client)
+{
+       struct lm3560_flash *flash = i2c_get_clientdata(client);
+       unsigned int i;
+
+       for (i = LM3560_LED0; i < LM3560_LED_MAX; i++) {
+               v4l2_device_unregister_subdev(&flash->subdev_led[i]);
+               v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
+               media_entity_cleanup(&flash->subdev_led[i].entity);
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id lm3560_id_table[] = {
+       {LM3560_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3560_id_table);
+
+static struct i2c_driver lm3560_i2c_driver = {
+       .driver = {
+                  .name = LM3560_NAME,
+                  .pm = NULL,
+                  },
+       .probe = lm3560_probe,
+       .remove = lm3560_remove,
+       .id_table = lm3560_id_table,
+};
+
+module_i2c_driver(lm3560_i2c_driver);
+
+MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
+MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
+MODULE_DESCRIPTION("Texas Instruments LM3560 LED flash driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
new file mode 100644 (file)
index 0000000..49bb445
--- /dev/null
@@ -0,0 +1,1228 @@
+#
+# Multifunction miscellaneous devices
+#
+
+if HAS_IOMEM
+menu "Multifunction device drivers"
+
+config MFD_CORE
+       tristate
+       select IRQ_DOMAIN
+       default n
+
+config MFD_CS5535
+       tristate "AMD CS5535 and CS5536 southbridge core functions"
+       select MFD_CORE
+       depends on PCI && X86
+       ---help---
+         This is the core driver for CS5535/CS5536 MFD functions.  This is
+          necessary for using the board's GPIO and MFGPT functionality.
+
+config MFD_AS3711
+       bool "AMS AS3711"
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       depends on I2C=y
+       help
+         Support for the AS3711 PMIC from AMS
+
+config MFD_AS3722
+       bool "ams AS3722 Power Management IC"
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       depends on I2C=y && OF
+       help
+         The ams AS3722 is a compact system PMU suitable for mobile phones,
+         tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down
+         controllers, 11 LDOs, RTC, automatic battery, temperature and
+         over current monitoring, GPIOs, ADC and a watchdog.
+
+config PMIC_ADP5520
+       bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
+       depends on I2C=y
+       help
+         Say yes here to add support for Analog Devices AD5520 and ADP5501,
+         Multifunction Power Management IC. This includes
+         the I2C driver and the core APIs _only_, you have to select
+         individual components like LCD backlight, LEDs, GPIOs and Kepad
+         under the corresponding menus.
+
+config MFD_AAT2870_CORE
+       bool "AnalogicTech AAT2870"
+       select MFD_CORE
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the AAT2870.
+         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_CROS_EC
+       tristate "ChromeOS Embedded Controller"
+       select MFD_CORE
+       help
+         If you say Y here you get support for the ChromeOS Embedded
+         Controller (EC) providing keyboard, battery and power services.
+         You also need to enable the driver for the bus you are using. The
+         protocol for talking to the EC is defined by the bus driver.
+
+config MFD_CROS_EC_I2C
+       tristate "ChromeOS Embedded Controller (I2C)"
+       depends on MFD_CROS_EC && I2C
+
+       help
+         If you say Y here, you get support for talking to the ChromeOS
+         EC through an I2C bus. This uses a simple byte-level protocol with
+         a checksum. Failing accesses will be retried three times to
+         improve reliability.
+
+config MFD_CROS_EC_SPI
+       tristate "ChromeOS Embedded Controller (SPI)"
+       depends on MFD_CROS_EC && SPI && OF
+
+       ---help---
+         If you say Y here, you get support for talking to the ChromeOS EC
+         through a SPI bus, using a byte-level protocol. Since the EC's
+         response time cannot be guaranteed, we support ignoring
+         'pre-amble' bytes before the response actually starts.
+
+config MFD_ASIC3
+       bool "Compaq ASIC3"
+       depends on GPIOLIB && ARM
+       select MFD_CORE
+        ---help---
+         This driver supports the ASIC3 multifunction chip found on many
+         PDAs (mainly iPAQ and HTC based ones)
+
+config PMIC_DA903X
+       bool "Dialog Semiconductor DA9030/DA9034 PMIC Support"
+       depends on I2C=y
+       help
+         Say yes here to support for Dialog Semiconductor DA9030 (a.k.a
+         ARAVA) and DA9034 (a.k.a MICCO), these are Power Management IC
+         usually found on PXA processors-based platforms. This includes
+         the I2C driver and the core APIs _only_, you have to select
+         individual components like LCD backlight, voltage regulators,
+         LEDs and battery-charger under the corresponding menus.
+
+config PMIC_DA9052
+       bool
+       select MFD_CORE
+
+config MFD_DA9052_SPI
+       bool "Dialog Semiconductor DA9052/53 PMIC variants with SPI"
+       select REGMAP_SPI
+       select REGMAP_IRQ
+       select PMIC_DA9052
+       depends on SPI_MASTER=y
+       help
+         Support for the Dialog Semiconductor DA9052 PMIC
+         when controlled using SPI. 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_DA9052_I2C
+       bool "Dialog Semiconductor DA9052/53 PMIC variants with I2C"
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select PMIC_DA9052
+       depends on I2C=y
+       help
+         Support for the Dialog Semiconductor DA9052 PMIC
+         when controlled using I2C. 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_DA9055
+       bool "Dialog Semiconductor DA9055 PMIC Support"
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       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 MFD_DA9063
+       bool "Dialog Semiconductor DA9063 PMIC Support"
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       depends on I2C=y
+       help
+         Say yes here for support for the Dialog Semiconductor DA9063 PMIC.
+         This includes the I2C driver and core APIs.
+         Additional drivers must be enabled in order to use the functionality
+         of the device.
+
+config MFD_MC13XXX
+       tristate
+       depends on (SPI_MASTER || I2C)
+       select MFD_CORE
+       help
+         Enable support for the Freescale MC13783 and MC13892 PMICs.
+         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_MC13XXX_SPI
+       tristate "Freescale MC13783 and MC13892 SPI interface"
+       depends on SPI_MASTER
+       select REGMAP_SPI
+       select MFD_MC13XXX
+       help
+         Select this if your MC13xxx is connected via an SPI bus.
+
+config MFD_MC13XXX_I2C
+       tristate "Freescale MC13892 I2C interface"
+       depends on I2C
+       select REGMAP_I2C
+       select MFD_MC13XXX
+       help
+         Select this if your MC13xxx is connected via an I2C bus.
+
+config HTC_EGPIO
+       bool "HTC EGPIO support"
+       depends on GPIOLIB && ARM
+       help
+           This driver supports the CPLD egpio chip present on
+           several HTC phones.  It provides basic support for input
+           pins, output pins, and irqs.
+
+config HTC_PASIC3
+       tristate "HTC PASIC3 LED/DS1WM chip support"
+       select MFD_CORE
+       help
+         This core driver provides register access for the LED/DS1WM
+         chips labeled "AIC2" and "AIC3", found on HTC Blueangel and
+         HTC Magician devices, respectively. Actual functionality is
+         handled by the leds-pasic3 and ds1wm drivers.
+
+config HTC_I2CPLD
+       bool "HTC I2C PLD chip support"
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the supposed CPLD
+         found on omap850 HTC devices like the HTC Wizard and HTC Herald.
+         This device provides input and output GPIOs through an I2C
+         interface to one or more sub-chips.
+
+config LPC_ICH
+       tristate "Intel ICH LPC"
+       depends on PCI
+       select MFD_CORE
+       help
+         The LPC bridge function of the Intel ICH provides support for
+         many functional units. This driver provides needed support for
+         other drivers to control these functions, currently GPIO and
+         watchdog.
+
+config LPC_SCH
+       tristate "Intel SCH LPC"
+       depends on PCI
+       select MFD_CORE
+       help
+         LPC bridge function of the Intel SCH provides support for
+         System Management Bus and General Purpose I/O.
+
+config MFD_INTEL_MSIC
+       bool "Intel MSIC"
+       depends on INTEL_SCU_IPC
+       select MFD_CORE
+       help
+         Select this option to enable access to Intel MSIC (Avatele
+         Passage) chip. This chip embeds audio, battery, GPIO, etc.
+         devices used in Intel Medfield platforms.
+
+config MFD_JANZ_CMODIO
+       tristate "Janz CMOD-IO PCI MODULbus Carrier Board"
+       select MFD_CORE
+       depends on PCI
+       help
+         This is the core driver for the Janz CMOD-IO PCI MODULbus
+         carrier board. This device is a PCI to MODULbus bridge which may
+         host many different types of MODULbus daughterboards, including
+         CAN and GPIO controllers.
+
+config MFD_JZ4740_ADC
+       bool "Janz JZ4740 ADC core"
+       select MFD_CORE
+       select GENERIC_IRQ_CHIP
+       depends on MACH_JZ4740
+       help
+         Say yes here if you want support for the ADC unit in the JZ4740 SoC.
+         This driver is necessary for jz4740-battery and jz4740-hwmon driver.
+
+config MFD_KEMPLD
+       tristate "Kontron module PLD device"
+       select MFD_CORE
+       help
+         This is the core driver for the PLD (Programmable Logic Device) found
+         on some Kontron ETX and COMexpress (ETXexpress) modules. The PLD
+         device may provide functions like watchdog, GPIO, UART and I2C bus.
+
+         The following modules are supported:
+               * COMe-bIP#
+               * COMe-bPC2 (ETXexpress-PC)
+               * COMe-bSC# (ETXexpress-SC T#)
+               * COMe-cCT6
+               * COMe-cDC2 (microETXexpress-DC)
+               * COMe-cPC2 (microETXexpress-PC)
+               * COMe-mCT10
+               * ETX-OH
+
+         This driver can also be built as a module. If so, the module
+         will be called kempld-core.
+
+config MFD_88PM800
+       tristate "Marvell 88PM800"
+       depends on I2C=y
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select MFD_CORE
+       help
+         This supports for Marvell 88PM800 Power Management IC.
+         This includes the I2C driver and the core APIs _only_, you have to
+         select individual components like voltage regulators, RTC and
+         battery-charger under the corresponding menus.
+
+config MFD_88PM805
+       tristate "Marvell 88PM805"
+       depends on I2C=y
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select MFD_CORE
+       help
+         This supports for Marvell 88PM805 Power Management IC. This includes
+         the I2C driver and the core APIs _only_, you have to select individual
+         components like codec device, headset/Mic device under the
+         corresponding menus.
+
+config MFD_88PM860X
+       bool "Marvell 88PM8606/88PM8607"
+       depends on I2C=y
+       select REGMAP_I2C
+       select MFD_CORE
+       help
+         This supports for Marvell 88PM8606/88PM8607 Power Management IC.
+         This includes the I2C driver and the core APIs _only_, you have to
+         select individual components like voltage regulators, RTC and
+         battery-charger under the corresponding menus.
+
+config MFD_MAX14577
+       bool "Maxim Semiconductor MAX14577 MUIC + Charger Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select IRQ_DOMAIN
+       help
+         Say yes here to support for Maxim Semiconductor MAX14577.
+         This is a Micro-USB IC with Charger controls on chip.
+         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_MAX77686
+       bool "Maxim Semiconductor MAX77686 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select IRQ_DOMAIN
+       help
+         Say yes here to support for Maxim Semiconductor MAX77686.
+         This is a Power Management IC with RTC on chip.
+         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_MAX77693
+       bool "Maxim Semiconductor MAX77693 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Say yes here to support for Maxim Semiconductor MAX77693.
+         This is a companion Power Management IC with Flash, Haptic, Charger,
+         and MUIC(Micro USB Interface Controller) controls on chip.
+         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_MAX8907
+       tristate "Maxim Semiconductor MAX8907 PMIC Support"
+       select MFD_CORE
+       depends on I2C=y
+       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
+       bool "Maxim Semiconductor MAX8925 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       help
+         Say yes here to support for Maxim Semiconductor MAX8925. 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_MAX8997
+       bool "Maxim Semiconductor MAX8997/8966 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       select IRQ_DOMAIN
+       help
+         Say yes here to support for Maxim Semiconductor MAX8997/8966.
+         This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
+         MUIC controls on chip.
+         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_MAX8998
+       bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       select IRQ_DOMAIN
+       help
+         Say yes here to support for Maxim Semiconductor MAX8998 and
+         National Semiconductor LP3974. 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 EZX_PCAP
+       bool "Motorola EZXPCAP Support"
+       depends on SPI_MASTER
+       help
+         This enables the PCAP ASIC present on EZX Phones. This is
+         needed for MMC, TouchScreen, Sound, USB, etc..
+
+config MFD_VIPERBOARD
+        tristate "Nano River Technologies Viperboard"
+       select MFD_CORE
+       depends on USB
+       default n
+       help
+         Say yes here if you want support for Nano River Technologies
+         Viperboard.
+         There are mfd cell drivers available for i2c master, adc and
+         both gpios found on the board. The spi part does not yet
+         have a driver.
+         You need to select the mfd cell drivers separately.
+         The drivers do not support all features the board exposes.
+
+config MFD_RETU
+       tristate "Nokia Retu and Tahvo multi-function device"
+       select MFD_CORE
+       depends on I2C
+       select REGMAP_IRQ
+       help
+         Retu and Tahvo are a multi-function devices found on Nokia
+         Internet Tablets (770, N800 and N810).
+
+config MFD_PCF50633
+       tristate "NXP PCF50633"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         Say yes here if you have NXP PCF50633 chip on your board.
+         This core driver provides register access and IRQ handling
+         facilities, and registers devices for the various functions
+         so that function-specific drivers can bind to them.
+
+config PCF50633_ADC
+       tristate "NXP PCF50633 ADC"
+       depends on MFD_PCF50633
+       help
+        Say yes here if you want to include support for ADC in the
+        NXP PCF50633 chip.
+
+config PCF50633_GPIO
+       tristate "NXP PCF50633 GPIO"
+       depends on MFD_PCF50633
+       help
+        Say yes here if you want to include support GPIO for pins on
+        the PCF50633 chip.
+
+config UCB1400_CORE
+       tristate "Philips UCB1400 Core driver"
+       depends on AC97_BUS
+       depends on GPIOLIB
+       help
+         This enables support for the Philips UCB1400 core functions.
+         The UCB1400 is an AC97 audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ucb1400_core.
+
+config MFD_PM8XXX
+       tristate
+
+config MFD_PM8921_CORE
+       tristate "Qualcomm PM8921 PMIC chip"
+       depends on (ARCH_MSM || HEXAGON)
+       depends on BROKEN
+       select MFD_CORE
+       select MFD_PM8XXX
+       help
+         If you say yes to this option, support will be included for the
+         built-in PM8921 PMIC chip.
+
+         This is required if your board has a PM8921 and uses its features,
+         such as: MPPs, GPIOs, regulators, interrupts, and PWM.
+
+         Say M here if you want to include support for PM8921 chip as a module.
+         This will build a module called "pm8921-core".
+
+config MFD_PM8XXX_IRQ
+       bool "Qualcomm PM8xxx IRQ features"
+       depends on MFD_PM8XXX
+       default y if MFD_PM8XXX
+       help
+         This is the IRQ driver for Qualcomm PM 8xxx PMIC chips.
+
+         This is required to use certain other PM 8xxx features, such as GPIO
+         and MPP.
+
+config MFD_RDC321X
+       tristate "RDC R-321x southbridge"
+       select MFD_CORE
+       depends on PCI
+       help
+         Say yes here if you want to have support for the RDC R-321x SoC
+         southbridge which provides access to GPIOs and Watchdog using the
+         southbridge PCI device configuration space.
+
+config MFD_RTSX_PCI
+       tristate "Realtek PCI-E card reader"
+       depends on PCI
+       select MFD_CORE
+       help
+         This supports for Realtek PCI-Express card reader including rts5209,
+         rts5229, rtl8411, etc. Realtek card reader supports access to many
+         types of memory cards, such as Memory Stick, Memory Stick Pro,
+         Secure Digital and MultiMediaCard.
+
+config MFD_RC5T583
+       bool "Ricoh RC5T583 Power Management system device"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Select this option to get support for the RICOH583 Power
+         Management system device.
+         This driver provides common support for accessing the device
+         through i2c interface. The device supports multiple sub-devices
+         like GPIO, interrupts, RTC, LDO and DCDC regulators, onkey.
+         Additional drivers must be enabled in order to use the
+         different functionality of the device.
+
+config MFD_SEC_CORE
+       bool "SAMSUNG Electronics PMIC Series Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+        Support for the Samsung Electronics MFD series.
+        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_SI476X_CORE
+       tristate "Silicon Laboratories 4761/64/68 AM/FM radio."
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         This is the core driver for the SI476x series of AM/FM
+         radio. This MFD driver connects the radio-si476x V4L2 module
+         and the si476x audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called si476x-core.
+
+config MFD_SM501
+       tristate "Silicon Motion SM501"
+        ---help---
+         This is the core driver for the Silicon Motion SM501 multimedia
+         companion chip. This device is a multifunction device which may
+         provide numerous interfaces including USB host controller, USB gadget,
+         asynchronous serial ports, audio functions, and a dual display video
+         interface. The device may be connected by PCI or local bus with
+         varying functions enabled.
+
+config MFD_SM501_GPIO
+       bool "Export GPIO via GPIO layer"
+       depends on MFD_SM501 && GPIOLIB
+        ---help---
+        This option uses the gpio library layer to export the 64 GPIO
+        lines on the SM501. The platform data is used to supply the
+        base number for the first GPIO line to register.
+
+config MFD_SMSC
+       bool "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 ABX500_CORE
+       bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
+       default y if ARCH_U300 || ARCH_U8500
+       help
+         Say yes here if you have the ABX500 Mixed Signal IC family
+         chips. This core driver expose register access functions.
+         Functionality specific drivers using these functions can
+         remain unchanged when IC changes. Binding of the functions to
+         actual register access is done by the IC core driver.
+
+config AB3100_CORE
+       bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
+       depends on I2C=y && ABX500_CORE
+       select MFD_CORE
+       default y if ARCH_U300
+       help
+         Select this to enable the AB3100 Mixed Signal IC core
+         functionality. This connects to a AB3100 on the I2C bus
+         and expose a number of symbols needed for dependent devices
+         to read and write registers and subscribe to events from
+         this multi-functional IC. This is needed to use other features
+         of the AB3100 such as battery-backed RTC, charging control,
+         LEDs, vibrator, system power and temperature, power management
+         and ALSA sound.
+
+config AB3100_OTP
+       tristate "ST-Ericsson AB3100 OTP functions"
+       depends on AB3100_CORE
+       default y if AB3100_CORE
+       help
+         Select this to enable the AB3100 Mixed Signal IC OTP (one-time
+         programmable memory) support. This exposes a sysfs file to read
+         out OTP values.
+
+config AB8500_CORE
+       bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
+       depends on ABX500_CORE && MFD_DB8500_PRCMU
+       select POWER_SUPPLY
+       select MFD_CORE
+       select IRQ_DOMAIN
+       help
+         Select this option to enable access to AB8500 power management
+         chip. This connects to U8500 either on the SSP/SPI bus (deprecated
+         since hardware version v1.0) or the I2C bus via PRCMU. It also adds
+         the irq_chip parts for handling the Mixed Signal chip events.
+         This chip embeds various other multimedia funtionalities as well.
+
+config AB8500_DEBUG
+       bool "Enable debug info via debugfs"
+       depends on AB8500_GPADC && DEBUG_FS
+       default y if DEBUG_FS
+       help
+         Select this option if you want debug information using the debug
+         filesystem, debugfs.
+
+config AB8500_GPADC
+       bool "ST-Ericsson AB8500 GPADC driver"
+       depends on AB8500_CORE && REGULATOR_AB8500
+       default y
+       help
+         AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
+
+config MFD_DB8500_PRCMU
+       bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
+       depends on UX500_SOC_DB8500
+       select MFD_CORE
+       help
+         Select this option to enable support for the DB8500 Power Reset
+         and Control Management Unit. This is basically an autonomous
+         system controller running an XP70 microprocessor, which is accessed
+         through a register map.
+
+config MFD_STMPE
+       bool "STMicroelectronics STMPE"
+       depends on (I2C=y || SPI_MASTER=y)
+       select MFD_CORE
+       help
+         Support for the STMPE family of I/O Expanders from
+         STMicroelectronics.
+
+         Currently supported devices are:
+
+               STMPE811: GPIO, Touchscreen
+               STMPE1601: GPIO, Keypad
+               STMPE1801: GPIO, Keypad
+               STMPE2401: GPIO, Keypad
+               STMPE2403: GPIO, Keypad
+
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the functionality
+         of the device.  Currently available sub drivers are:
+
+               GPIO: stmpe-gpio
+               Keypad: stmpe-keypad
+               Touchscreen: stmpe-ts
+
+menu "STMicroelectronics STMPE Interface Drivers"
+depends on MFD_STMPE
+
+config STMPE_I2C
+       bool "STMicroelectronics STMPE I2C Interface"
+       depends on I2C=y
+       default y
+       help
+         This is used to enable I2C interface of STMPE
+
+config STMPE_SPI
+       bool "STMicroelectronics STMPE SPI Interface"
+       depends on SPI_MASTER
+       help
+         This is used to enable SPI interface of STMPE
+endmenu
+
+config MFD_STA2X11
+       bool "STMicroelectronics STA2X11"
+       depends on STA2X11
+       select MFD_CORE
+       select REGMAP_MMIO
+
+config MFD_SYSCON
+       bool "System Controller Register R/W Based on Regmap"
+       select REGMAP_MMIO
+       help
+         Select this option to enable accessing system control registers
+         via regmap.
+
+config MFD_DAVINCI_VOICECODEC
+       tristate
+       select MFD_CORE
+
+config MFD_TI_AM335X_TSCADC
+       tristate "TI ADC / Touch Screen chip support"
+       select MFD_CORE
+       select REGMAP
+       select REGMAP_MMIO
+       help
+         If you say yes here you get support for Texas Instruments series
+         of Touch Screen /ADC chips.
+         To compile this driver as a module, choose M here: the
+         module will be called ti_am335x_tscadc.
+
+config MFD_DM355EVM_MSP
+       bool "TI DaVinci DM355 EVM microcontroller"
+       depends on I2C=y && MACH_DAVINCI_DM355_EVM
+       help
+         This driver supports the MSP430 microcontroller used on these
+         boards.  MSP430 firmware manages resets and power sequencing,
+         inputs from buttons and the IR remote, LEDs, an RTC, and more.
+
+config MFD_LP3943
+       tristate "TI/National Semiconductor LP3943 MFD Driver"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Support for the TI/National Semiconductor LP3943.
+         This driver consists of GPIO and PWM drivers.
+         With these functionalities, it can be used for LED string control or
+         general usage such like a GPIO controller and a PWM controller.
+
+config MFD_LP8788
+       bool "TI 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_OMAP_USB_HOST
+       bool "TI OMAP USBHS core and TLL driver"
+       depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
+       default y
+       help
+         This is the core driver for the OAMP EHCI and OHCI drivers.
+         This MFD driver does the required setup functionalities for
+         OMAP USB Host drivers.
+
+config MFD_PALMAS
+       bool "TI Palmas series chips"
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       depends on I2C=y
+       help
+         If you say yes here you get support for the Palmas
+         series of PMIC chips from Texas Instruments.
+
+config MFD_TI_SSP
+       tristate "TI Sequencer Serial Port support"
+       depends on ARCH_DAVINCI_TNETV107X
+       select MFD_CORE
+       ---help---
+         Say Y here if you want support for the Sequencer Serial Port
+         in a Texas Instruments TNETV107X SoC.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ti-ssp.
+
+config TPS6105X
+       tristate "TI TPS61050/61052 Boost Converters"
+       depends on I2C
+       select REGULATOR
+       select MFD_CORE
+       select REGULATOR_FIXED_VOLTAGE
+       help
+         This option enables a driver for the TP61050/TPS61052
+         high-power "white LED driver". This boost converter is
+         sometimes used for other things than white LEDs, and
+         also contains a GPIO pin.
+
+config TPS65010
+       tristate "TI TPS6501x Power Management chips"
+       depends on I2C && GPIOLIB
+       default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+       help
+         If you say yes here you get support for the TPS6501x series of
+         Power Management chips.  These include voltage regulators,
+         lithium ion/polymer battery charging, and other features that
+         are often used in portable devices like cell phones and cameras.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65010.
+
+config TPS6507X
+       tristate "TI TPS6507x Power Management / Touch Screen chips"
+       select MFD_CORE
+       depends on I2C
+       help
+         If you say yes here you get support for the TPS6507x series of
+         Power Management / Touch Screen chips.  These include voltage
+         regulators, lithium ion/polymer battery charging, touch screen
+         and other features that are often used in portable devices.
+         This driver can also be built as a module.  If so, the module
+         will be called tps6507x.
+
+config TPS65911_COMPARATOR
+       tristate
+
+config MFD_TPS65090
+       bool "TI TPS65090 Power Management chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         If you say yes here you get support for the TPS65090 series of
+         Power Management chips.
+         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_TPS65217
+       tristate "TI TPS65217 Power Management / White LED chips"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS65217 series of
+         Power Management / White LED chips.
+         These include voltage regulators, lithium ion/polymer battery
+         charger, wled and other features that are often used in portable
+         devices.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65217.
+
+config MFD_TPS6586X
+       bool "TI TPS6586x Power Management chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS6586X series of
+         Power Management chips.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps6586x.
+
+config MFD_TPS65910
+       bool "TI TPS65910 Power Management chip"
+       depends on I2C=y && GPIOLIB
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select IRQ_DOMAIN
+       help
+         if you say yes here you get support for the TPS65910 series of
+         Power Management chips.
+
+config MFD_TPS65912
+       bool "TI TPS65912 Power Management chip"
+       depends on GPIOLIB
+       select MFD_CORE
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips.
+
+config MFD_TPS65912_I2C
+       bool "TI TPS65912 Power Management chip with I2C"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with I2C interface.
+
+config MFD_TPS65912_SPI
+       bool "TI TPS65912 Power Management chip with SPI"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on SPI_MASTER && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with SPI interface.
+
+config MFD_TPS80031
+       bool "TI TPS80031/TPS80032 Power Management chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         If you say yes here you get support for the Texas Instruments
+         TPS80031/ TPS80032 Fully Integrated Power Management with Power
+         Path and Battery Charger. The device provides five configurable
+         step-down converters, 11 general purpose LDOs, USB OTG Module,
+         ADC, RTC, 2 PWM, System Voltage Regulator/Battery Charger with
+         Power Path from USB, 32K clock generator.
+
+config TWL4030_CORE
+       bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
+       depends on I2C=y
+       select IRQ_DOMAIN
+       select REGMAP_I2C
+       help
+         Say yes here if you have TWL4030 / TWL6030 family chip on your board.
+         This core driver provides register access and IRQ handling
+         facilities, and registers devices for the various functions
+         so that function-specific drivers can bind to them.
+
+         These multi-function chips are found on many OMAP2 and OMAP3
+         boards, providing power management, RTC, GPIO, keypad, a
+         high speed USB OTG transceiver, an audio codec (on most
+         versions) and many other features.
+
+config TWL4030_MADC
+       tristate "TI TWL4030 MADC"
+       depends on TWL4030_CORE
+       help
+       This driver provides support for triton TWL4030-MADC. The
+       driver supports both RT and SW conversion methods.
+
+       This driver can be built as a module. If so it will be
+       named twl4030-madc
+
+config TWL4030_POWER
+       bool "TI TWL4030 power resources"
+       depends on TWL4030_CORE && ARM
+       help
+         Say yes here if you want to use the power resources on the
+         TWL4030 family chips.  Most of these resources are regulators,
+         which have a separate driver; some are control signals, such
+         as clock request handshaking.
+
+         This driver uses board-specific data to initialize the resources
+         and load scripts controlling which resources are switched off/on
+         or reset when a sleep, wakeup or warm reset event occurs.
+
+config MFD_TWL4030_AUDIO
+       bool "TI TWL4030 Audio"
+       depends on TWL4030_CORE
+       select MFD_CORE
+       default n
+
+config TWL6040_CORE
+       bool "TI TWL6040 audio codec"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       default n
+       help
+         Say yes here if you want support for Texas Instruments TWL6040 audio
+         codec.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device (audio, vibra).
+
+config MENELAUS
+       bool "TI TWL92330/Menelaus PM chip"
+       depends on I2C=y && ARCH_OMAP2
+       help
+         If you say yes here you get support for the Texas Instruments
+         TWL92330/Menelaus Power Management chip. This include voltage
+         regulators, Dual slot memory card transceivers, real-time clock
+         and other features that are often used in portable devices like
+         cell phones and PDAs.
+
+config MFD_WL1273_CORE
+       tristate "TI WL1273 FM radio"
+       depends on I2C
+       select MFD_CORE
+       default n
+       help
+         This is the core driver for the TI WL1273 FM radio. This MFD
+         driver connects the radio-wl1273 V4L2 module and the wl1273
+         audio codec.
+
+config MFD_LM3533
+       tristate "TI/National Semiconductor LM3533 Lighting Power chip"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Say yes here to enable support for National Semiconductor / TI
+         LM3533 Lighting Power chips.
+
+         This driver provides common support for accessing the device;
+         additional drivers must be enabled in order to use the LED,
+         backlight or ambient-light-sensor functionality of the device.
+
+config MFD_TIMBERDALE
+       tristate "Timberdale FPGA"
+       select MFD_CORE
+       depends on PCI && GPIOLIB
+       ---help---
+       This is the core driver for the timberdale FPGA. This device is a
+       multifunction device which exposes numerous platform devices.
+
+       The timberdale FPGA can be found on the Intel Atom development board
+       for in-vehicle infontainment, called Russellville.
+
+config MFD_TC3589X
+       bool "Toshiba TC35892 and variants"
+       depends on I2C=y
+       select MFD_CORE
+       help
+         Support for the Toshiba TC35892 and variants I/O Expander.
+
+         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_TMIO
+       bool
+       default n
+
+config MFD_T7L66XB
+       bool "Toshiba T7L66XB"
+       depends on ARM && HAVE_CLK
+       select MFD_CORE
+       select MFD_TMIO
+       help
+         Support for Toshiba Mobile IO Controller T7L66XB
+
+config MFD_TC6387XB
+       bool "Toshiba TC6387XB"
+       depends on ARM && HAVE_CLK
+       select MFD_CORE
+       select MFD_TMIO
+       help
+         Support for Toshiba Mobile IO Controller TC6387XB
+
+config MFD_TC6393XB
+       bool "Toshiba TC6393XB"
+       depends on ARM && HAVE_CLK
+       select GPIOLIB
+       select MFD_CORE
+       select MFD_TMIO
+       help
+         Support for Toshiba Mobile IO Controller TC6393XB
+
+config MFD_VX855
+       tristate "VIA VX855/VX875 integrated south bridge"
+       depends on PCI
+       select MFD_CORE
+       help
+         Say yes here to enable support for various functions of the
+         VIA VX855/VX875 south bridge. You will need to enable the vx855_spi
+         and/or vx855_gpio drivers for this to do anything useful.
+
+config MFD_ARIZONA
+       select REGMAP
+       select REGMAP_IRQ
+       select MFD_CORE
+       bool
+
+config MFD_ARIZONA_I2C
+       tristate "Wolfson Microelectronics Arizona platform with I2C"
+       select MFD_ARIZONA
+       select MFD_CORE
+       select REGMAP_I2C
+       depends on I2C
+       help
+         Support for the Wolfson Microelectronics Arizona platform audio SoC
+         core functionality controlled via I2C.
+
+config MFD_ARIZONA_SPI
+       tristate "Wolfson Microelectronics Arizona platform with SPI"
+       select MFD_ARIZONA
+       select MFD_CORE
+       select REGMAP_SPI
+       depends on SPI_MASTER
+       help
+         Support for the Wolfson Microelectronics Arizona platform audio SoC
+         core functionality controlled via I2C.
+
+config MFD_WM5102
+       bool "Wolfson Microelectronics WM5102"
+       depends on MFD_ARIZONA
+       help
+         Support for Wolfson Microelectronics WM5102 low power audio SoC
+
+config MFD_WM5110
+       bool "Wolfson Microelectronics WM5110"
+       depends on MFD_ARIZONA
+       help
+         Support for Wolfson Microelectronics WM5110 low power audio SoC
+
+config MFD_WM8997
+       bool "Wolfson Microelectronics WM8997"
+       depends on MFD_ARIZONA
+       help
+         Support for Wolfson Microelectronics WM8997 low power audio SoC
+
+config MFD_WM8400
+       bool "Wolfson Microelectronics WM8400"
+       select MFD_CORE
+       depends on I2C=y
+       select REGMAP_I2C
+       help
+         Support for the Wolfson Microelecronics WM8400 PMIC and audio
+         CODEC.  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_WM831X
+       bool
+
+config MFD_WM831X_I2C
+       bool "Wolfson Microelectronics WM831x/2x PMICs with I2C"
+       select MFD_CORE
+       select MFD_WM831X
+       select REGMAP_I2C
+       select IRQ_DOMAIN
+       depends on I2C=y
+       help
+         Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+         when controlled using I2C.  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_WM831X_SPI
+       bool "Wolfson Microelectronics WM831x/2x PMICs with SPI"
+       select MFD_CORE
+       select MFD_WM831X
+       select REGMAP_SPI
+       select IRQ_DOMAIN
+       depends on SPI_MASTER
+       help
+         Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+         when controlled using SPI.  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_WM8350
+       bool
+
+config MFD_WM8350_I2C
+       bool "Wolfson Microelectronics WM8350 with I2C"
+       select MFD_WM8350
+       depends on I2C=y
+       help
+         The WM8350 is an integrated audio and power management
+         subsystem with watchdog and RTC functionality for embedded
+         systems.  This option enables core support for the WM8350 with
+         I2C as the control interface.  Additional options must be
+         selected to enable support for the functionality of the chip.
+
+config MFD_WM8994
+       bool "Wolfson Microelectronics WM8994"
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       depends on I2C=y
+       help
+         The WM8994 is a highly integrated hi-fi CODEC designed for
+         smartphone applicatiosn.  As well as audio functionality it
+         has on board GPIO and regulator functionality which is
+         supported via the relevant subsystems.  This driver provides
+         core support for the WM8994, in order to use the actual
+         functionaltiy of the device other drivers must be enabled.
+
+config MFD_STW481X
+       bool "Support for ST Microelectronics STw481x"
+       depends on I2C && ARCH_NOMADIK
+       select REGMAP_I2C
+       select MFD_CORE
+       help
+         Select this option to enable the STw481x chip driver used
+         in various ST Microelectronics and ST-Ericsson embedded
+         Nomadik series.
+
+endmenu
+endif
+
+menu "Multimedia Capabilities Port drivers"
+       depends on ARCH_SA1100
+
+config MCP
+       tristate
+
+# Interface drivers
+config MCP_SA11X0
+       tristate "Support SA11x0 MCP interface"
+       depends on ARCH_SA1100
+       select MCP
+
+# Chip drivers
+config MCP_UCB1200
+       bool "Support for UCB1200 / UCB1300"
+       depends on MCP_SA11X0
+       select MCP
+
+config MCP_UCB1200_TS
+       tristate "Touchscreen interface support"
+       depends on MCP_UCB1200 && INPUT
+
+endmenu
+
+config VEXPRESS_CONFIG
+       bool "ARM Versatile Express platform infrastructure"
+       depends on ARM || ARM64
+       help
+         Platform configuration infrastructure for the ARM Ltd.
+         Versatile Express.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
new file mode 100644 (file)
index 0000000..5aea5ef
--- /dev/null
@@ -0,0 +1,168 @@
+#
+# Makefile for multifunction miscellaneous devices
+#
+
+88pm860x-objs                  := 88pm860x-core.o 88pm860x-i2c.o
+obj-$(CONFIG_MFD_88PM860X)     += 88pm860x.o
+obj-$(CONFIG_MFD_88PM800)      += 88pm800.o 88pm80x.o
+obj-$(CONFIG_MFD_88PM805)      += 88pm805.o 88pm80x.o
+obj-$(CONFIG_MFD_SM501)                += sm501.o
+obj-$(CONFIG_MFD_ASIC3)                += asic3.o tmio_core.o
+obj-$(CONFIG_MFD_CROS_EC)      += cros_ec.o
+obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
+obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
+
+rtsx_pci-objs                  := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+obj-$(CONFIG_MFD_RTSX_PCI)     += rtsx_pci.o
+
+obj-$(CONFIG_HTC_EGPIO)                += htc-egpio.o
+obj-$(CONFIG_HTC_PASIC3)       += htc-pasic3.o
+obj-$(CONFIG_HTC_I2CPLD)       += htc-i2cpld.o
+
+obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)   += davinci_voicecodec.o
+obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
+obj-$(CONFIG_MFD_TI_SSP)       += ti-ssp.o
+obj-$(CONFIG_MFD_TI_AM335X_TSCADC)     += ti_am335x_tscadc.o
+
+obj-$(CONFIG_MFD_STA2X11)      += sta2x11-mfd.o
+obj-$(CONFIG_MFD_STMPE)                += stmpe.o
+obj-$(CONFIG_STMPE_I2C)                += stmpe-i2c.o
+obj-$(CONFIG_STMPE_SPI)                += stmpe-spi.o
+obj-$(CONFIG_MFD_TC3589X)      += tc3589x.o
+obj-$(CONFIG_MFD_T7L66XB)      += t7l66xb.o tmio_core.o
+obj-$(CONFIG_MFD_TC6387XB)     += tc6387xb.o tmio_core.o
+obj-$(CONFIG_MFD_TC6393XB)     += tc6393xb.o tmio_core.o
+
+obj-$(CONFIG_MFD_ARIZONA)      += arizona-core.o
+obj-$(CONFIG_MFD_ARIZONA)      += arizona-irq.o
+obj-$(CONFIG_MFD_ARIZONA_I2C)  += arizona-i2c.o
+obj-$(CONFIG_MFD_ARIZONA_SPI)  += arizona-spi.o
+ifneq ($(CONFIG_MFD_WM5102),n)
+obj-$(CONFIG_MFD_ARIZONA)      += wm5102-tables.o
+endif
+ifneq ($(CONFIG_MFD_WM5110),n)
+obj-$(CONFIG_MFD_ARIZONA)      += wm5110-tables.o
+endif
+ifneq ($(CONFIG_MFD_WM8997),n)
+obj-$(CONFIG_MFD_ARIZONA)      += wm8997-tables.o
+endif
+obj-$(CONFIG_MFD_WM8400)       += wm8400-core.o
+wm831x-objs                    := wm831x-core.o wm831x-irq.o wm831x-otp.o
+wm831x-objs                    += wm831x-auxadc.o
+obj-$(CONFIG_MFD_WM831X)       += wm831x.o
+obj-$(CONFIG_MFD_WM831X_I2C)   += wm831x-i2c.o
+obj-$(CONFIG_MFD_WM831X_SPI)   += wm831x-spi.o
+wm8350-objs                    := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
+wm8350-objs                    += wm8350-irq.o
+obj-$(CONFIG_MFD_WM8350)       += wm8350.o
+obj-$(CONFIG_MFD_WM8350_I2C)   += wm8350-i2c.o
+obj-$(CONFIG_MFD_WM8994)       += wm8994-core.o wm8994-irq.o wm8994-regmap.o
+
+obj-$(CONFIG_TPS6105X)         += tps6105x.o
+obj-$(CONFIG_TPS65010)         += tps65010.o
+obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65217)     += tps65217.o
+obj-$(CONFIG_MFD_TPS65910)     += tps65910.o
+tps65912-objs                   := tps65912-core.o tps65912-irq.o
+obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
+obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
+obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
+obj-$(CONFIG_MFD_TPS80031)     += tps80031.o
+obj-$(CONFIG_MENELAUS)         += menelaus.o
+
+obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
+obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
+obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
+obj-$(CONFIG_MFD_TWL4030_AUDIO)        += twl4030-audio.o
+obj-$(CONFIG_TWL6040_CORE)     += twl6040.o
+
+obj-$(CONFIG_MFD_MC13XXX)      += mc13xxx-core.o
+obj-$(CONFIG_MFD_MC13XXX_SPI)  += mc13xxx-spi.o
+obj-$(CONFIG_MFD_MC13XXX_I2C)  += mc13xxx-i2c.o
+
+obj-$(CONFIG_MFD_CORE)         += mfd-core.o
+
+obj-$(CONFIG_EZX_PCAP)         += ezx-pcap.o
+
+obj-$(CONFIG_MCP)              += mcp-core.o
+obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
+obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
+obj-$(CONFIG_MFD_SMSC)        += smsc-ece1099.o
+obj-$(CONFIG_MCP_UCB1200_TS)   += ucb1x00-ts.o
+
+ifeq ($(CONFIG_SA1100_ASSABET),y)
+obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-assabet.o
+endif
+obj-$(CONFIG_UCB1400_CORE)     += ucb1400_core.o
+
+obj-$(CONFIG_PMIC_DA903X)      += da903x.o
+
+obj-$(CONFIG_PMIC_DA9052)      += da9052-irq.o
+obj-$(CONFIG_PMIC_DA9052)      += da9052-core.o
+obj-$(CONFIG_MFD_DA9052_SPI)   += da9052-spi.o
+obj-$(CONFIG_MFD_DA9052_I2C)   += da9052-i2c.o
+
+obj-$(CONFIG_MFD_LP3943)       += lp3943.o
+obj-$(CONFIG_MFD_LP8788)       += lp8788.o lp8788-irq.o
+
+da9055-objs                    := da9055-core.o da9055-i2c.o
+obj-$(CONFIG_MFD_DA9055)       += da9055.o
+
+da9063-objs                    := da9063-core.o da9063-irq.o da9063-i2c.o
+obj-$(CONFIG_MFD_DA9063)       += da9063.o
+
+obj-$(CONFIG_MFD_MAX14577)     += max14577.o
+obj-$(CONFIG_MFD_MAX77686)     += max77686.o max77686-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
+obj-$(CONFIG_MFD_MAX8925)      += max8925.o
+obj-$(CONFIG_MFD_MAX8997)      += max8997.o max8997-irq.o
+obj-$(CONFIG_MFD_MAX8998)      += max8998.o max8998-irq.o
+
+pcf50633-objs                  := pcf50633-core.o pcf50633-irq.o
+obj-$(CONFIG_MFD_PCF50633)     += pcf50633.o
+obj-$(CONFIG_PCF50633_ADC)     += pcf50633-adc.o
+obj-$(CONFIG_PCF50633_GPIO)    += pcf50633-gpio.o
+obj-$(CONFIG_ABX500_CORE)      += abx500-core.o
+obj-$(CONFIG_AB3100_CORE)      += ab3100-core.o
+obj-$(CONFIG_AB3100_OTP)       += ab3100-otp.o
+obj-$(CONFIG_AB8500_DEBUG)     += ab8500-debugfs.o
+obj-$(CONFIG_AB8500_GPADC)     += ab8500-gpadc.o
+obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
+# ab8500-core need to come after db8500-prcmu (which provides the channel)
+obj-$(CONFIG_AB8500_CORE)      += ab8500-core.o ab8500-sysctrl.o
+obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
+obj-$(CONFIG_PMIC_ADP5520)     += adp5520.o
+obj-$(CONFIG_MFD_KEMPLD)       += kempld-core.o
+obj-$(CONFIG_LPC_SCH)          += lpc_sch.o
+obj-$(CONFIG_LPC_ICH)          += lpc_ich.o
+obj-$(CONFIG_MFD_RDC321X)      += rdc321x-southbridge.o
+obj-$(CONFIG_MFD_JANZ_CMODIO)  += janz-cmodio.o
+obj-$(CONFIG_MFD_JZ4740_ADC)   += jz4740-adc.o
+obj-$(CONFIG_MFD_TPS6586X)     += tps6586x.o
+obj-$(CONFIG_MFD_VX855)                += vx855.o
+obj-$(CONFIG_MFD_WL1273_CORE)  += wl1273-core.o
+
+si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o
+obj-$(CONFIG_MFD_SI476X_CORE)  += si476x-core.o
+
+obj-$(CONFIG_MFD_CS5535)       += cs5535-mfd.o
+obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o omap-usb-tll.o
+obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o ssbi.o
+obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
+obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
+obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
+obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
+obj-$(CONFIG_MFD_PALMAS)       += palmas.o
+obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
+obj-$(CONFIG_MFD_RC5T583)      += rc5t583.o rc5t583-irq.o
+obj-$(CONFIG_MFD_SEC_CORE)     += sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_SYSCON)       += syscon.o
+obj-$(CONFIG_MFD_LM3533)       += lm3533-core.o lm3533-ctrlbank.o
+obj-$(CONFIG_VEXPRESS_CONFIG)  += vexpress-config.o vexpress-sysreg.o
+obj-$(CONFIG_MFD_RETU)         += retu-mfd.o
+obj-$(CONFIG_MFD_AS3711)       += as3711.o
+obj-$(CONFIG_MFD_AS3722)       += as3722.o
+obj-$(CONFIG_MFD_STW481X)      += stw481x.o
diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c
new file mode 100644 (file)
index 0000000..e322268
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * TI/National Semiconductor LP3943 MFD Core Driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo 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.
+ *
+ * Driver structure:
+ *   LP3943 is an integrated device capable of driving 16 output channels.
+ *   It can be used for a GPIO expander and PWM generators.
+ *
+ *                                   LED control    General usage for a device
+ *                                   ___________   ____________________________
+ *
+ *   LP3943 MFD ---- GPIO expander    leds-gpio        eg) HW enable pin
+ *               |
+ *               --- PWM generator    leds-pwm         eg) PWM input
+ *
+ *   Internal two PWM channels are used for LED dimming effect.
+ *   And each output pin can be used as a GPIO as well.
+ *   The LED functionality can work with GPIOs or PWMs.
+ *   LEDs can be controlled with legacy leds-gpio(static brightness) or
+ *   leds-pwm drivers(dynamic brightness control).
+ *   Alternatively, it can be used for generic GPIO and PWM controller.
+ *   For example, a GPIO is HW enable pin of a device.
+ *   A PWM is input pin of a backlight device.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define LP3943_MAX_REGISTERS           0x09
+
+/* Register configuration for pin MUX */
+static const struct lp3943_reg_cfg lp3943_mux_cfg[] = {
+       /* address, mask, shift */
+       { LP3943_REG_MUX0, 0x03, 0 },
+       { LP3943_REG_MUX0, 0x0C, 2 },
+       { LP3943_REG_MUX0, 0x30, 4 },
+       { LP3943_REG_MUX0, 0xC0, 6 },
+       { LP3943_REG_MUX1, 0x03, 0 },
+       { LP3943_REG_MUX1, 0x0C, 2 },
+       { LP3943_REG_MUX1, 0x30, 4 },
+       { LP3943_REG_MUX1, 0xC0, 6 },
+       { LP3943_REG_MUX2, 0x03, 0 },
+       { LP3943_REG_MUX2, 0x0C, 2 },
+       { LP3943_REG_MUX2, 0x30, 4 },
+       { LP3943_REG_MUX2, 0xC0, 6 },
+       { LP3943_REG_MUX3, 0x03, 0 },
+       { LP3943_REG_MUX3, 0x0C, 2 },
+       { LP3943_REG_MUX3, 0x30, 4 },
+       { LP3943_REG_MUX3, 0xC0, 6 },
+};
+
+static struct mfd_cell lp3943_devs[] = {
+       {
+               .name = "lp3943-pwm",
+               .of_compatible = "ti,lp3943-pwm",
+       },
+       {
+               .name = "lp3943-gpio",
+               .of_compatible = "ti,lp3943-gpio",
+       },
+};
+
+int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read)
+{
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(lp3943->regmap, reg, &val);
+       if (ret < 0)
+               return ret;
+
+       *read = (u8)val;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lp3943_read_byte);
+
+int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data)
+{
+       return regmap_write(lp3943->regmap, reg, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_write_byte);
+
+int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data)
+{
+       return regmap_update_bits(lp3943->regmap, reg, mask, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_update_bits);
+
+static const struct regmap_config lp3943_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = LP3943_MAX_REGISTERS,
+};
+
+static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+       struct lp3943 *lp3943;
+       struct device *dev = &cl->dev;
+
+       lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL);
+       if (!lp3943)
+               return -ENOMEM;
+
+       lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config);
+       if (IS_ERR(lp3943->regmap))
+               return PTR_ERR(lp3943->regmap);
+
+       lp3943->pdata = dev_get_platdata(dev);
+       lp3943->dev = dev;
+       lp3943->mux_cfg = lp3943_mux_cfg;
+       i2c_set_clientdata(cl, lp3943);
+
+       return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs),
+                              NULL, 0, NULL);
+}
+
+static int lp3943_remove(struct i2c_client *cl)
+{
+       struct lp3943 *lp3943 = i2c_get_clientdata(cl);
+
+       mfd_remove_devices(lp3943->dev);
+       return 0;
+}
+
+static const struct i2c_device_id lp3943_ids[] = {
+       { "lp3943", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp3943_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id lp3943_of_match[] = {
+       { .compatible = "ti,lp3943", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_of_match);
+#endif
+
+static struct i2c_driver lp3943_driver = {
+       .probe = lp3943_probe,
+       .remove = lp3943_remove,
+       .driver = {
+               .name = "lp3943",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(lp3943_of_match),
+       },
+       .id_table = lp3943_ids,
+};
+
+module_i2c_driver(lp3943_driver);
+
+MODULE_DESCRIPTION("LP3943 MFD Core Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
new file mode 100644 (file)
index 0000000..c84ded5
--- /dev/null
@@ -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);
+}
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
new file mode 100644 (file)
index 0000000..a30bc15
--- /dev/null
@@ -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 const 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 = dev_get_platdata(&cl->dev);
+       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_de