Merge tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jul 2013 18:10:27 +0000 (11:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Jul 2013 18:10:27 +0000 (11:10 -0700)
Pull MFD update from Samuel Ortiz:
 "For the 3.11 merge we only have one new MFD driver for the Kontron
  PLD.

  But we also have:
   - Support for the TPS659038 PMIC from the palmas driver.
   - Intel's Coleto Creek and Avoton SoCs support from the lpc_ich
     driver.
   - RTL8411B support from the rtsx driver.
   - More DT support for the Arizona, max8998, twl4030-power and the
     ti_am335x_tsadc drivers.
   - The SSBI driver move under MFD.
   - A conversion to the devm_* API for most of the MFD drivers.
   - The twl4030-power got split from twl-core into its own module.
   - A major ti_am335x_adc cleanup, leading to a proper DT support.
   - Our regular arizona and wm* updates and cleanups from the Wolfson
     folks.
   - A better error handling and initialization, and a regulator
     subdevice addition for the 88pm80x driver.
   - A bulk platform_set_drvdata() call removal that's no longer need
     since commit 0998d0631001 ("device-core: Ensure drvdata = NULL when
     no driver is bound")

* tag 'mfd-3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (102 commits)
  mfd: sec: Provide max_register to regmap
  mfd: wm8994: Remove duplicate check for active JACKDET
  MAINTAINERS: Add include directory to MFD file patterns
  mfd: sec: Remove fields not used since regmap conversion
  watchdog: Kontron PLD watchdog timer driver
  mfd: max8998: Add support for Device Tree
  regulator: max8998: Use arrays for specifying voltages in platform data
  mfd: max8998: Add irq domain support
  regulator: palmas: Add TPS659038 support
  mfd: Kontron PLD mfd driver
  mfd: palmas: Add TPS659038 PMIC support
  mfd: palmas: Add SMPS10_BOOST feature
  mfd: palmas: Check if irq is valid
  mfd: lpc_ich: iTCO_wdt patch for Intel Coleto Creek DeviceIDs
  mfd: twl-core: Change TWL6025 references to TWL6032
  mfd: davinci_voicecodec: Fix build breakage
  mfd: vexpress: Make the driver optional for arm and arm64
  mfd: htc-egpio: Use devm_ioremap_nocache() instead of ioremap_nocache()
  mfd: davinci_voicecodec: Convert to use devm_* APIs
  mfd: twl4030-power: Fix relocking on error
  ...

97 files changed:
Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/max8998.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/twl4030-power.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/twl-regulator.txt
Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
MAINTAINERS
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
drivers/Kconfig
drivers/Makefile
drivers/iio/adc/ti_am335x_adc.c
drivers/input/touchscreen/ti_am335x_tsc.c
drivers/mfd/88pm800.c
drivers/mfd/88pm805.c
drivers/mfd/88pm80x.c
drivers/mfd/88pm860x-core.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/aat2870-core.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab3100-otp.c
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-debugfs.c
drivers/mfd/ab8500-gpadc.c
drivers/mfd/abx500-core.c
drivers/mfd/adp5520.c
drivers/mfd/arizona-core.c
drivers/mfd/arizona-i2c.c
drivers/mfd/arizona-irq.c
drivers/mfd/arizona.h
drivers/mfd/asic3.c
drivers/mfd/cros_ec.c
drivers/mfd/davinci_voicecodec.c
drivers/mfd/dbx500-prcmu-regs.h
drivers/mfd/htc-egpio.c
drivers/mfd/htc-i2cpld.c
drivers/mfd/htc-pasic3.c
drivers/mfd/intel_msic.c
drivers/mfd/janz-cmodio.c
drivers/mfd/jz4740-adc.c
drivers/mfd/kempld-core.c [new file with mode: 0644]
drivers/mfd/lpc_ich.c
drivers/mfd/max77686.c
drivers/mfd/max8925-i2c.c
drivers/mfd/max8998-irq.c
drivers/mfd/max8998.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/palmas.c
drivers/mfd/rtl8411.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/rtsx_pcr.h
drivers/mfd/sec-core.c
drivers/mfd/ssbi.c [moved from drivers/ssbi/ssbi.c with 100% similarity]
drivers/mfd/t7l66xb.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/tps65912-core.c
drivers/mfd/tps65912-i2c.c
drivers/mfd/tps65912-spi.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl4030-irq.c
drivers/mfd/twl4030-madc.c
drivers/mfd/twl4030-power.c
drivers/mfd/vexpress-sysreg.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-irq.c
drivers/mfd/wm8997-tables.c [new file with mode: 0644]
drivers/regulator/max8998.c
drivers/regulator/palmas-regulator.c
drivers/regulator/twl-regulator.c
drivers/rtc/rtc-max8998.c
drivers/ssbi/Kconfig [deleted file]
drivers/ssbi/Makefile [deleted file]
drivers/usb/phy/phy-twl6030-usb.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/kempld_wdt.c [new file with mode: 0644]
include/linux/i2c/twl.h
include/linux/input/ti_am335x_tsc.h [deleted file]
include/linux/mfd/88pm80x.h
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/arizona/core.h
include/linux/mfd/davinci_voicecodec.h
include/linux/mfd/kempld.h [new file with mode: 0644]
include/linux/mfd/max8998-private.h
include/linux/mfd/max8998.h
include/linux/mfd/palmas.h
include/linux/mfd/rtsx_pci.h
include/linux/mfd/samsung/core.h
include/linux/mfd/ti_am335x_tscadc.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/platform_data/ti_am335x_adc.h [deleted file]

diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
new file mode 100644 (file)
index 0000000..491c97b
--- /dev/null
@@ -0,0 +1,44 @@
+* TI - TSC ADC (Touschscreen and analog digital converter)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Required properties:
+- child "tsc"
+       ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
+                 support on the platform.
+       ti,x-plate-resistance: X plate resistance
+       ti,coordiante-readouts: The sequencer supports a total of 16
+                               programmable steps each step is used to
+                               read a single coordinate. A single
+                                readout is enough but multiple reads can
+                               increase the quality.
+                               A value of 5 means, 5 reads for X, 5 for
+                               Y and 2 for Z (always). This utilises 12
+                               of the 16 software steps available. The
+                               remaining 4 can be used by the ADC.
+       ti,wire-config: Different boards could have a different order for
+                       connecting wires on touchscreen. We need to provide an
+                       8 bit number where in the 1st four bits represent the
+                       analog lines and the next 4 bits represent positive/
+                       negative terminal on that input line. Notations to
+                       represent the input lines and terminals resoectively
+                       is as follows:
+                       AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+                       XP  = 0, XN = 1, YP = 2, YN = 3.
+- child "adc"
+       ti,adc-channels: List of analog inputs available for ADC.
+                        AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+
+Example:
+       tscadc: tscadc@44e0d000 {
+               compatible = "ti,am3359-tscadc";
+               tsc {
+                       ti,wires = <4>;
+                       ti,x-plate-resistance = <200>;
+                       ti,coordiante-readouts = <5>;
+                       ti,wire-config = <0x00 0x11 0x22 0x33>;
+               };
+
+               adc {
+                       ti,adc-channels = <4 5 6 7>;
+               };
+       }
diff --git a/Documentation/devicetree/bindings/mfd/max8998.txt b/Documentation/devicetree/bindings/mfd/max8998.txt
new file mode 100644 (file)
index 0000000..23a3650
--- /dev/null
@@ -0,0 +1,119 @@
+* Maxim MAX8998, National/TI LP3974 multi-function device
+
+The Maxim MAX8998 is a multi-function device which includes voltage/current
+regulators, real time clock, battery charging controller and several
+other sub-blocks. It is interfaced using an I2C interface. Each sub-block
+is addressed by the host system using different i2c slave address.
+
+PMIC sub-block
+--------------
+
+The PMIC sub-block contains a number of voltage and current regulators,
+with controllable parameters and dynamic voltage scaling capability.
+In addition, it includes a real time clock and battery charging controller
+as well. It is accessible at I2C address 0x66.
+
+Required properties:
+- compatible: Should be one of the following:
+    - "maxim,max8998" for Maxim MAX8998
+    - "national,lp3974" or "ti,lp3974" for National/TI LP3974.
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from MAX8998 are routed to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+  - First interrupt specifier is for main interrupt.
+  - Second interrupt specifier is for power-on/-off interrupt.
+- max8998,pmic-buck1-dvs-gpios: GPIO specifiers for two host gpios used
+  for buck 1 dvs. The format of the gpio specifier depends on the gpio
+  controller.
+- max8998,pmic-buck2-dvs-gpio: GPIO specifier for host gpio used
+  for buck 2 dvs. The format of the gpio specifier depends on the gpio
+  controller.
+- max8998,pmic-buck1-default-dvs-idx: Default voltage setting selected from
+  the possible 4 options selectable by the dvs gpios. The value of this
+  property should be 0, 1, 2 or 3. If not specified or out of range,
+  a default value of 0 is taken.
+- max8998,pmic-buck2-default-dvs-idx: Default voltage setting selected from
+  the possible 2 options selectable by the dvs gpios. The value of this
+  property should be 0 or 1. If not specified or out of range, a default
+  value of 0 is taken.
+- max8998,pmic-buck-voltage-lock: If present, disallows changing of
+  preprogrammed buck dvfs voltages.
+
+Additional properties required if max8998,pmic-buck1-dvs-gpios is defined:
+- max8998,pmic-buck1-dvs-voltage: An array of 4 voltage values in microvolts
+  for buck1 regulator that can be selected using dvs gpio.
+
+Additional properties required if max8998,pmic-buck2-dvs-gpio is defined:
+- max8998,pmic-buck2-dvs-voltage: An array of 2 voltage values in microvolts
+  for buck2 regulator that can be selected using dvs gpio.
+
+Regulators: All the regulators of MAX8998 to be instantiated shall be
+listed in a child node named 'regulators'. Each regulator is represented
+by a child node of the 'regulators' node.
+
+       regulator-name {
+               /* standard regulator bindings here */
+       };
+
+Following regulators of the MAX8998 PMIC block are supported. Note that
+the 'n' in regulator name, as in LDOn or BUCKn, represents the LDO or BUCK
+number as described in MAX8998 datasheet.
+
+       - LDOn
+                 - valid values for n are 2 to 17
+                 - Example: LDO2, LDO10, LDO17
+       - BUCKn
+                 - valid values for n are 1 to 4.
+                 - Example: BUCK1, BUCK2, BUCK3, BUCK4
+
+       - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+                  voltage type regulator
+
+       - ESAFEOUT1: (ldo19)
+       - ESAFEOUT2: (ld020)
+
+Standard regulator bindings are used inside regulator subnodes. Check
+  Documentation/devicetree/bindings/regulator/regulator.txt
+for more details.
+
+Example:
+
+       pmic@66 {
+               compatible = "maxim,max8998-pmic";
+               reg = <0x66>;
+               interrupt-parent = <&wakeup_eint>;
+               interrupts = <4 0>, <3 0>;
+
+               /* Buck 1 DVS settings */
+               max8998,pmic-buck1-default-dvs-idx = <0>;
+               max8998,pmic-buck1-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+                                              <&gpx0 1 1 0 0>; /* SET2 */
+               max8998,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+                                                <1000000>, <950000>;
+
+               /* Buck 2 DVS settings */
+               max8998,pmic-buck2-default-dvs-idx = <0>;
+               max8998,pmic-buck2-dvs-gpio = <&gpx0 0 3 0 0>; /* SET3 */
+               max8998,pmic-buck2-dvs-voltage = <1350000>, <1300000>;
+
+               /* Regulators to instantiate */
+               regulators {
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VDD_ALIVE_1.1V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "VDD_ARM_1.2V";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt
new file mode 100644 (file)
index 0000000..8e15ec3
--- /dev/null
@@ -0,0 +1,28 @@
+Texas Instruments TWL family (twl4030) reset and power management module
+
+The power management module inside the TWL family provides several facilities
+to control the power resources, including power scripts. For now, the
+binding only supports the complete shutdown of the system after poweroff.
+
+Required properties:
+- compatible : must be "ti,twl4030-power"
+
+Optional properties:
+- ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or
+                  SLEEP-to-OFF transition when the system poweroffs.
+
+Example:
+&i2c1 {
+       clock-frequency = <2600000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+               interrupt-parent = <&intc>;
+
+               twl_power: power {
+                       compatible = "ti,twl4030-power";
+                       ti,use_poweroff;
+               };
+       };
+};
index 658749b..75b0c16 100644 (file)
@@ -18,20 +18,20 @@ For twl6030 regulators/LDOs
   - "ti,twl6030-vdd1" for VDD1 SMPS
   - "ti,twl6030-vdd2" for VDD2 SMPS
   - "ti,twl6030-vdd3" for VDD3 SMPS
-For twl6025 regulators/LDOs
+For twl6032 regulators/LDOs
 - compatible:
-  - "ti,twl6025-ldo1" for LDO1 LDO
-  - "ti,twl6025-ldo2" for LDO2 LDO
-  - "ti,twl6025-ldo3" for LDO3 LDO
-  - "ti,twl6025-ldo4" for LDO4 LDO
-  - "ti,twl6025-ldo5" for LDO5 LDO
-  - "ti,twl6025-ldo6" for LDO6 LDO
-  - "ti,twl6025-ldo7" for LDO7 LDO
-  - "ti,twl6025-ldoln" for LDOLN LDO
-  - "ti,twl6025-ldousb" for LDOUSB LDO
-  - "ti,twl6025-smps3" for SMPS3 SMPS
-  - "ti,twl6025-smps4" for SMPS4 SMPS
-  - "ti,twl6025-vio" for VIO SMPS
+  - "ti,twl6032-ldo1" for LDO1 LDO
+  - "ti,twl6032-ldo2" for LDO2 LDO
+  - "ti,twl6032-ldo3" for LDO3 LDO
+  - "ti,twl6032-ldo4" for LDO4 LDO
+  - "ti,twl6032-ldo5" for LDO5 LDO
+  - "ti,twl6032-ldo6" for LDO6 LDO
+  - "ti,twl6032-ldo7" for LDO7 LDO
+  - "ti,twl6032-ldoln" for LDOLN LDO
+  - "ti,twl6032-ldousb" for LDOUSB LDO
+  - "ti,twl6032-smps3" for SMPS3 SMPS
+  - "ti,twl6032-smps4" for SMPS4 SMPS
+  - "ti,twl6032-vio" for VIO SMPS
 For twl4030 regulators/LDOs
 - compatible:
   - "ti,twl4030-vaux1" for VAUX1 LDO
index 36b9aed..0aee0ad 100644 (file)
@@ -8,7 +8,7 @@ TWL6030 USB COMPARATOR
    usb interrupt number that raises VBUS interrupts when the controller has to
    act as device
  - usb-supply : phandle to the regulator device tree node. It should be vusb
-   if it is twl6030 or ldousb if it is twl6025 subclass.
+   if it is twl6030 or ldousb if it is twl6032 subclass.
 
 twl6030-usb {
        compatible = "ti,twl6030-usb";
index 293c762..bb70073 100644 (file)
@@ -5500,9 +5500,12 @@ F:       include/media/mt9v032.h
 
 MULTIFUNCTION DEVICES (MFD)
 M:     Samuel Ortiz <sameo@linux.intel.com>
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
+M:     Lee Jones <lee.jones@linaro.org>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git
 S:     Supported
 F:     drivers/mfd/
+F:     include/linux/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
 M:     Chris Ball <cjb@laptop.org>
index 904ba83..3aee1a4 100644 (file)
        phy_id = <&davinci_mdio>, <1>;
        phy-mode = "rgmii-txid";
 };
+
+&tscadc {
+       status = "okay";
+       tsc {
+               ti,wires = <4>;
+               ti,x-plate-resistance = <200>;
+               ti,coordiante-readouts = <5>;
+               ti,wire-config = <0x00 0x11 0x22 0x33>;
+       };
+
+       adc {
+               ti,adc-channels = <4 5 6 7>;
+       };
+};
index 0d4df90..38b446b 100644 (file)
                        status = "disabled";
                };
 
+               tscadc: tscadc@44e0d000 {
+                       compatible = "ti,am3359-tscadc";
+                       reg = <0x44e0d000 0x1000>;
+                       interrupt-parent = <&intc>;
+                       interrupts = <16>;
+                       ti,hwmods = "adc_tsc";
+                       status = "disabled";
+
+                       tsc {
+                               compatible = "ti,am3359-tsc";
+                       };
+                       am335x_adc: adc {
+                               #io-channel-cells = <1>;
+                               compatible = "ti,am3359-adc";
+                       };
+               };
+
                gpmc: gpmc@50000000 {
                        compatible = "ti,am3352-gpmc";
                        ti,hwmods = "gpmc";
index ed2b854..ad40ab0 100644 (file)
@@ -377,12 +377,8 @@ static struct max8998_platform_data aquila_max8998_pdata = {
        .buck1_set1     = S5PV210_GPH0(3),
        .buck1_set2     = S5PV210_GPH0(4),
        .buck2_set3     = S5PV210_GPH0(5),
-       .buck1_voltage1 = 1200000,
-       .buck1_voltage2 = 1200000,
-       .buck1_voltage3 = 1200000,
-       .buck1_voltage4 = 1200000,
-       .buck2_voltage1 = 1200000,
-       .buck2_voltage2 = 1200000,
+       .buck1_voltage  = { 1200000, 1200000, 1200000, 1200000 },
+       .buck2_voltage  = { 1200000, 1200000 },
 };
 #endif
 
index 30b24ad..e5cd9fb 100644 (file)
@@ -580,12 +580,8 @@ static struct max8998_platform_data goni_max8998_pdata = {
        .buck1_set1     = S5PV210_GPH0(3),
        .buck1_set2     = S5PV210_GPH0(4),
        .buck2_set3     = S5PV210_GPH0(5),
-       .buck1_voltage1 = 1200000,
-       .buck1_voltage2 = 1200000,
-       .buck1_voltage3 = 1200000,
-       .buck1_voltage4 = 1200000,
-       .buck2_voltage1 = 1200000,
-       .buck2_voltage2 = 1200000,
+       .buck1_voltage  = { 1200000, 1200000, 1200000, 1200000 },
+       .buck2_voltage  = { 1200000, 1200000 },
 };
 #endif
 
index ae050b5..aa43b91 100644 (file)
@@ -52,8 +52,6 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
-source "drivers/ssbi/Kconfig"
-
 source "drivers/hsi/Kconfig"
 
 source "drivers/pps/Kconfig"
index 336b0ad..ab93de8 100644 (file)
@@ -117,7 +117,6 @@ obj-y                               += firmware/
 obj-$(CONFIG_CRYPTO)           += crypto/
 obj-$(CONFIG_SUPERH)           += sh/
 obj-$(CONFIG_ARCH_SHMOBILE)    += sh/
-obj-$(CONFIG_SSBI)             += ssbi/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y                          += clocksource/
 endif
index 5f9a7e7..4427e8e 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
-#include <linux/platform_data/ti_am335x_adc.h>
 
 struct tiadc_device {
        struct ti_tscadc_dev *mfd_tscadc;
        int channels;
+       u8 channel_line[8];
+       u8 channel_step[8];
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -42,10 +47,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
        writel(val, adc->mfd_tscadc->tscadc_base + reg);
 }
 
+static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
+{
+       u32 step_en;
+
+       step_en = ((1 << adc_dev->channels) - 1);
+       step_en <<= TOTAL_STEPS - adc_dev->channels + 1;
+       return step_en;
+}
+
 static void tiadc_step_config(struct tiadc_device *adc_dev)
 {
        unsigned int stepconfig;
-       int i, channels = 0, steps;
+       int i, steps;
+       u32 step_en;
 
        /*
         * There are 16 configurable steps and 8 analog input
@@ -58,43 +73,63 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
         */
 
        steps = TOTAL_STEPS - adc_dev->channels;
-       channels = TOTAL_CHANNELS - adc_dev->channels;
-
        stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
-       for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
-               tiadc_writel(adc_dev, REG_STEPCONFIG(i),
-                               stepconfig | STEPCONFIG_INP(channels));
-               tiadc_writel(adc_dev, REG_STEPDELAY(i),
+       for (i = 0; i < adc_dev->channels; i++) {
+               int chan;
+
+               chan = adc_dev->channel_line[i];
+               tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
+                               stepconfig | STEPCONFIG_INP(chan));
+               tiadc_writel(adc_dev, REG_STEPDELAY(steps),
                                STEPCONFIG_OPENDLY);
-               channels++;
+               adc_dev->channel_step[i] = steps;
+               steps++;
        }
-       tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+       step_en = get_adc_step_mask(adc_dev);
+       am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 }
 
+static const char * const chan_name_ain[] = {
+       "AIN0",
+       "AIN1",
+       "AIN2",
+       "AIN3",
+       "AIN4",
+       "AIN5",
+       "AIN6",
+       "AIN7",
+};
+
 static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 {
+       struct tiadc_device *adc_dev = iio_priv(indio_dev);
        struct iio_chan_spec *chan_array;
+       struct iio_chan_spec *chan;
        int i;
 
        indio_dev->num_channels = channels;
-       chan_array = kcalloc(indio_dev->num_channels,
+       chan_array = kcalloc(channels,
                        sizeof(struct iio_chan_spec), GFP_KERNEL);
-
        if (chan_array == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < (indio_dev->num_channels); i++) {
-               struct iio_chan_spec *chan = chan_array + i;
+       chan = chan_array;
+       for (i = 0; i < channels; i++, chan++) {
+
                chan->type = IIO_VOLTAGE;
                chan->indexed = 1;
-               chan->channel = i;
+               chan->channel = adc_dev->channel_line[i];
                chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+               chan->datasheet_name = chan_name_ain[chan->channel];
+               chan->scan_type.sign = 'u';
+               chan->scan_type.realbits = 12;
+               chan->scan_type.storagebits = 32;
        }
 
        indio_dev->channels = chan_array;
 
-       return indio_dev->num_channels;
+       return 0;
 }
 
 static void tiadc_channels_remove(struct iio_dev *indio_dev)
@@ -108,7 +143,9 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 {
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
        int i;
-       unsigned int fifo1count, readx1;
+       unsigned int fifo1count, read;
+       u32 step = UINT_MAX;
+       bool found = false;
 
        /*
         * When the sub-system is first enabled,
@@ -121,14 +158,26 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
         * Hence we need to flush out this data.
         */
 
+       for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
+               if (chan->channel == adc_dev->channel_line[i]) {
+                       step = adc_dev->channel_step[i];
+                       break;
+               }
+       }
+       if (WARN_ON_ONCE(step == UINT_MAX))
+               return -EINVAL;
+
        fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
        for (i = 0; i < fifo1count; i++) {
-               readx1 = tiadc_readl(adc_dev, REG_FIFO1);
-               if (i == chan->channel)
-                       *val = readx1 & 0xfff;
+               read = tiadc_readl(adc_dev, REG_FIFO1);
+               if (read >> 16 == step) {
+                       *val = read & 0xfff;
+                       found = true;
+               }
        }
-       tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
-
+       am335x_tsc_se_update(adc_dev->mfd_tscadc);
+       if (found == false)
+               return -EBUSY;
        return IIO_VAL_INT;
 }
 
@@ -140,13 +189,15 @@ static int tiadc_probe(struct platform_device *pdev)
 {
        struct iio_dev          *indio_dev;
        struct tiadc_device     *adc_dev;
-       struct ti_tscadc_dev    *tscadc_dev = pdev->dev.platform_data;
-       struct mfd_tscadc_board *pdata;
+       struct device_node      *node = pdev->dev.of_node;
+       struct property         *prop;
+       const __be32            *cur;
        int                     err;
+       u32                     val;
+       int                     channels = 0;
 
-       pdata = tscadc_dev->dev->platform_data;
-       if (!pdata || !pdata->adc_init) {
-               dev_err(&pdev->dev, "Could not find platform data\n");
+       if (!node) {
+               dev_err(&pdev->dev, "Could not find valid DT data.\n");
                return -EINVAL;
        }
 
@@ -158,8 +209,13 @@ static int tiadc_probe(struct platform_device *pdev)
        }
        adc_dev = iio_priv(indio_dev);
 
-       adc_dev->mfd_tscadc = tscadc_dev;
-       adc_dev->channels = pdata->adc_init->adc_channels;
+       adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
+
+       of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+               adc_dev->channel_line[channels] = val;
+               channels++;
+       }
+       adc_dev->channels = channels;
 
        indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
@@ -191,10 +247,15 @@ err_ret:
 static int tiadc_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct tiadc_device *adc_dev = iio_priv(indio_dev);
+       u32 step_en;
 
        iio_device_unregister(indio_dev);
        tiadc_channels_remove(indio_dev);
 
+       step_en = get_adc_step_mask(adc_dev);
+       am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
+
        iio_device_free(indio_dev);
 
        return 0;
@@ -205,9 +266,10 @@ static int tiadc_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
-       struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+       struct ti_tscadc_dev *tscadc_dev;
        unsigned int idle;
 
+       tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
        if (!device_may_wakeup(tscadc_dev->dev)) {
                idle = tiadc_readl(adc_dev, REG_CTRL);
                idle &= ~(CNTRLREG_TSCSSENB);
@@ -243,16 +305,22 @@ static const struct dev_pm_ops tiadc_pm_ops = {
 #define TIADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_adc_dt_ids[] = {
+       { .compatible = "ti,am3359-adc", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
+
 static struct platform_driver tiadc_driver = {
        .driver = {
-               .name   = "tiadc",
+               .name   = "TI-am335x-adc",
                .owner  = THIS_MODULE,
                .pm     = TIADC_PM_OPS,
+               .of_match_table = of_match_ptr(ti_adc_dt_ids),
        },
        .probe  = tiadc_probe,
        .remove = tiadc_remove,
 };
-
 module_platform_driver(tiadc_driver);
 
 MODULE_DESCRIPTION("TI ADC controller driver");
index 50fb129..e1c5300 100644 (file)
@@ -24,8 +24,9 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/input/ti_am335x_tsc.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 
 #define SEQ_SETTLE             275
 #define MAX_12BIT              ((1 << 12) - 1)
 
+static const int config_pins[] = {
+       STEPCONFIG_XPP,
+       STEPCONFIG_XNN,
+       STEPCONFIG_YPP,
+       STEPCONFIG_YNN,
+};
+
 struct titsc {
        struct input_dev        *input;
        struct ti_tscadc_dev    *mfd_tscadc;
@@ -40,7 +48,10 @@ struct titsc {
        unsigned int            wires;
        unsigned int            x_plate_resistance;
        bool                    pen_down;
-       int                     steps_to_configure;
+       int                     coordinate_readouts;
+       u32                     config_inp[4];
+       u32                     bit_xp, bit_xn, bit_yp, bit_yn;
+       u32                     inp_xp, inp_xn, inp_yp, inp_yn;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
        writel(val, tsc->mfd_tscadc->tscadc_base + reg);
 }
 
+static int titsc_config_wires(struct titsc *ts_dev)
+{
+       u32 analog_line[4];
+       u32 wire_order[4];
+       int i, bit_cfg;
+
+       for (i = 0; i < 4; i++) {
+               /*
+                * Get the order in which TSC wires are attached
+                * w.r.t. each of the analog input lines on the EVM.
+                */
+               analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
+               wire_order[i] = ts_dev->config_inp[i] & 0x0F;
+               if (WARN_ON(analog_line[i] > 7))
+                       return -EINVAL;
+               if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
+                       return -EINVAL;
+       }
+
+       for (i = 0; i < 4; i++) {
+               int an_line;
+               int wi_order;
+
+               an_line = analog_line[i];
+               wi_order = wire_order[i];
+               bit_cfg = config_pins[wi_order];
+               if (bit_cfg == 0)
+                       return -EINVAL;
+               switch (wi_order) {
+               case 0:
+                       ts_dev->bit_xp = bit_cfg;
+                       ts_dev->inp_xp = an_line;
+                       break;
+
+               case 1:
+                       ts_dev->bit_xn = bit_cfg;
+                       ts_dev->inp_xn = an_line;
+                       break;
+
+               case 2:
+                       ts_dev->bit_yp = bit_cfg;
+                       ts_dev->inp_yp = an_line;
+                       break;
+               case 3:
+                       ts_dev->bit_yn = bit_cfg;
+                       ts_dev->inp_yn = an_line;
+                       break;
+               }
+       }
+       return 0;
+}
+
 static void titsc_step_config(struct titsc *ts_dev)
 {
        unsigned int    config;
-       int i, total_steps;
-
-       /* Configure the Step registers */
-       total_steps = 2 * ts_dev->steps_to_configure;
+       int i;
+       int end_step;
+       u32 stepenable;
 
        config = STEPCONFIG_MODE_HWSYNC |
-                       STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+                       STEPCONFIG_AVG_16 | ts_dev->bit_xp;
        switch (ts_dev->wires) {
        case 4:
-               config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+               config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
                break;
        case 5:
-               config |= STEPCONFIG_YNN |
-                               STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
-                               STEPCONFIG_YPP;
+               config |= ts_dev->bit_yn |
+                               STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
+                               ts_dev->bit_yp;
                break;
        case 8:
-               config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+               config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
                break;
        }
 
-       for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+       /* 1 â€¦ coordinate_readouts is for X */
+       end_step = ts_dev->coordinate_readouts;
+       for (i = 0; i < end_step; i++) {
                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
        }
 
        config = 0;
        config = STEPCONFIG_MODE_HWSYNC |
-                       STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
-                       STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+                       STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+                       STEPCONFIG_INM_ADCREFM;
        switch (ts_dev->wires) {
        case 4:
-               config |= STEPCONFIG_YPP;
+               config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
                break;
        case 5:
-               config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
-                               STEPCONFIG_XNP | STEPCONFIG_YPN;
+               config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
+                               ts_dev->bit_xn | ts_dev->bit_yp;
                break;
        case 8:
-               config |= STEPCONFIG_YPP;
+               config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
                break;
        }
 
-       for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+       /* coordinate_readouts â€¦ coordinate_readouts * 2 is for Y */
+       end_step = ts_dev->coordinate_readouts * 2;
+       for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
        }
 
-       config = 0;
        /* Charge step configuration */
-       config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+       config = ts_dev->bit_xp | ts_dev->bit_yn |
                        STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
-                       STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+                       STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
 
        titsc_writel(ts_dev, REG_CHARGECONFIG, config);
        titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 
-       config = 0;
-       /* Configure to calculate pressure */
+       /* coordinate_readouts * 2 â€¦ coordinate_readouts * 2 + 2 is for Z */
        config = STEPCONFIG_MODE_HWSYNC |
-                       STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
-                       STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
-       titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
-       titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+                       STEPCONFIG_AVG_16 | ts_dev->bit_yp |
+                       ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
+                       STEPCONFIG_INP(ts_dev->inp_xp);
+       titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
+       titsc_writel(ts_dev, REG_STEPDELAY(end_step),
                        STEPCONFIG_OPENDLY);
 
-       config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
-       titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
-       titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+       end_step++;
+       config |= STEPCONFIG_INP(ts_dev->inp_yn);
+       titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
+       titsc_writel(ts_dev, REG_STEPDELAY(end_step),
                        STEPCONFIG_OPENDLY);
 
-       titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+       /* The steps1 â€¦ end and bit 0 for TS_Charge */
+       stepenable = (1 << (end_step + 2)) - 1;
+       am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
-                                   unsigned int *x, unsigned int *y)
+               u32 *x, u32 *y, u32 *z1, u32 *z2)
 {
        unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
        unsigned int prev_val_x = ~0, prev_val_y = ~0;
        unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
        unsigned int read, diff;
        unsigned int i, channel;
+       unsigned int creads = ts_dev->coordinate_readouts;
 
+       *z1 = *z2 = 0;
+       if (fifocount % (creads * 2 + 2))
+               fifocount -= fifocount % (creads * 2 + 2);
        /*
         * Delta filter is used to remove large variations in sampled
         * values from ADC. The filter tries to predict where the next
@@ -148,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
         * algorithm compares the difference with that of a present value,
         * if true the value is reported to the sub system.
         */
-       for (i = 0; i < fifocount - 1; i++) {
+       for (i = 0; i < fifocount; i++) {
                read = titsc_readl(ts_dev, REG_FIFO0);
-               channel = read & 0xf0000;
-               channel = channel >> 0x10;
-               if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
-                       read &= 0xfff;
+
+               channel = (read & 0xf0000) >> 16;
+               read &= 0xfff;
+               if (channel < creads) {
                        diff = abs(read - prev_val_x);
                        if (diff < prev_diff_x) {
                                prev_diff_x = diff;
                                *x = read;
                        }
                        prev_val_x = read;
-               }
 
-               read = titsc_readl(ts_dev, REG_FIFO1);
-               channel = read & 0xf0000;
-               channel = channel >> 0x10;
-               if ((channel >= ts_dev->steps_to_configure) &&
-                       (channel < (2 * ts_dev->steps_to_configure - 1))) {
-                       read &= 0xfff;
+               } else if (channel < creads * 2) {
                        diff = abs(read - prev_val_y);
                        if (diff < prev_diff_y) {
                                prev_diff_y = diff;
                                *y = read;
                        }
                        prev_val_y = read;
+
+               } else if (channel < creads * 2 + 1) {
+                       *z1 = read;
+
+               } else if (channel < creads * 2 + 2) {
+                       *z2 = read;
                }
        }
 }
@@ -186,23 +258,11 @@ static irqreturn_t titsc_irq(int irq, void *dev)
        unsigned int x = 0, y = 0;
        unsigned int z1, z2, z;
        unsigned int fsm;
-       unsigned int fifo1count, fifo0count;
-       int i;
 
        status = titsc_readl(ts_dev, REG_IRQSTATUS);
        if (status & IRQENB_FIFO0THRES) {
-               titsc_read_coordinates(ts_dev, &x, &y);
 
-               z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
-               z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
-
-               fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
-               for (i = 0; i < fifo1count; i++)
-                       titsc_readl(ts_dev, REG_FIFO1);
-
-               fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
-               for (i = 0; i < fifo0count; i++)
-                       titsc_readl(ts_dev, REG_FIFO0);
+               titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
 
                if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
                        /*
@@ -210,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
                         * Resistance(touch) = x plate resistance *
                         * x postion/4096 * ((z2 / z1) - 1)
                         */
-                       z = z2 - z1;
+                       z = z1 - z2;
                        z *= x;
                        z *= ts_dev->x_plate_resistance;
-                       z /= z1;
+                       z /= z2;
                        z = (z + 2047) >> 12;
 
                        if (z <= MAX_12BIT) {
@@ -248,10 +308,53 @@ static irqreturn_t titsc_irq(int irq, void *dev)
                irqclr |= IRQENB_PENUP;
        }
 
-       titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+       if (status & IRQENB_HW_PEN) {
+
+               titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
+               titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+       }
 
-       titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
-       return IRQ_HANDLED;
+       if (irqclr) {
+               titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+               am335x_tsc_se_update(ts_dev->mfd_tscadc);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+static int titsc_parse_dt(struct platform_device *pdev,
+                                       struct titsc *ts_dev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       int err;
+
+       if (!node)
+               return -EINVAL;
+
+       err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
+       if (err < 0)
+               return err;
+       switch (ts_dev->wires) {
+       case 4:
+       case 5:
+       case 8:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = of_property_read_u32(node, "ti,x-plate-resistance",
+                       &ts_dev->x_plate_resistance);
+       if (err < 0)
+               return err;
+
+       err = of_property_read_u32(node, "ti,coordiante-readouts",
+                       &ts_dev->coordinate_readouts);
+       if (err < 0)
+               return err;
+
+       return of_property_read_u32_array(node, "ti,wire-config",
+                       ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
 }
 
 /*
@@ -262,17 +365,9 @@ static int titsc_probe(struct platform_device *pdev)
 {
        struct titsc *ts_dev;
        struct input_dev *input_dev;
-       struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
-       struct mfd_tscadc_board *pdata;
+       struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
        int err;
 
-       pdata = tscadc_dev->dev->platform_data;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "Could not find platform data\n");
-               return -EINVAL;
-       }
-
        /* Allocate memory for device */
        ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
        input_dev = input_allocate_device();
@@ -286,9 +381,12 @@ static int titsc_probe(struct platform_device *pdev)
        ts_dev->mfd_tscadc = tscadc_dev;
        ts_dev->input = input_dev;
        ts_dev->irq = tscadc_dev->irq;
-       ts_dev->wires = pdata->tsc_init->wires;
-       ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
-       ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
+
+       err = titsc_parse_dt(pdev, ts_dev);
+       if (err) {
+               dev_err(&pdev->dev, "Could not find valid DT data.\n");
+               goto err_free_mem;
+       }
 
        err = request_irq(ts_dev->irq, titsc_irq,
                          0, pdev->dev.driver->name, ts_dev);
@@ -298,8 +396,14 @@ static int titsc_probe(struct platform_device *pdev)
        }
 
        titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+       err = titsc_config_wires(ts_dev);
+       if (err) {
+               dev_err(&pdev->dev, "wrong i/p wire configuration\n");
+               goto err_free_irq;
+       }
        titsc_step_config(ts_dev);
-       titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+       titsc_writel(ts_dev, REG_FIFO0THR,
+                       ts_dev->coordinate_readouts * 2 + 2 - 1);
 
        input_dev->name = "ti-tsc";
        input_dev->dev.parent = &pdev->dev;
@@ -329,11 +433,16 @@ err_free_mem:
 
 static int titsc_remove(struct platform_device *pdev)
 {
-       struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
-       struct titsc *ts_dev = tscadc_dev->tsc;
+       struct titsc *ts_dev = platform_get_drvdata(pdev);
+       u32 steps;
 
        free_irq(ts_dev->irq, ts_dev);
 
+       /* total steps followed by the enable mask */
+       steps = 2 * ts_dev->coordinate_readouts + 2;
+       steps = (1 << steps) - 1;
+       am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
+
        input_unregister_device(ts_dev->input);
 
        kfree(ts_dev);
@@ -343,10 +452,11 @@ static int titsc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int titsc_suspend(struct device *dev)
 {
-       struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
-       struct titsc *ts_dev = tscadc_dev->tsc;
+       struct titsc *ts_dev = dev_get_drvdata(dev);
+       struct ti_tscadc_dev *tscadc_dev;
        unsigned int idle;
 
+       tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
        if (device_may_wakeup(tscadc_dev->dev)) {
                idle = titsc_readl(ts_dev, REG_IRQENABLE);
                titsc_writel(ts_dev, REG_IRQENABLE,
@@ -358,9 +468,10 @@ static int titsc_suspend(struct device *dev)
 
 static int titsc_resume(struct device *dev)
 {
-       struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
-       struct titsc *ts_dev = tscadc_dev->tsc;
+       struct titsc *ts_dev = dev_get_drvdata(dev);
+       struct ti_tscadc_dev *tscadc_dev;
 
+       tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
        if (device_may_wakeup(tscadc_dev->dev)) {
                titsc_writel(ts_dev, REG_IRQWAKEUP,
                                0x00);
@@ -368,7 +479,7 @@ static int titsc_resume(struct device *dev)
        }
        titsc_step_config(ts_dev);
        titsc_writel(ts_dev, REG_FIFO0THR,
-                       ts_dev->steps_to_configure);
+                       ts_dev->coordinate_readouts * 2 + 2 - 1);
        return 0;
 }
 
@@ -381,13 +492,20 @@ static const struct dev_pm_ops titsc_pm_ops = {
 #define TITSC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_tsc_dt_ids[] = {
+       { .compatible = "ti,am3359-tsc", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
+
 static struct platform_driver ti_tsc_driver = {
        .probe  = titsc_probe,
        .remove = titsc_remove,
        .driver = {
-               .name   = "tsc",
+               .name   = "TI-am335x-tsc",
                .owner  = THIS_MODULE,
                .pm     = TITSC_PM_OPS,
+               .of_match_table = of_match_ptr(ti_tsc_dt_ids),
        },
 };
 module_platform_driver(ti_tsc_driver);
index 582bda5..6c95483 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/88pm80x.h>
 #include <linux/slab.h>
 
-#define PM800_CHIP_ID                  (0x00)
-
 /* Interrupt Registers */
 #define PM800_INT_STATUS1              (0x05)
 #define PM800_ONKEY_INT_STS1           (1 << 0)
@@ -113,20 +112,11 @@ enum {
        PM800_MAX_IRQ,
 };
 
-enum {
-       /* Procida */
-       PM800_CHIP_A0  = 0x60,
-       PM800_CHIP_A1  = 0x61,
-       PM800_CHIP_B0  = 0x62,
-       PM800_CHIP_C0  = 0x63,
-       PM800_CHIP_END = PM800_CHIP_C0,
-
-       /* Make sure to update this to the last stepping */
-       PM8XXX_CHIP_END = PM800_CHIP_END
-};
+/* PM800: generation identification number */
+#define PM800_CHIP_GEN_ID_NUM  0x3
 
 static const struct i2c_device_id pm80x_id_table[] = {
-       {"88PM800", CHIP_PM800},
+       {"88PM800", 0},
        {} /* NULL terminated */
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
@@ -167,6 +157,13 @@ static struct mfd_cell onkey_devs[] = {
         },
 };
 
+static struct mfd_cell regulator_devs[] = {
+       {
+        .name = "88pm80x-regulator",
+        .id = -1,
+       },
+};
+
 static const struct regmap_irq pm800_irqs[] = {
        /* INT0 */
        [PM800_IRQ_ONKEY] = {
@@ -315,10 +312,59 @@ out:
        return ret;
 }
 
+static int device_onkey_init(struct pm80x_chip *chip,
+                               struct pm80x_platform_data *pdata)
+{
+       int ret;
+
+       ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+                             ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
+                             NULL);
+       if (ret) {
+               dev_err(chip->dev, "Failed to add onkey subdev\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int device_rtc_init(struct pm80x_chip *chip,
+                               struct pm80x_platform_data *pdata)
+{
+       int ret;
+
+       rtc_devs[0].platform_data = pdata->rtc;
+       rtc_devs[0].pdata_size =
+                       pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+       ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+                             ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
+       if (ret) {
+               dev_err(chip->dev, "Failed to add rtc subdev\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int device_regulator_init(struct pm80x_chip *chip,
+                                          struct pm80x_platform_data *pdata)
+{
+       int ret;
+
+       ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+                             ARRAY_SIZE(regulator_devs), NULL, 0, NULL);
+       if (ret) {
+               dev_err(chip->dev, "Failed to add regulator subdev\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int device_irq_init_800(struct pm80x_chip *chip)
 {
        struct regmap *map = chip->regmap;
-       unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+       unsigned long flags = IRQF_ONESHOT;
        int data, mask, ret = -EINVAL;
 
        if (!map || !chip->irq) {
@@ -362,6 +408,7 @@ static struct regmap_irq_chip pm800_irq_chip = {
        .status_base = PM800_INT_STATUS1,
        .mask_base = PM800_INT_ENA_1,
        .ack_base = PM800_INT_STATUS1,
+       .mask_invert = 1,
 };
 
 static int pm800_pages_init(struct pm80x_chip *chip)
@@ -369,77 +416,72 @@ static int pm800_pages_init(struct pm80x_chip *chip)
        struct pm80x_subchip *subchip;
        struct i2c_client *client = chip->client;
 
+       int ret = 0;
+
        subchip = chip->subchip;
-       /* PM800 block power: i2c addr 0x31 */
-       if (subchip->power_page_addr) {
-               subchip->power_page =
-                   i2c_new_dummy(client->adapter, subchip->power_page_addr);
-               subchip->regmap_power =
-                   devm_regmap_init_i2c(subchip->power_page,
-                                        &pm80x_regmap_config);
-               i2c_set_clientdata(subchip->power_page, chip);
-       } else
-               dev_info(chip->dev,
-                        "PM800 block power 0x31: No power_page_addr\n");
-
-       /* PM800 block GPADC: i2c addr 0x32 */
-       if (subchip->gpadc_page_addr) {
-               subchip->gpadc_page = i2c_new_dummy(client->adapter,
-                                                   subchip->gpadc_page_addr);
-               subchip->regmap_gpadc =
-                   devm_regmap_init_i2c(subchip->gpadc_page,
-                                        &pm80x_regmap_config);
-               i2c_set_clientdata(subchip->gpadc_page, chip);
-       } else
-               dev_info(chip->dev,
-                        "PM800 block GPADC 0x32: No gpadc_page_addr\n");
+       if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr)
+               return -ENODEV;
+
+       /* PM800 block power page */
+       subchip->power_page = i2c_new_dummy(client->adapter,
+                                           subchip->power_page_addr);
+       if (subchip->power_page == NULL) {
+               ret = -ENODEV;
+               goto out;
+       }
 
-       return 0;
+       subchip->regmap_power = devm_regmap_init_i2c(subchip->power_page,
+                                                    &pm80x_regmap_config);
+       if (IS_ERR(subchip->regmap_power)) {
+               ret = PTR_ERR(subchip->regmap_power);
+               dev_err(chip->dev,
+                       "Failed to allocate regmap_power: %d\n", ret);
+               goto out;
+       }
+
+       i2c_set_clientdata(subchip->power_page, chip);
+
+       /* PM800 block GPADC */
+       subchip->gpadc_page = i2c_new_dummy(client->adapter,
+                                           subchip->gpadc_page_addr);
+       if (subchip->gpadc_page == NULL) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       subchip->regmap_gpadc = devm_regmap_init_i2c(subchip->gpadc_page,
+                                                    &pm80x_regmap_config);
+       if (IS_ERR(subchip->regmap_gpadc)) {
+               ret = PTR_ERR(subchip->regmap_gpadc);
+               dev_err(chip->dev,
+                       "Failed to allocate regmap_gpadc: %d\n", ret);
+               goto out;
+       }
+       i2c_set_clientdata(subchip->gpadc_page, chip);
+
+out:
+       return ret;
 }
 
 static void pm800_pages_exit(struct pm80x_chip *chip)
 {
        struct pm80x_subchip *subchip;
 
-       regmap_exit(chip->regmap);
-       i2c_unregister_device(chip->client);
-
        subchip = chip->subchip;
-       if (subchip->power_page) {
-               regmap_exit(subchip->regmap_power);
+
+       if (subchip && subchip->power_page)
                i2c_unregister_device(subchip->power_page);
-       }
-       if (subchip->gpadc_page) {
-               regmap_exit(subchip->regmap_gpadc);
+
+       if (subchip && subchip->gpadc_page)
                i2c_unregister_device(subchip->gpadc_page);
-       }
 }
 
 static int device_800_init(struct pm80x_chip *chip,
                                     struct pm80x_platform_data *pdata)
 {
-       int ret, pmic_id;
+       int ret;
        unsigned int val;
 
-       ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
-               goto out;
-       }
-
-       pmic_id = val & PM80X_VERSION_MASK;
-
-       if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) {
-               chip->version = val;
-               dev_info(chip->dev,
-                        "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val);
-       } else {
-               dev_err(chip->dev,
-                       "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
-               ret = -EINVAL;
-               goto out;
-       }
-
        /*
         * alarm wake up bit will be clear in device_irq_init(),
         * read before that
@@ -468,27 +510,22 @@ static int device_800_init(struct pm80x_chip *chip,
                goto out;
        }
 
-       ret =
-           mfd_add_devices(chip->dev, 0, &onkey_devs[0],
-                           ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
-                           NULL);
-       if (ret < 0) {
+       ret = device_onkey_init(chip, pdata);
+       if (ret) {
                dev_err(chip->dev, "Failed to add onkey subdev\n");
                goto out_dev;
-       } else
-               dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__);
-
-       if (pdata && pdata->rtc) {
-               rtc_devs[0].platform_data = pdata->rtc;
-               rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
-               ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
-                                     ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
-               if (ret < 0) {
-                       dev_err(chip->dev, "Failed to add rtc subdev\n");
-                       goto out_dev;
-               } else
-                       dev_info(chip->dev,
-                                "[%s]:Added mfd rtc_devs\n", __func__);
+       }
+
+       ret = device_rtc_init(chip, pdata);
+       if (ret) {
+               dev_err(chip->dev, "Failed to add rtc subdev\n");
+               goto out;
+       }
+
+       ret = device_regulator_init(chip, pdata);
+       if (ret) {
+               dev_err(chip->dev, "Failed to add regulators subdev\n");
+               goto out;
        }
 
        return 0;
@@ -507,7 +544,7 @@ static int pm800_probe(struct i2c_client *client,
        struct pm80x_platform_data *pdata = client->dev.platform_data;
        struct pm80x_subchip *subchip;
 
-       ret = pm80x_init(client, id);
+       ret = pm80x_init(client);
        if (ret) {
                dev_err(&client->dev, "pm800_init fail\n");
                goto out_init;
@@ -524,28 +561,31 @@ static int pm800_probe(struct i2c_client *client,
                goto err_subchip_alloc;
        }
 
-       subchip->power_page_addr = pdata->power_page_addr;
-       subchip->gpadc_page_addr = pdata->gpadc_page_addr;
+       /* pm800 has 2 addtional pages to support power and gpadc. */
+       subchip->power_page_addr = client->addr + 1;
+       subchip->gpadc_page_addr = client->addr + 2;
        chip->subchip = subchip;
 
-       ret = device_800_init(chip, pdata);
-       if (ret) {
-               dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
-               goto err_subchip_alloc;
-       }
-
        ret = pm800_pages_init(chip);
        if (ret) {
                dev_err(&client->dev, "pm800_pages_init failed!\n");
                goto err_page_init;
        }
 
+       ret = device_800_init(chip, pdata);
+       if (ret) {
+               dev_err(chip->dev, "Failed to initialize 88pm800 devices\n");
+               goto err_device_init;
+       }
+
        if (pdata->plat_config)
                pdata->plat_config(chip, pdata);
 
+       return 0;
+
+err_device_init:
+       pm800_pages_exit(chip);
 err_page_init:
-       mfd_remove_devices(chip->dev);
-       device_irq_exit_800(chip);
 err_subchip_alloc:
        pm80x_deinit();
 out_init:
@@ -567,7 +607,7 @@ static int pm800_remove(struct i2c_client *client)
 
 static struct i2c_driver pm800_driver = {
        .driver = {
-               .name = "88PM80X",
+               .name = "88PM800",
                .owner = THIS_MODULE,
                .pm = &pm80x_pm_ops,
                },
index 65d7ac0..5216022 100644 (file)
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#define PM805_CHIP_ID                  (0x00)
-
 static const struct i2c_device_id pm80x_id_table[] = {
-       {"88PM805", CHIP_PM805},
+       {"88PM805", 0},
        {} /* NULL terminated */
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
@@ -138,7 +136,7 @@ static struct regmap_irq pm805_irqs[] = {
 static int device_irq_init_805(struct pm80x_chip *chip)
 {
        struct regmap *map = chip->regmap;
-       unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+       unsigned long flags = IRQF_ONESHOT;
        int data, mask, ret = -EINVAL;
 
        if (!map || !chip->irq) {
@@ -192,7 +190,6 @@ static struct regmap_irq_chip pm805_irq_chip = {
 static int device_805_init(struct pm80x_chip *chip)
 {
        int ret = 0;
-       unsigned int val;
        struct regmap *map = chip->regmap;
 
        if (!map) {
@@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip)
                return -EINVAL;
        }
 
-       ret = regmap_read(map, PM805_CHIP_ID, &val);
-       if (ret < 0) {
-               dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
-               goto out_irq_init;
-       }
-       chip->version = val;
-
        chip->regmap_irq_chip = &pm805_irq_chip;
 
        ret = device_irq_init_805(chip);
@@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client,
        struct pm80x_chip *chip;
        struct pm80x_platform_data *pdata = client->dev.platform_data;
 
-       ret = pm80x_init(client, id);
+       ret = pm80x_init(client);
        if (ret) {
                dev_err(&client->dev, "pm805_init fail!\n");
                goto out_init;
@@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client,
 
        ret = device_805_init(chip);
        if (ret) {
-               dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id);
+               dev_err(chip->dev, "Failed to initialize 88pm805 devices\n");
                goto err_805_init;
        }
 
@@ -276,7 +266,7 @@ static int pm805_remove(struct i2c_client *client)
 
 static struct i2c_driver pm805_driver = {
        .driver = {
-               .name = "88PM80X",
+               .name = "88PM805",
                .owner = THIS_MODULE,
                .pm = &pm80x_pm_ops,
                },
index f736a46..5e72f65 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/err.h>
 
+/* 88pm80x chips have same definition for chip id register. */
+#define PM80X_CHIP_ID                  (0x00)
+#define PM80X_CHIP_ID_NUM(x)           (((x) >> 5) & 0x7)
+#define PM80X_CHIP_ID_REVISION(x)      ((x) & 0x1F)
+
+struct pm80x_chip_mapping {
+       unsigned int    id;
+       int             type;
+};
+
+static struct pm80x_chip_mapping chip_mapping[] = {
+       /* 88PM800 chip id number */
+       {0x3,   CHIP_PM800},
+       /* 88PM805 chip id number */
+       {0x0,   CHIP_PM805},
+};
+
 /*
  * workaround: some registers needed by pm805 are defined in pm800, so
  * need to use this global variable to maintain the relation between
@@ -31,12 +48,13 @@ const struct regmap_config pm80x_regmap_config = {
 };
 EXPORT_SYMBOL_GPL(pm80x_regmap_config);
 
-int pm80x_init(struct i2c_client *client,
-                                const struct i2c_device_id *id)
+
+int pm80x_init(struct i2c_client *client)
 {
        struct pm80x_chip *chip;
        struct regmap *map;
-       int ret = 0;
+       unsigned int val;
+       int i, ret = 0;
 
        chip =
            devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL);
@@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client,
                return ret;
        }
 
-       chip->id = id->driver_data;
-       if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805)
-               return -EINVAL;
-
        chip->client = client;
        chip->regmap = map;
 
@@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client,
        dev_set_drvdata(chip->dev, chip);
        i2c_set_clientdata(chip->client, chip);
 
+       ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(chip_mapping); i++) {
+               if (chip_mapping[i].id == PM80X_CHIP_ID_NUM(val)) {
+                       chip->type = chip_mapping[i].type;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(chip_mapping)) {
+               dev_err(chip->dev,
+                       "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val);
+               return -EINVAL;
+       }
+
        device_init_wakeup(&client->dev, 1);
 
        /*
index 31ca555..eeb481d 100644 (file)
@@ -1150,17 +1150,17 @@ static int pm860x_probe(struct i2c_client *client,
                return -EINVAL;
        }
 
-       chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct pm860x_chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
 
        chip->id = verify_addr(client);
-       chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
+       chip->regmap = devm_regmap_init_i2c(client, &pm860x_regmap_config);
        if (IS_ERR(chip->regmap)) {
                ret = PTR_ERR(chip->regmap);
                dev_err(&client->dev, "Failed to allocate register map: %d\n",
                                ret);
-               kfree(chip);
                return ret;
        }
        chip->client = client;
@@ -1203,8 +1203,6 @@ static int pm860x_remove(struct i2c_client *client)
                regmap_exit(chip->regmap_companion);
                i2c_unregister_device(chip->companion);
        }
-       regmap_exit(chip->regmap);
-       kfree(chip);
        return 0;
 }
 
index d54e985..aecd6dd 100644 (file)
@@ -53,7 +53,7 @@ config MFD_CROS_EC
        help
          If you say Y here you get support for the ChromeOS Embedded
          Controller (EC) providing keyboard, battery and power services.
-         You also ned to enable the driver for the bus you are using. The
+         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
@@ -242,6 +242,27 @@ config MFD_JZ4740_ADC
          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 && GENERIC_HARDIRQS
@@ -342,6 +363,7 @@ config MFD_MAX8998
        bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
        depends on I2C=y && GENERIC_HARDIRQS
        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.
@@ -419,7 +441,8 @@ config MFD_PM8XXX
 
 config MFD_PM8921_CORE
        tristate "Qualcomm PM8921 PMIC chip"
-       depends on SSBI && BROKEN
+       depends on (ARCH_MSM || HEXAGON)
+       depends on BROKEN
        select MFD_CORE
        select MFD_PM8XXX
        help
@@ -1046,6 +1069,12 @@ config MFD_WM5110
        help
          Support for Wolfson Microelectronics WM5110 low power audio SoC
 
+config MFD_WM8997
+       bool "Support 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
@@ -1144,7 +1173,8 @@ config MCP_UCB1200_TS
 endmenu
 
 config VEXPRESS_CONFIG
-       bool
+       bool "ARM Versatile Express platform infrastructure"
+       depends on ARM || ARM64
        help
          Platform configuration infrastructure for the ARM Ltd.
          Versatile Express.
index 718e94a..3c90051 100644 (file)
@@ -43,6 +43,9 @@ 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
@@ -126,6 +129,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU)      += db8500-prcmu.o
 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
@@ -140,7 +144,7 @@ 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
+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
index dfdb0a2..d4f5945 100644 (file)
@@ -312,8 +312,9 @@ static ssize_t aat2870_reg_write_file(struct file *file,
        while (*start == ' ')
                start++;
 
-       if (strict_strtoul(start, 16, &val))
-               return -EINVAL;
+       ret = kstrtoul(start, 16, &val);
+       if (ret)
+               return ret;
 
        ret = aat2870->write(aat2870, (u8)addr, (u8)val);
        if (ret)
index a9bb140..ddc669d 100644 (file)
@@ -491,7 +491,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
        char buf[32];
        ssize_t buf_size;
        int regp;
-       unsigned long user_reg;
+       u8 user_reg;
        int err;
        int i = 0;
 
@@ -514,34 +514,29 @@ static ssize_t ab3100_get_set_reg(struct file *file,
        /*
         * Advance pointer to end of string then terminate
         * the register string. This is needed to satisfy
-        * the strict_strtoul() function.
+        * the kstrtou8() function.
         */
        while ((i < buf_size) && (buf[i] != ' '))
                i++;
        buf[i] = '\0';
 
-       err = strict_strtoul(&buf[regp], 16, &user_reg);
+       err = kstrtou8(&buf[regp], 16, &user_reg);
        if (err)
                return err;
-       if (user_reg > 0xff)
-               return -EINVAL;
 
        /* Either we read or we write a register here */
        if (!priv->mode) {
                /* Reading */
-               u8 reg = (u8) user_reg;
                u8 regvalue;
 
-               ab3100_get_register_interruptible(ab3100, reg, &regvalue);
+               ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
 
                dev_info(ab3100->dev,
                         "debug read AB3100 reg[0x%02x]: 0x%02x\n",
-                        reg, regvalue);
+                        user_reg, regvalue);
        } else {
                int valp;
-               unsigned long user_value;
-               u8 reg = (u8) user_reg;
-               u8 value;
+               u8 user_value;
                u8 regvalue;
 
                /*
@@ -557,20 +552,17 @@ static ssize_t ab3100_get_set_reg(struct file *file,
                        i++;
                buf[i] = '\0';
 
-               err = strict_strtoul(&buf[valp], 16, &user_value);
+               err = kstrtou8(&buf[valp], 16, &user_value);
                if (err)
                        return err;
-               if (user_reg > 0xff)
-                       return -EINVAL;
 
-               value = (u8) user_value;
-               ab3100_set_register_interruptible(ab3100, reg, value);
-               ab3100_get_register_interruptible(ab3100, reg, &regvalue);
+               ab3100_set_register_interruptible(ab3100, user_reg, user_value);
+               ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
 
                dev_info(ab3100->dev,
                         "debug write reg[0x%02x] with 0x%02x, "
                         "after readback: 0x%02x\n",
-                        reg, value, regvalue);
+                        user_reg, user_value, regvalue);
        }
        return buf_size;
 }
index d7ce016..c9af16c 100644 (file)
@@ -187,7 +187,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
        int err = 0;
        int i;
 
-       otp = kzalloc(sizeof(struct ab3100_otp), GFP_KERNEL);
+       otp = devm_kzalloc(&pdev->dev, sizeof(struct ab3100_otp), GFP_KERNEL);
        if (!otp) {
                dev_err(&pdev->dev, "could not allocate AB3100 OTP device\n");
                return -ENOMEM;
@@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
 
        err = ab3100_otp_read(otp);
        if (err)
-               goto err_otp_read;
+               return err;
 
        dev_info(&pdev->dev, "AB3100 OTP readout registered\n");
 
@@ -208,22 +208,19 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
                err = device_create_file(&pdev->dev,
                                         &ab3100_otp_attrs[i]);
                if (err)
-                       goto err_create_file;
+                       goto err;
        }
 
        /* debugfs entries */
        err = ab3100_otp_init_debugfs(&pdev->dev, otp);
        if (err)
-               goto err_init_debugfs;
+               goto err;
 
        return 0;
 
-err_init_debugfs:
-err_create_file:
+err:
        while (--i >= 0)
                device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]);
-err_otp_read:
-       kfree(otp);
        return err;
 }
 
@@ -236,7 +233,6 @@ static int __exit ab3100_otp_remove(struct platform_device *pdev)
                device_remove_file(&pdev->dev,
                                   &ab3100_otp_attrs[i]);
        ab3100_otp_exit_debugfs(otp);
-       kfree(otp);
        return 0;
 }
 
index 258b367..b6c2cdc 100644 (file)
@@ -650,6 +650,21 @@ static struct resource ab8500_rtc_resources[] = {
        },
 };
 
+static struct resource ab8540_rtc_resources[] = {
+       {
+               .name   = "1S",
+               .start  = AB8540_INT_RTC_1S,
+               .end    = AB8540_INT_RTC_1S,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "ALARM",
+               .start  = AB8500_INT_RTC_ALARM,
+               .end    = AB8500_INT_RTC_ALARM,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct resource ab8500_poweronkey_db_resources[] = {
        {
                .name   = "ONKEY_DBF",
@@ -1050,6 +1065,10 @@ static struct mfd_cell ab8500_devs[] = {
                .name = "ab8500-sysctrl",
                .of_compatible = "stericsson,ab8500-sysctrl",
        },
+       {
+               .name = "ab8500-ext-regulator",
+               .of_compatible = "stericsson,ab8500-ext-regulator",
+       },
        {
                .name = "ab8500-regulator",
                .of_compatible = "stericsson,ab8500-regulator",
@@ -1098,10 +1117,6 @@ static struct mfd_cell ab8500_devs[] = {
                .of_compatible = "stericsson,ab8500-pwm",
                .id = 3,
        },
-       {
-               .name = "ab8500-leds",
-               .of_compatible = "stericsson,ab8500-leds",
-       },
        {
                .name = "ab8500-denc",
                .of_compatible = "stericsson,ab8500-denc",
@@ -1124,6 +1139,7 @@ static struct mfd_cell ab8500_devs[] = {
        },
        {
                .name = "ab8500-codec",
+               .of_compatible = "stericsson,ab8500-codec",
        },
 };
 
@@ -1138,6 +1154,9 @@ static struct mfd_cell ab9540_devs[] = {
        {
                .name = "ab8500-sysctrl",
        },
+       {
+               .name = "ab8500-ext-regulator",
+       },
        {
                .name = "ab8500-regulator",
        },
@@ -1170,9 +1189,6 @@ static struct mfd_cell ab9540_devs[] = {
                .name = "ab8500-pwm",
                .id = 1,
        },
-       {
-               .name = "ab8500-leds",
-       },
        {
                .name = "abx500-temp",
                .num_resources = ARRAY_SIZE(ab8500_temp_resources),
@@ -1241,9 +1257,6 @@ static struct mfd_cell ab8505_devs[] = {
                .name = "ab8500-pwm",
                .id = 1,
        },
-       {
-               .name = "ab8500-leds",
-       },
        {
                .name = "pinctrl-ab8505",
        },
@@ -1273,6 +1286,9 @@ static struct mfd_cell ab8540_devs[] = {
        {
                .name = "ab8500-sysctrl",
        },
+       {
+               .name = "ab8500-ext-regulator",
+       },
        {
                .name = "ab8500-regulator",
        },
@@ -1286,11 +1302,6 @@ static struct mfd_cell ab8540_devs[] = {
                .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
                .resources = ab8505_gpadc_resources,
        },
-       {
-               .name = "ab8500-rtc",
-               .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
-               .resources = ab8500_rtc_resources,
-       },
        {
                .name = "ab8500-acc-det",
                .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
@@ -1305,9 +1316,6 @@ static struct mfd_cell ab8540_devs[] = {
                .name = "ab8500-pwm",
                .id = 1,
        },
-       {
-               .name = "ab8500-leds",
-       },
        {
                .name = "abx500-temp",
                .num_resources = ARRAY_SIZE(ab8500_temp_resources),
@@ -1331,6 +1339,24 @@ static struct mfd_cell ab8540_devs[] = {
        },
 };
 
+static struct mfd_cell ab8540_cut1_devs[] = {
+       {
+               .name = "ab8500-rtc",
+               .of_compatible = "stericsson,ab8500-rtc",
+               .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
+               .resources = ab8500_rtc_resources,
+       },
+};
+
+static struct mfd_cell ab8540_cut2_devs[] = {
+       {
+               .name = "ab8540-rtc",
+               .of_compatible = "stericsson,ab8540-rtc",
+               .num_resources = ARRAY_SIZE(ab8540_rtc_resources),
+               .resources = ab8540_rtc_resources,
+       },
+};
+
 static ssize_t show_chip_id(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -1734,11 +1760,22 @@ static int ab8500_probe(struct platform_device *pdev)
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
                                ARRAY_SIZE(ab9540_devs), NULL,
                                ab8500->irq_base, ab8500->domain);
-       else if (is_ab8540(ab8500))
+       else if (is_ab8540(ab8500)) {
                ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
                              ARRAY_SIZE(ab8540_devs), NULL,
-                             ab8500->irq_base, ab8500->domain);
-       else if (is_ab8505(ab8500))
+                             ab8500->irq_base, NULL);
+               if (ret)
+                       return ret;
+
+               if (is_ab8540_1p2_or_earlier(ab8500))
+                       ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
+                             ARRAY_SIZE(ab8540_cut1_devs), NULL,
+                             ab8500->irq_base, NULL);
+               else /* ab8540 >= cut2 */
+                       ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
+                             ARRAY_SIZE(ab8540_cut2_devs), NULL,
+                             ab8500->irq_base, NULL);
+       } else if (is_ab8505(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
                              ARRAY_SIZE(ab8505_devs), NULL,
                              ab8500->irq_base, ab8500->domain);
index 37b7ce4..7d1f1b0 100644 (file)
@@ -2757,7 +2757,7 @@ static ssize_t show_irq(struct device *dev,
        unsigned int irq_index;
        int err;
 
-       err = strict_strtoul(attr->attr.name, 0, &name);
+       err = kstrtoul(attr->attr.name, 0, &name);
        if (err)
                return err;
 
@@ -2937,7 +2937,6 @@ static struct dentry *ab8500_gpadc_dir;
 static int ab8500_debug_probe(struct platform_device *plf)
 {
        struct dentry *file;
-       int ret = -ENOMEM;
        struct ab8500 *ab8500;
        struct resource *res;
        debug_bank = AB8500_MISC;
@@ -2946,24 +2945,26 @@ static int ab8500_debug_probe(struct platform_device *plf)
        ab8500 = dev_get_drvdata(plf->dev.parent);
        num_irqs = ab8500->mask_size;
 
-       irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL);
+       irq_count = devm_kzalloc(&plf->dev,
+                                sizeof(*irq_count)*num_irqs, GFP_KERNEL);
        if (!irq_count)
                return -ENOMEM;
 
-       dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
+       dev_attr = devm_kzalloc(&plf->dev,
+                               sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
        if (!dev_attr)
-               goto out_freeirq_count;
+               return -ENOMEM;
 
-       event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL);
+       event_name = devm_kzalloc(&plf->dev,
+                                 sizeof(*event_name)*num_irqs, GFP_KERNEL);
        if (!event_name)
-               goto out_freedev_attr;
+               return -ENOMEM;
 
        res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
        if (!res) {
                dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
                        irq_first);
-               ret = -ENXIO;
-               goto out_freeevent_name;
+               return ENXIO;
        }
        irq_ab8500 = res->start;
 
@@ -2971,16 +2972,14 @@ static int ab8500_debug_probe(struct platform_device *plf)
        if (irq_first < 0) {
                dev_err(&plf->dev, "First irq not found, err %d\n",
                        irq_first);
-               ret = irq_first;
-               goto out_freeevent_name;
+               return irq_first;
        }
 
        irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
        if (irq_last < 0) {
                dev_err(&plf->dev, "Last irq not found, err %d\n",
                        irq_last);
-               ret = irq_last;
-               goto out_freeevent_name;
+               return irq_last;
        }
 
        ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
@@ -3189,22 +3188,13 @@ err:
        if (ab8500_dir)
                debugfs_remove_recursive(ab8500_dir);
        dev_err(&plf->dev, "failed to create debugfs entries.\n");
-out_freeevent_name:
-       kfree(event_name);
-out_freedev_attr:
-       kfree(dev_attr);
-out_freeirq_count:
-       kfree(irq_count);
 
-       return ret;
+       return -ENOMEM;
 }
 
 static int ab8500_debug_remove(struct platform_device *plf)
 {
        debugfs_remove_recursive(ab8500_dir);
-       kfree(event_name);
-       kfree(dev_attr);
-       kfree(irq_count);
 
        return 0;
 }
index 3598b0e..7623e91 100644 (file)
@@ -919,7 +919,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
        int ret = 0;
        struct ab8500_gpadc *gpadc;
 
-       gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL);
+       gpadc = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_gpadc), GFP_KERNEL);
        if (!gpadc) {
                dev_err(&pdev->dev, "Error: No memory\n");
                return -ENOMEM;
@@ -999,8 +999,6 @@ fail_irq:
        free_irq(gpadc->irq_sw, gpadc);
        free_irq(gpadc->irq_hw, gpadc);
 fail:
-       kfree(gpadc);
-       gpadc = NULL;
        return ret;
 }
 
@@ -1025,8 +1023,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
 
        pm_runtime_put_noidle(gpadc->dev);
 
-       kfree(gpadc);
-       gpadc = NULL;
        return 0;
 }
 
index 3714acb..f3a15aa 100644 (file)
@@ -36,7 +36,9 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
 {
        struct abx500_device_entry *dev_entry;
 
-       dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL);
+       dev_entry = devm_kzalloc(dev,
+                                sizeof(struct abx500_device_entry),
+                                GFP_KERNEL);
        if (!dev_entry) {
                dev_err(dev, "register_ops kzalloc failed");
                return -ENOMEM;
@@ -54,12 +56,8 @@ void abx500_remove_ops(struct device *dev)
        struct abx500_device_entry *dev_entry, *tmp;
 
        list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)
-       {
-               if (dev_entry->dev == dev) {
+               if (dev_entry->dev == dev)
                        list_del(&dev_entry->list);
-                       kfree(dev_entry);
-               }
-       }
 }
 EXPORT_SYMBOL(abx500_remove_ops);
 
index 0d2eba0..28346ad 100644 (file)
@@ -223,7 +223,7 @@ static int adp5520_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
                return -ENOMEM;
 
@@ -244,7 +244,7 @@ static int adp5520_probe(struct i2c_client *client,
                if (ret) {
                        dev_err(&client->dev, "failed to request irq %d\n",
                                        chip->irq);
-                       goto out_free_chip;
+                       return ret;
                }
        }
 
@@ -302,9 +302,6 @@ out_free_irq:
        if (chip->irq)
                free_irq(chip->irq, chip);
 
-out_free_chip:
-       kfree(chip);
-
        return ret;
 }
 
@@ -317,7 +314,6 @@ static int adp5520_remove(struct i2c_client *client)
 
        adp5520_remove_subdevs(chip);
        adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
-       kfree(chip);
        return 0;
 }
 
index 74b4481..89a1153 100644 (file)
@@ -554,6 +554,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
 const struct of_device_id arizona_of_match[] = {
        { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
        { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
+       { .compatible = "wlf,wm8997", .data = (void *)WM8997 },
        {},
 };
 EXPORT_SYMBOL_GPL(arizona_of_match);
@@ -586,6 +587,15 @@ static struct mfd_cell wm5110_devs[] = {
        { .name = "wm5110-codec" },
 };
 
+static struct mfd_cell wm8997_devs[] = {
+       { .name = "arizona-micsupp" },
+       { .name = "arizona-extcon" },
+       { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
+       { .name = "arizona-pwm" },
+       { .name = "wm8997-codec" },
+};
+
 int arizona_dev_init(struct arizona *arizona)
 {
        struct device *dev = arizona->dev;
@@ -608,6 +618,7 @@ int arizona_dev_init(struct arizona *arizona)
        switch (arizona->type) {
        case WM5102:
        case WM5110:
+       case WM8997:
                for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
                        arizona->core_supplies[i].supply
                                = wm5102_core_supplies[i];
@@ -683,6 +694,7 @@ int arizona_dev_init(struct arizona *arizona)
        switch (reg) {
        case 0x5102:
        case 0x5110:
+       case 0x8997:
                break;
        default:
                dev_err(arizona->dev, "Unknown device ID: %x\n", reg);
@@ -767,6 +779,17 @@ int arizona_dev_init(struct arizona *arizona)
                }
                apply_patch = wm5110_patch;
                break;
+#endif
+#ifdef CONFIG_MFD_WM8997
+       case 0x8997:
+               type_name = "WM8997";
+               if (arizona->type != WM8997) {
+                       dev_err(arizona->dev, "WM8997 registered as %d\n",
+                               arizona->type);
+                       arizona->type = WM8997;
+               }
+               apply_patch = wm8997_patch;
+               break;
 #endif
        default:
                dev_err(arizona->dev, "Unknown device ID %x\n", reg);
@@ -934,6 +957,10 @@ int arizona_dev_init(struct arizona *arizona)
                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
                                      ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
                break;
+       case WM8997:
+               ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
+                                     ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
+               break;
        }
 
        if (ret != 0) {
index deb267e..51dbabf 100644 (file)
@@ -44,6 +44,11 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
        case WM5110:
                regmap_config = &wm5110_i2c_regmap;
                break;
+#endif
+#ifdef CONFIG_MFD_WM8997
+       case WM8997:
+               regmap_config = &wm8997_i2c_regmap;
+               break;
 #endif
        default:
                dev_err(&i2c->dev, "Unknown device type %ld\n",
@@ -80,6 +85,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c)
 static const struct i2c_device_id arizona_i2c_id[] = {
        { "wm5102", WM5102 },
        { "wm5110", WM5110 },
+       { "wm8997", WM8997 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);
index 64cd9b6..88758ab 100644 (file)
@@ -208,6 +208,14 @@ int arizona_irq_init(struct arizona *arizona)
                ctrlif_error = false;
                break;
 #endif
+#ifdef CONFIG_MFD_WM8997
+       case WM8997:
+               aod = &wm8997_aod;
+               irq = &wm8997_irq;
+
+               ctrlif_error = false;
+               break;
+#endif
        default:
                BUG_ON("Unknown Arizona class device" == NULL);
                return -EINVAL;
index db55d98..b4cef77 100644 (file)
@@ -25,6 +25,8 @@ extern const struct regmap_config wm5102_spi_regmap;
 extern const struct regmap_config wm5110_i2c_regmap;
 extern const struct regmap_config wm5110_spi_regmap;
 
+extern const struct regmap_config wm8997_i2c_regmap;
+
 extern const struct dev_pm_ops arizona_pm_ops;
 
 extern const struct of_device_id arizona_of_match[];
@@ -35,6 +37,9 @@ extern const struct regmap_irq_chip wm5102_irq;
 extern const struct regmap_irq_chip wm5110_aod;
 extern const struct regmap_irq_chip wm5110_irq;
 
+extern const struct regmap_irq_chip wm8997_aod;
+extern const struct regmap_irq_chip wm8997_irq;
+
 int arizona_dev_init(struct arizona *arizona);
 int arizona_dev_exit(struct arizona *arizona);
 int arizona_irq_init(struct arizona *arizona);
index 1b15986..9532f74 100644 (file)
@@ -958,7 +958,8 @@ static int __init asic3_probe(struct platform_device *pdev)
        unsigned long clksel;
        int ret = 0;
 
-       asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
+       asic = devm_kzalloc(&pdev->dev,
+                           sizeof(struct asic3), GFP_KERNEL);
        if (asic == NULL) {
                printk(KERN_ERR "kzalloc failed\n");
                return -ENOMEM;
@@ -970,16 +971,14 @@ static int __init asic3_probe(struct platform_device *pdev)
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
-               ret = -ENOMEM;
                dev_err(asic->dev, "no MEM resource\n");
-               goto out_free;
+               return -ENOMEM;
        }
 
        asic->mapping = ioremap(mem->start, resource_size(mem));
        if (!asic->mapping) {
-               ret = -ENOMEM;
                dev_err(asic->dev, "Couldn't ioremap\n");
-               goto out_free;
+               return -ENOMEM;
        }
 
        asic->irq_base = pdata->irq_base;
@@ -1033,9 +1032,6 @@ static int __init asic3_probe(struct platform_device *pdev)
  out_unmap:
        iounmap(asic->mapping);
 
- out_free:
-       kfree(asic);
-
        return ret;
 }
 
@@ -1058,8 +1054,6 @@ static int asic3_remove(struct platform_device *pdev)
 
        iounmap(asic->mapping);
 
-       kfree(asic);
-
        return 0;
 }
 
index 10cd14e..1f36885 100644 (file)
@@ -104,23 +104,19 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
        ec_dev->command_sendrecv = cros_ec_command_sendrecv;
 
        if (ec_dev->din_size) {
-               ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL);
-               if (!ec_dev->din) {
-                       err = -ENOMEM;
-                       goto fail_din;
-               }
+               ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
+               if (!ec_dev->din)
+                       return -ENOMEM;
        }
        if (ec_dev->dout_size) {
-               ec_dev->dout = kmalloc(ec_dev->dout_size, GFP_KERNEL);
-               if (!ec_dev->dout) {
-                       err = -ENOMEM;
-                       goto fail_dout;
-               }
+               ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
+               if (!ec_dev->dout)
+                       return -ENOMEM;
        }
 
        if (!ec_dev->irq) {
                dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
-               goto fail_irq;
+               return err;
        }
 
        err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
@@ -128,7 +124,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
                                   "chromeos-ec", ec_dev);
        if (err) {
                dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
-               goto fail_irq;
+               return err;
        }
 
        err = mfd_add_devices(dev, 0, cros_devs,
@@ -145,11 +141,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
 fail_mfd:
        free_irq(ec_dev->irq, ec_dev);
-fail_irq:
-       kfree(ec_dev->dout);
-fail_dout:
-       kfree(ec_dev->din);
-fail_din:
+
        return err;
 }
 EXPORT_SYMBOL(cros_ec_register);
@@ -158,8 +150,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
        mfd_remove_devices(ec_dev->dev);
        free_irq(ec_dev->irq, ec_dev);
-       kfree(ec_dev->dout);
-       kfree(ec_dev->din);
 
        return 0;
 }
index c60ab0c..fb64398 100644 (file)
@@ -46,56 +46,39 @@ void davinci_vc_write(struct davinci_vc *davinci_vc,
 static int __init davinci_vc_probe(struct platform_device *pdev)
 {
        struct davinci_vc *davinci_vc;
-       struct resource *res, *mem;
+       struct resource *res;
        struct mfd_cell *cell = NULL;
        int ret;
 
-       davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL);
+       davinci_vc = devm_kzalloc(&pdev->dev,
+                                 sizeof(struct davinci_vc), GFP_KERNEL);
        if (!davinci_vc) {
                dev_dbg(&pdev->dev,
                            "could not allocate memory for private data\n");
                return -ENOMEM;
        }
 
-       davinci_vc->clk = clk_get(&pdev->dev, NULL);
+       davinci_vc->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(davinci_vc->clk)) {
                dev_dbg(&pdev->dev,
                            "could not get the clock for voice codec\n");
-               ret = -ENODEV;
-               goto fail1;
+               return -ENODEV;
        }
        clk_enable(davinci_vc->clk);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no mem resource\n");
-               ret = -ENODEV;
-               goto fail2;
-       }
 
-       davinci_vc->pbase = res->start;
-       davinci_vc->base_size = resource_size(res);
-
-       mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size,
-                                pdev->name);
-       if (!mem) {
-               dev_err(&pdev->dev, "VCIF region already claimed\n");
-               ret = -EBUSY;
-               goto fail2;
-       }
-
-       davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size);
-       if (!davinci_vc->base) {
-               dev_err(&pdev->dev, "can't ioremap mem resource.\n");
-               ret = -ENOMEM;
-               goto fail3;
+       davinci_vc->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(davinci_vc->base)) {
+               ret = PTR_ERR(davinci_vc->base);
+               goto fail;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (!res) {
                dev_err(&pdev->dev, "no DMA resource\n");
                ret = -ENXIO;
-               goto fail4;
+               goto fail;
        }
 
        davinci_vc->davinci_vcif.dma_tx_channel = res->start;
@@ -106,7 +89,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
        if (!res) {
                dev_err(&pdev->dev, "no DMA resource\n");
                ret = -ENXIO;
-               goto fail4;
+               goto fail;
        }
 
        davinci_vc->davinci_vcif.dma_rx_channel = res->start;
@@ -132,21 +115,13 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
                              DAVINCI_VC_CELLS, NULL, 0, NULL);
        if (ret != 0) {
                dev_err(&pdev->dev, "fail to register client devices\n");
-               goto fail4;
+               goto fail;
        }
 
        return 0;
 
-fail4:
-       iounmap(davinci_vc->base);
-fail3:
-       release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
-fail2:
+fail:
        clk_disable(davinci_vc->clk);
-       clk_put(davinci_vc->clk);
-       davinci_vc->clk = NULL;
-fail1:
-       kfree(davinci_vc);
 
        return ret;
 }
@@ -157,14 +132,7 @@ static int davinci_vc_remove(struct platform_device *pdev)
 
        mfd_remove_devices(&pdev->dev);
 
-       iounmap(davinci_vc->base);
-       release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
-
        clk_disable(davinci_vc->clk);
-       clk_put(davinci_vc->clk);
-       davinci_vc->clk = NULL;
-
-       kfree(davinci_vc);
 
        return 0;
 }
index ca355dd..4f6f0fa 100644 (file)
@@ -16,8 +16,8 @@
 #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
 
 #define PRCM_ACLK_MGT          (0x004)
-#define PRCM_SVACLK_MGT                (0x008)
-#define PRCM_SIACLK_MGT                (0x00C)
+#define PRCM_SVAMMCSPCLK_MGT   (0x008)
+#define PRCM_SIAMMDSPCLK_MGT   (0x00C)
 #define PRCM_SGACLK_MGT                (0x014)
 #define PRCM_UARTCLK_MGT       (0x018)
 #define PRCM_MSP02CLK_MGT      (0x01C)
index bbaec0c..26aca54 100644 (file)
@@ -270,7 +270,7 @@ static int __init egpio_probe(struct platform_device *pdev)
        int               ret;
 
        /* Initialize ei data structure. */
-       ei = kzalloc(sizeof(*ei), GFP_KERNEL);
+       ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL);
        if (!ei)
                return -ENOMEM;
 
@@ -286,7 +286,8 @@ static int __init egpio_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                goto fail;
-       ei->base_addr = ioremap_nocache(res->start, resource_size(res));
+       ei->base_addr = devm_ioremap_nocache(&pdev->dev, res->start,
+                                            resource_size(res));
        if (!ei->base_addr)
                goto fail;
        pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
@@ -306,7 +307,9 @@ static int __init egpio_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, ei);
 
        ei->nchips = pdata->num_chips;
-       ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
+       ei->chip = devm_kzalloc(&pdev->dev,
+                               sizeof(struct egpio_chip) * ei->nchips,
+                               GFP_KERNEL);
        if (!ei->chip) {
                ret = -ENOMEM;
                goto fail;
@@ -361,7 +364,6 @@ static int __init egpio_probe(struct platform_device *pdev)
 
 fail:
        printk(KERN_ERR "EGPIO failed to setup\n");
-       kfree(ei);
        return ret;
 }
 
@@ -379,9 +381,6 @@ static int __exit egpio_remove(struct platform_device *pdev)
                irq_set_chained_handler(ei->chained_irq, NULL);
                device_init_wakeup(&pdev->dev, 0);
        }
-       iounmap(ei->base_addr);
-       kfree(ei->chip);
-       kfree(ei);
 
        return 0;
 }
index 324187c..c9dfce6 100644 (file)
@@ -514,8 +514,8 @@ static int htcpld_setup_chips(struct platform_device *pdev)
 
        /* Setup each chip's output GPIOs */
        htcpld->nchips = pdata->num_chip;
-       htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
-                              GFP_KERNEL);
+       htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips,
+                                   GFP_KERNEL);
        if (!htcpld->chip) {
                dev_warn(dev, "Unable to allocate memory for chips\n");
                return -ENOMEM;
@@ -580,12 +580,11 @@ static int htcpld_core_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
+       htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL);
        if (!htcpld)
                return -ENOMEM;
 
        /* Find chained irq */
-       ret = -EINVAL;
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res) {
                int flags;
@@ -598,7 +597,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
                                           flags, pdev->name, htcpld);
                if (ret) {
                        dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
-                       goto fail;
+                       return ret;
                } else
                        device_init_wakeup(dev, 0);
        }
@@ -609,7 +608,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
        /* Setup the htcpld chips */
        ret = htcpld_setup_chips(pdev);
        if (ret)
-               goto fail;
+               return ret;
 
        /* Request the GPIO(s) for the int reset and set them up */
        if (pdata->int_reset_gpio_hi) {
@@ -644,10 +643,6 @@ static int htcpld_core_probe(struct platform_device *pdev)
 
        dev_info(dev, "Initialized successfully\n");
        return 0;
-
-fail:
-       kfree(htcpld);
-       return ret;
 }
 
 /* The I2C Driver -- used internally */
index 0285fce..0a5e85f 100644 (file)
@@ -147,7 +147,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
        if (!request_mem_region(r->start, resource_size(r), "pasic3"))
                return -EBUSY;
 
-       asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
+       asic = devm_kzalloc(dev, sizeof(struct pasic3_data), GFP_KERNEL);
        if (!asic)
                return -ENOMEM;
 
@@ -156,7 +156,6 @@ static int __init pasic3_probe(struct platform_device *pdev)
        asic->mapping = ioremap(r->start, resource_size(r));
        if (!asic->mapping) {
                dev_err(dev, "couldn't ioremap PASIC3\n");
-               kfree(asic);
                return -ENOMEM;
        }
 
@@ -195,7 +194,6 @@ static int pasic3_remove(struct platform_device *pdev)
        iounmap(asic->mapping);
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(r->start, resource_size(r));
-       kfree(asic);
        return 0;
 }
 
index d8d5137..4f2462f 100644 (file)
@@ -438,7 +438,6 @@ static int intel_msic_remove(struct platform_device *pdev)
        struct intel_msic *msic = platform_get_drvdata(pdev);
 
        intel_msic_remove_devices(msic);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index 45ece11..fcbb2e9 100644 (file)
@@ -183,11 +183,10 @@ static int cmodio_pci_probe(struct pci_dev *dev,
        struct cmodio_device *priv;
        int ret;
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                dev_err(&dev->dev, "unable to allocate private data\n");
-               ret = -ENOMEM;
-               goto out_return;
+               return -ENOMEM;
        }
 
        pci_set_drvdata(dev, priv);
@@ -197,7 +196,7 @@ static int cmodio_pci_probe(struct pci_dev *dev,
        ret = pci_enable_device(dev);
        if (ret) {
                dev_err(&dev->dev, "unable to enable device\n");
-               goto out_free_priv;
+               return ret;
        }
 
        pci_set_master(dev);
@@ -248,9 +247,7 @@ out_pci_release_regions:
        pci_release_regions(dev);
 out_pci_disable_device:
        pci_disable_device(dev);
-out_free_priv:
-       kfree(priv);
-out_return:
+
        return ret;
 }
 
@@ -263,7 +260,6 @@ static void cmodio_pci_remove(struct pci_dev *dev)
        iounmap(priv->ctrl);
        pci_release_regions(dev);
        pci_disable_device(dev);
-       kfree(priv);
 }
 
 #define PCI_VENDOR_ID_JANZ             0x13c3
index e80587f..3c0e8cf 100644 (file)
@@ -86,13 +86,13 @@ static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
 static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc)
 {
        if (atomic_inc_return(&adc->clk_ref) == 1)
-               clk_enable(adc->clk);
+               clk_prepare_enable(adc->clk);
 }
 
 static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc)
 {
        if (atomic_dec_return(&adc->clk_ref) == 0)
-               clk_disable(adc->clk);
+               clk_disable_unprepare(adc->clk);
 }
 
 static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine,
@@ -294,7 +294,6 @@ static int jz4740_adc_probe(struct platform_device *pdev)
 err_clk_put:
        clk_put(adc->clk);
 err_iounmap:
-       platform_set_drvdata(pdev, NULL);
        iounmap(adc->base);
 err_release_mem_region:
        release_mem_region(adc->mem->start, resource_size(adc->mem));
@@ -317,8 +316,6 @@ static int jz4740_adc_remove(struct platform_device *pdev)
 
        clk_put(adc->clk);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
new file mode 100644 (file)
index 0000000..686a456
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Kontron PLD MFD core driver
+ *
+ * Copyright (c) 2010-2013 Kontron Europe GmbH
+ * Author: Michael Brunner <michael.brunner@kontron.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/kempld.h>
+#include <linux/module.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define MAX_ID_LEN 4
+static char force_device_id[MAX_ID_LEN + 1] = "";
+module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
+MODULE_PARM_DESC(force_device_id, "Override detected product");
+
+/*
+ * Get hardware mutex to block firmware from accessing the pld.
+ * It is possible for the firmware may hold the mutex for an extended length of
+ * time. This function will block until access has been granted.
+ */
+static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
+{
+       /* The mutex bit will read 1 until access has been granted */
+       while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
+               msleep(1);
+}
+
+static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
+{
+       /* The harware mutex is released when 1 is written to the mutex bit. */
+       iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+}
+
+static int kempld_get_info_generic(struct kempld_device_data *pld)
+{
+       u16 version;
+       u8 spec;
+
+       kempld_get_mutex(pld);
+
+       version = kempld_read16(pld, KEMPLD_VERSION);
+       spec = kempld_read8(pld, KEMPLD_SPEC);
+       pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR);
+
+       pld->info.minor = KEMPLD_VERSION_GET_MINOR(version);
+       pld->info.major = KEMPLD_VERSION_GET_MAJOR(version);
+       pld->info.number = KEMPLD_VERSION_GET_NUMBER(version);
+       pld->info.type = KEMPLD_VERSION_GET_TYPE(version);
+
+       if (spec == 0xff) {
+               pld->info.spec_minor = 0;
+               pld->info.spec_major = 1;
+       } else {
+               pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec);
+               pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec);
+       }
+
+       if (pld->info.spec_major > 0)
+               pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE);
+       else
+               pld->feature_mask = 0;
+
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+enum kempld_cells {
+       KEMPLD_I2C = 0,
+       KEMPLD_WDT,
+       KEMPLD_GPIO,
+       KEMPLD_UART,
+};
+
+static struct mfd_cell kempld_devs[] = {
+       [KEMPLD_I2C] = {
+               .name = "kempld-i2c",
+       },
+       [KEMPLD_WDT] = {
+               .name = "kempld-wdt",
+       },
+       [KEMPLD_GPIO] = {
+               .name = "kempld-gpio",
+       },
+       [KEMPLD_UART] = {
+               .name = "kempld-uart",
+       },
+};
+
+#define KEMPLD_MAX_DEVS        ARRAY_SIZE(kempld_devs)
+
+static int kempld_register_cells_generic(struct kempld_device_data *pld)
+{
+       struct mfd_cell devs[KEMPLD_MAX_DEVS];
+       int i = 0;
+
+       if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
+               devs[i++] = kempld_devs[KEMPLD_I2C];
+
+       if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
+               devs[i++] = kempld_devs[KEMPLD_WDT];
+
+       if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
+               devs[i++] = kempld_devs[KEMPLD_GPIO];
+
+       if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
+               devs[i++] = kempld_devs[KEMPLD_UART];
+
+       return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
+}
+
+static struct resource kempld_ioresource = {
+       .start  = KEMPLD_IOINDEX,
+       .end    = KEMPLD_IODATA,
+       .flags  = IORESOURCE_IO,
+};
+
+static const struct kempld_platform_data kempld_platform_data_generic = {
+       .pld_clock              = KEMPLD_CLK,
+       .ioresource             = &kempld_ioresource,
+       .get_hardware_mutex     = kempld_get_hardware_mutex,
+       .release_hardware_mutex = kempld_release_hardware_mutex,
+       .get_info               = kempld_get_info_generic,
+       .register_cells         = kempld_register_cells_generic,
+};
+
+static struct platform_device *kempld_pdev;
+
+static int kempld_create_platform_device(const struct dmi_system_id *id)
+{
+       struct kempld_platform_data *pdata = id->driver_data;
+       int ret;
+
+       kempld_pdev = platform_device_alloc("kempld", -1);
+       if (!kempld_pdev)
+               return -ENOMEM;
+
+       ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata));
+       if (ret)
+               goto err;
+
+       ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1);
+       if (ret)
+               goto err;
+
+       ret = platform_device_add(kempld_pdev);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       platform_device_put(kempld_pdev);
+       return ret;
+}
+
+/**
+ * kempld_read8 - read 8 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+u8 kempld_read8(struct kempld_device_data *pld, u8 index)
+{
+       iowrite8(index, pld->io_index);
+       return ioread8(pld->io_data);
+}
+EXPORT_SYMBOL_GPL(kempld_read8);
+
+/**
+ * kempld_write8 - write 8 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ * @data: new register value
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data)
+{
+       iowrite8(index, pld->io_index);
+       iowrite8(data, pld->io_data);
+}
+EXPORT_SYMBOL_GPL(kempld_write8);
+
+/**
+ * kempld_read16 - read 16 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+u16 kempld_read16(struct kempld_device_data *pld, u8 index)
+{
+       return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8;
+}
+EXPORT_SYMBOL_GPL(kempld_read16);
+
+/**
+ * kempld_write16 - write 16 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ * @data: new register value
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data)
+{
+       kempld_write8(pld, index, (u8)data);
+       kempld_write8(pld, index + 1, (u8)(data >> 8));
+}
+EXPORT_SYMBOL_GPL(kempld_write16);
+
+/**
+ * kempld_read32 - read 32 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+u32 kempld_read32(struct kempld_device_data *pld, u8 index)
+{
+       return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16;
+}
+EXPORT_SYMBOL_GPL(kempld_read32);
+
+/**
+ * kempld_write32 - write 32 bit register
+ * @pld: kempld_device_data structure describing the PLD
+ * @index: register index on the chip
+ * @data: new register value
+ *
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data)
+{
+       kempld_write16(pld, index, (u16)data);
+       kempld_write16(pld, index + 2, (u16)(data >> 16));
+}
+EXPORT_SYMBOL_GPL(kempld_write32);
+
+/**
+ * kempld_get_mutex - acquire PLD mutex
+ * @pld: kempld_device_data structure describing the PLD
+ */
+void kempld_get_mutex(struct kempld_device_data *pld)
+{
+       struct kempld_platform_data *pdata = pld->dev->platform_data;
+
+       mutex_lock(&pld->lock);
+       pdata->get_hardware_mutex(pld);
+}
+EXPORT_SYMBOL_GPL(kempld_get_mutex);
+
+/**
+ * kempld_release_mutex - release PLD mutex
+ * @pld: kempld_device_data structure describing the PLD
+ */
+void kempld_release_mutex(struct kempld_device_data *pld)
+{
+       struct kempld_platform_data *pdata = pld->dev->platform_data;
+
+       pdata->release_hardware_mutex(pld);
+       mutex_unlock(&pld->lock);
+}
+EXPORT_SYMBOL_GPL(kempld_release_mutex);
+
+/**
+ * kempld_get_info - update device specific information
+ * @pld: kempld_device_data structure describing the PLD
+ *
+ * This function calls the configured board specific kempld_get_info_XXXX
+ * function which is responsible for gathering information about the specific
+ * hardware. The information is then stored within the pld structure.
+ */
+static int kempld_get_info(struct kempld_device_data *pld)
+{
+       struct kempld_platform_data *pdata = pld->dev->platform_data;
+
+       return pdata->get_info(pld);
+}
+
+/*
+ * kempld_register_cells - register cell drivers
+ *
+ * This function registers cell drivers for the detected hardware by calling
+ * the configured kempld_register_cells_XXXX function which is responsible
+ * to detect and register the needed cell drivers.
+ */
+static int kempld_register_cells(struct kempld_device_data *pld)
+{
+       struct kempld_platform_data *pdata = pld->dev->platform_data;
+
+       return pdata->register_cells(pld);
+}
+
+static int kempld_detect_device(struct kempld_device_data *pld)
+{
+       char *version_type;
+       u8 index_reg;
+       int ret;
+
+       mutex_lock(&pld->lock);
+
+       /* Check for empty IO space */
+       index_reg = ioread8(pld->io_index);
+       if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) {
+               mutex_unlock(&pld->lock);
+               return -ENODEV;
+       }
+
+       /* Release hardware mutex if aquired */
+       if (!(index_reg & KEMPLD_MUTEX_KEY))
+               iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+
+       mutex_unlock(&pld->lock);
+
+       ret = kempld_get_info(pld);
+       if (ret)
+               return ret;
+
+       switch (pld->info.type) {
+       case 0:
+               version_type = "release";
+               break;
+       case 1:
+               version_type = "debug";
+               break;
+       case 2:
+               version_type = "custom";
+               break;
+       default:
+               version_type = "unspecified";
+       }
+
+       dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number);
+       dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n",
+                version_type, pld->info.major, pld->info.minor,
+                pld->info.buildnr, pld->info.spec_major,
+                pld->info.spec_minor);
+
+       return kempld_register_cells(pld);
+}
+
+static int kempld_probe(struct platform_device *pdev)
+{
+       struct kempld_platform_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct kempld_device_data *pld;
+       struct resource *ioport;
+       int ret;
+
+       pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
+       if (!pld)
+               return -ENOMEM;
+
+       ioport = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!ioport)
+               return -EINVAL;
+
+       pld->io_base = devm_ioport_map(dev, ioport->start,
+                                       ioport->end - ioport->start);
+       if (!pld->io_base)
+               return -ENOMEM;
+
+       pld->io_index = pld->io_base;
+       pld->io_data = pld->io_base + 1;
+       pld->pld_clock = pdata->pld_clock;
+       pld->dev = dev;
+
+       mutex_init(&pld->lock);
+       platform_set_drvdata(pdev, pld);
+
+       ret = kempld_detect_device(pld);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int kempld_remove(struct platform_device *pdev)
+{
+       struct kempld_device_data *pld = platform_get_drvdata(pdev);
+       struct kempld_platform_data *pdata = pld->dev->platform_data;
+
+       mfd_remove_devices(&pdev->dev);
+       pdata->release_hardware_mutex(pld);
+
+       return 0;
+}
+
+static struct platform_driver kempld_driver = {
+       .driver         = {
+               .name   = "kempld",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = kempld_probe,
+       .remove         = kempld_remove,
+};
+
+static struct dmi_system_id __initdata kempld_dmi_table[] = {
+       {
+               .ident = "CCR2",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CCR6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR2",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR2",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR2",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHR6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CNTG",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CNTG",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CNTX",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "PXT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "FRI2",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "FRI2",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "MBR1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "NTC1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "NTC1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "NTC1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "NUP1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "UNP1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "UNP1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "UNTG",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "UNTG",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
+               .ident = "UUP6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
+
+static int __init kempld_init(void)
+{
+       const struct dmi_system_id *id;
+       int ret;
+
+       if (force_device_id[0]) {
+               for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
+                       if (strstr(id->ident, force_device_id))
+                               if (id->callback && id->callback(id))
+                                       break;
+               if (id->matches[0].slot == DMI_NONE)
+                       return -ENODEV;
+       } else {
+               if (!dmi_check_system(kempld_dmi_table))
+                       return -ENODEV;
+       }
+
+       ret = platform_driver_register(&kempld_driver);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void __exit kempld_exit(void)
+{
+       if (kempld_pdev)
+               platform_device_unregister(kempld_pdev);
+
+       platform_driver_unregister(&kempld_driver);
+}
+
+module_init(kempld_init);
+module_exit(kempld_exit);
+
+MODULE_DESCRIPTION("KEM PLD Core Driver");
+MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:kempld-core");
index 9f12f91..2403332 100644 (file)
@@ -51,6 +51,8 @@
  *     document number TBD : Lynx Point
  *     document number TBD : Lynx Point-LP
  *     document number TBD : Wellsburg
+ *     document number TBD : Avoton SoC
+ *     document number TBD : Coleto Creek
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -207,6 +209,8 @@ enum lpc_chipsets {
        LPC_LPT,        /* Lynx Point */
        LPC_LPT_LP,     /* Lynx Point-LP */
        LPC_WBG,        /* Wellsburg */
+       LPC_AVN,        /* Avoton SoC */
+       LPC_COLETO,     /* Coleto Creek */
 };
 
 struct lpc_ich_info lpc_chipset_info[] = {
@@ -491,6 +495,14 @@ struct lpc_ich_info lpc_chipset_info[] = {
                .name = "Wellsburg",
                .iTCO_version = 2,
        },
+       [LPC_AVN] = {
+               .name = "Avoton SoC",
+               .iTCO_version = 1,
+       },
+       [LPC_COLETO] = {
+               .name = "Coleto Creek",
+               .iTCO_version = 2,
+       },
 };
 
 /*
@@ -704,6 +716,11 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
        { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG},
+       { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@@ -973,18 +990,7 @@ static struct pci_driver lpc_ich_driver = {
        .remove         = lpc_ich_remove,
 };
 
-static int __init lpc_ich_init(void)
-{
-       return pci_register_driver(&lpc_ich_driver);
-}
-
-static void __exit lpc_ich_exit(void)
-{
-       pci_unregister_driver(&lpc_ich_driver);
-}
-
-module_init(lpc_ich_init);
-module_exit(lpc_ich_exit);
+module_pci_driver(lpc_ich_driver);
 
 MODULE_AUTHOR("Aaron Sierra <asierra@xes-inc.com>");
 MODULE_DESCRIPTION("LPC interface for Intel ICH");
index 1cbb176..f27a218 100644 (file)
@@ -37,6 +37,7 @@
 static struct mfd_cell max77686_devs[] = {
        { .name = "max77686-pmic", },
        { .name = "max77686-rtc", },
+       { .name = "max77686-clk", },
 };
 
 static struct regmap_config max77686_regmap_config = {
@@ -84,12 +85,12 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
                pdata = max77686_i2c_parse_dt_pdata(&i2c->dev);
 
        if (!pdata) {
-               ret = -EIO;
                dev_err(&i2c->dev, "No platform data found.\n");
-               goto err;
+               return -EIO;
        }
 
-       max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL);
+       max77686 = devm_kzalloc(&i2c->dev,
+                               sizeof(struct max77686_dev), GFP_KERNEL);
        if (max77686 == NULL)
                return -ENOMEM;
 
@@ -107,7 +108,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
                ret = PTR_ERR(max77686->regmap);
                dev_err(max77686->dev, "Failed to allocate register map: %d\n",
                                ret);
-               kfree(max77686);
                return ret;
        }
 
@@ -115,8 +115,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
                         MAX77686_REG_DEVICE_ID, &data) < 0) {
                dev_err(max77686->dev,
                        "device not found on this channel (this is not an error)\n");
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        } else
                dev_info(max77686->dev, "device found\n");
 
@@ -127,17 +126,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
 
        ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
                              ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
+       if (ret < 0) {
+               mfd_remove_devices(max77686->dev);
+               i2c_unregister_device(max77686->rtc);
+       }
 
-       if (ret < 0)
-               goto err_mfd;
-
-       return ret;
-
-err_mfd:
-       mfd_remove_devices(max77686->dev);
-       i2c_unregister_device(max77686->rtc);
-err:
-       kfree(max77686);
        return ret;
 }
 
@@ -147,7 +140,6 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
 
        mfd_remove_devices(max77686->dev);
        i2c_unregister_device(max77686->rtc);
-       kfree(max77686);
 
        return 0;
 }
index 92bbebd..8042b32 100644 (file)
@@ -170,7 +170,8 @@ static int max8925_probe(struct i2c_client *client,
                return -EINVAL;
        }
 
-       chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
+       chip = devm_kzalloc(&client->dev,
+                           sizeof(struct max8925_chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
        chip->i2c = client;
@@ -199,7 +200,6 @@ static int max8925_remove(struct i2c_client *client)
        max8925_device_exit(chip);
        i2c_unregister_device(chip->adc);
        i2c_unregister_device(chip->rtc);
-       kfree(chip);
        return 0;
 }
 
index 5919710..c469477 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/mfd/max8998-private.h>
 
 struct max8998_irq_data {
@@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = {
 static inline struct max8998_irq_data *
 irq_to_max8998_irq(struct max8998_dev *max8998, int irq)
 {
-       return &max8998_irqs[irq - max8998->irq_base];
+       struct irq_data *data = irq_get_irq_data(irq);
+       return &max8998_irqs[data->hwirq];
 }
 
 static void max8998_irq_lock(struct irq_data *data)
@@ -176,8 +178,14 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
 
        /* Report */
        for (i = 0; i < MAX8998_IRQ_NR; i++) {
-               if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask)
-                       handle_nested_irq(max8998->irq_base + i);
+               if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) {
+                       irq = irq_find_mapping(max8998->irq_domain, i);
+                       if (WARN_ON(!irq)) {
+                               disable_irq_nosync(max8998->irq);
+                               return IRQ_NONE;
+                       }
+                       handle_nested_irq(irq);
+               }
        }
 
        return IRQ_HANDLED;
@@ -185,27 +193,40 @@ static irqreturn_t max8998_irq_thread(int irq, void *data)
 
 int max8998_irq_resume(struct max8998_dev *max8998)
 {
-       if (max8998->irq && max8998->irq_base)
-               max8998_irq_thread(max8998->irq_base, max8998);
+       if (max8998->irq && max8998->irq_domain)
+               max8998_irq_thread(max8998->irq, max8998);
+       return 0;
+}
+
+static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq,
+                                       irq_hw_number_t hw)
+{
+       struct max8997_dev *max8998 = d->host_data;
+
+       irq_set_chip_data(irq, max8998);
+       irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq);
+       irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+       set_irq_flags(irq, IRQF_VALID);
+#else
+       irq_set_noprobe(irq);
+#endif
        return 0;
 }
 
+static struct irq_domain_ops max8998_irq_domain_ops = {
+       .map = max8998_irq_domain_map,
+};
+
 int max8998_irq_init(struct max8998_dev *max8998)
 {
        int i;
-       int cur_irq;
        int ret;
+       struct irq_domain *domain;
 
        if (!max8998->irq) {
                dev_warn(max8998->dev,
                         "No interrupt specified, no interrupts\n");
-               max8998->irq_base = 0;
-               return 0;
-       }
-
-       if (!max8998->irq_base) {
-               dev_err(max8998->dev,
-                       "No interrupt base specified, no interrupts\n");
                return 0;
        }
 
@@ -221,19 +242,13 @@ int max8998_irq_init(struct max8998_dev *max8998)
        max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff);
        max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff);
 
-       /* register with genirq */
-       for (i = 0; i < MAX8998_IRQ_NR; i++) {
-               cur_irq = i + max8998->irq_base;
-               irq_set_chip_data(cur_irq, max8998);
-               irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
-                                        handle_edge_irq);
-               irq_set_nested_thread(cur_irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(cur_irq, IRQF_VALID);
-#else
-               irq_set_noprobe(cur_irq);
-#endif
+       domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR,
+                       max8998->irq_base, &max8998_irq_domain_ops, max8998);
+       if (!domain) {
+               dev_err(max8998->dev, "could not create irq domain\n");
+               return -ENODEV;
        }
+       max8998->irq_domain = domain;
 
        ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread,
                                   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
index d7218cc..21af51a 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/mfd/core.h>
@@ -128,6 +131,56 @@ int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
 }
 EXPORT_SYMBOL(max8998_update_reg);
 
+#ifdef CONFIG_OF
+static struct of_device_id max8998_dt_match[] = {
+       { .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 },
+       { .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 },
+       { .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 },
+       {},
+};
+MODULE_DEVICE_TABLE(of, max8998_dt_match);
+#endif
+
+/*
+ * Only the common platform data elements for max8998 are parsed here from the
+ * device tree. Other sub-modules of max8998 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8998 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
+                                                       struct device *dev)
+{
+       struct max8998_platform_data *pd;
+
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return ERR_PTR(-ENOMEM);
+
+       pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+       /*
+        * ToDo: the 'wakeup' member in the platform data is more of a linux
+        * specfic information. Hence, there is no binding for that yet and
+        * not parsed here.
+        */
+       return pd;
+}
+
+static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
+                                               const struct i2c_device_id *id)
+{
+       if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(max8998_dt_match, i2c->dev.of_node);
+               return (int)match->data;
+       }
+
+       return (int)id->driver_data;
+}
+
 static int max8998_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -139,11 +192,20 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
        if (max8998 == NULL)
                return -ENOMEM;
 
+       if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
+               pdata = max8998_i2c_parse_dt_pdata(&i2c->dev);
+               if (IS_ERR(pdata)) {
+                       ret = PTR_ERR(pdata);
+                       goto err;
+               }
+       }
+
        i2c_set_clientdata(i2c, max8998);
        max8998->dev = &i2c->dev;
        max8998->i2c = i2c;
        max8998->irq = i2c->irq;
-       max8998->type = id->driver_data;
+       max8998->type = max8998_i2c_get_driver_data(i2c, id);
+       max8998->pdata = pdata;
        if (pdata) {
                max8998->ono = pdata->ono;
                max8998->irq_base = pdata->irq_base;
@@ -158,7 +220,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
 
        pm_runtime_set_active(max8998->dev);
 
-       switch (id->driver_data) {
+       switch (max8998->type) {
        case TYPE_LP3974:
                ret = mfd_add_devices(max8998->dev, -1,
                                      lp3974_devs, ARRAY_SIZE(lp3974_devs),
@@ -314,6 +376,7 @@ static struct i2c_driver max8998_i2c_driver = {
                   .name = "max8998",
                   .owner = THIS_MODULE,
                   .pm = &max8998_pm,
+                  .of_match_table = of_match_ptr(max8998_dt_match),
        },
        .probe = max8998_i2c_probe,
        .remove = max8998_i2c_remove,
index f99d629..13198d9 100644 (file)
@@ -225,8 +225,6 @@ static int mcp_sa11x0_probe(struct platform_device *dev)
        if (ret == 0)
                return 0;
 
-       platform_set_drvdata(dev, NULL);
-
  err_ioremap:
        iounmap(m->base1);
        iounmap(m->base0);
@@ -252,7 +250,6 @@ static int mcp_sa11x0_remove(struct platform_device *dev)
        mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
        mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
 
-       platform_set_drvdata(dev, NULL);
        mcp_host_del(mcp);
        iounmap(m->base1);
        iounmap(m->base0);
index 53e9fe6..e4d1c70 100644 (file)
 #include <linux/err.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/palmas.h>
-#include <linux/of_platform.h>
-
-enum palmas_ids {
-       PALMAS_PMIC_ID,
-       PALMAS_GPIO_ID,
-       PALMAS_LEDS_ID,
-       PALMAS_WDT_ID,
-       PALMAS_RTC_ID,
-       PALMAS_PWRBUTTON_ID,
-       PALMAS_GPADC_ID,
-       PALMAS_RESOURCE_ID,
-       PALMAS_CLK_ID,
-       PALMAS_PWM_ID,
-       PALMAS_USB_ID,
-};
-
-static struct resource palmas_rtc_resources[] = {
-       {
-               .start  = PALMAS_RTC_ALARM_IRQ,
-               .end    = PALMAS_RTC_ALARM_IRQ,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static const struct mfd_cell palmas_children[] = {
-       {
-               .name = "palmas-pmic",
-               .id = PALMAS_PMIC_ID,
-       },
-       {
-               .name = "palmas-gpio",
-               .id = PALMAS_GPIO_ID,
-       },
-       {
-               .name = "palmas-leds",
-               .id = PALMAS_LEDS_ID,
-       },
-       {
-               .name = "palmas-wdt",
-               .id = PALMAS_WDT_ID,
-       },
-       {
-               .name = "palmas-rtc",
-               .id = PALMAS_RTC_ID,
-               .resources = &palmas_rtc_resources[0],
-               .num_resources = ARRAY_SIZE(palmas_rtc_resources),
-       },
-       {
-               .name = "palmas-pwrbutton",
-               .id = PALMAS_PWRBUTTON_ID,
-       },
-       {
-               .name = "palmas-gpadc",
-               .id = PALMAS_GPADC_ID,
-       },
-       {
-               .name = "palmas-resource",
-               .id = PALMAS_RESOURCE_ID,
-       },
-       {
-               .name = "palmas-clk",
-               .id = PALMAS_CLK_ID,
-       },
-       {
-               .name = "palmas-pwm",
-               .id = PALMAS_PWM_ID,
-       },
-       {
-               .name = "palmas-usb",
-               .id = PALMAS_USB_ID,
-       }
-};
+#include <linux/of_device.h>
 
 static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
        {
@@ -302,6 +231,21 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c,
                palmas_set_pdata_irq_flag(i2c, pdata);
 }
 
+static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
+static unsigned int tps659038_features;
+
+static const struct of_device_id of_palmas_match_tbl[] = {
+       {
+               .compatible = "ti,palmas",
+               .data = &palmas_features,
+       },
+       {
+               .compatible = "ti,tps659038",
+               .data = &tps659038_features,
+       },
+       { },
+};
+
 static int palmas_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -309,9 +253,9 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
        struct palmas_platform_data *pdata;
        struct device_node *node = i2c->dev.of_node;
        int ret = 0, i;
-       unsigned int reg, addr;
+       unsigned int reg, addr, *features;
        int slave;
-       struct mfd_cell *children;
+       const struct of_device_id *match;
 
        pdata = dev_get_platdata(&i2c->dev);
 
@@ -333,9 +277,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, palmas);
        palmas->dev = &i2c->dev;
-       palmas->id = id->driver_data;
        palmas->irq = i2c->irq;
 
+       match = of_match_device(of_match_ptr(of_palmas_match_tbl), &i2c->dev);
+
+       if (!match)
+               return -ENODATA;
+
+       features = (unsigned int *)match->data;
+       palmas->features = *features;
+
        for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
                if (i == 0)
                        palmas->i2c_clients[i] = i2c;
@@ -362,6 +313,11 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                }
        }
 
+       if (!palmas->irq) {
+               dev_warn(palmas->dev, "IRQ missing: skipping irq request\n");
+               goto no_irq;
+       }
+
        /* Change interrupt line output polarity */
        if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH)
                reg = PALMAS_POLARITY_CTRL_INT_POLARITY;
@@ -388,6 +344,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                goto err;
 
+no_irq:
        slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
        addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE,
                        PALMAS_PRIMARY_SECONDARY_PAD1);
@@ -472,42 +429,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                        return ret;
        }
 
-       children = kmemdup(palmas_children, sizeof(palmas_children),
-                          GFP_KERNEL);
-       if (!children) {
-               ret = -ENOMEM;
-               goto err_irq;
-       }
-
-       children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
-       children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
-
-       children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata;
-       children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata);
-
-       children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata;
-       children[PALMAS_RESOURCE_ID].pdata_size =
-                       sizeof(*pdata->resource_pdata);
-
-       children[PALMAS_USB_ID].platform_data = pdata->usb_pdata;
-       children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata);
-
-       children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata;
-       children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata);
-
-       ret = mfd_add_devices(palmas->dev, -1,
-                             children, ARRAY_SIZE(palmas_children),
-                             NULL, 0,
-                             regmap_irq_get_domain(palmas->irq_data));
-       kfree(children);
-
-       if (ret < 0)
-               goto err_devices;
-
        return ret;
 
-err_devices:
-       mfd_remove_devices(palmas->dev);
 err_irq:
        regmap_del_irq_chip(palmas->irq, palmas->irq_data);
 err:
@@ -533,11 +456,6 @@ static const struct i2c_device_id palmas_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
 
-static struct of_device_id of_palmas_match_tbl[] = {
-       { .compatible = "ti,palmas", },
-       { /* end */ }
-};
-
 static struct i2c_driver palmas_i2c_driver = {
        .driver = {
                   .name = "palmas",
index 2a2d316..c436bf2 100644 (file)
@@ -35,12 +35,33 @@ static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
        return val & 0x0F;
 }
 
+static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
+{
+       u8 val = 0;
+
+       rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val);
+
+       if (val & 0x2)
+               return 1;
+       else
+               return 0;
+}
+
 static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, CD_PAD_CTL,
                        CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
 }
 
+static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       if (rtl8411b_is_qfn48(pcr))
+               rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5);
+
+       return rtsx_pci_write_register(pcr, CD_PAD_CTL,
+                       CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
+}
+
 static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
@@ -214,6 +235,20 @@ static const struct pcr_ops rtl8411_pcr_ops = {
        .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
 };
 
+static const struct pcr_ops rtl8411b_pcr_ops = {
+       .extra_init_hw = rtl8411b_extra_init_hw,
+       .optimize_phy = NULL,
+       .turn_on_led = rtl8411_turn_on_led,
+       .turn_off_led = rtl8411_turn_off_led,
+       .enable_auto_blink = rtl8411_enable_auto_blink,
+       .disable_auto_blink = rtl8411_disable_auto_blink,
+       .card_power_on = rtl8411_card_power_on,
+       .card_power_off = rtl8411_card_power_off,
+       .switch_output_voltage = rtl8411_switch_output_voltage,
+       .cd_deglitch = rtl8411_cd_deglitch,
+       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
+};
+
 /* SD Pull Control Enable:
  *     SD_DAT[3:0] ==> pull up
  *     SD_CD       ==> pull up
@@ -276,6 +311,74 @@ static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
        0,
 };
 
+static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
 void rtl8411_init_params(struct rtsx_pcr *pcr)
 {
        pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
@@ -288,3 +391,32 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
        pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
        pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
 }
+
+void rtl8411b_init_params(struct rtsx_pcr *pcr)
+{
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+       pcr->num_slots = 2;
+       pcr->ops = &rtl8411b_pcr_ops;
+
+       pcr->ic_version = rtl8411_get_ic_version(pcr);
+
+       if (rtl8411b_is_qfn48(pcr)) {
+               pcr->sd_pull_ctl_enable_tbl =
+                       rtl8411b_qfn48_sd_pull_ctl_enable_tbl;
+               pcr->sd_pull_ctl_disable_tbl =
+                       rtl8411b_qfn48_sd_pull_ctl_disable_tbl;
+               pcr->ms_pull_ctl_enable_tbl =
+                       rtl8411b_qfn48_ms_pull_ctl_enable_tbl;
+               pcr->ms_pull_ctl_disable_tbl =
+                       rtl8411b_qfn48_ms_pull_ctl_disable_tbl;
+       } else {
+               pcr->sd_pull_ctl_enable_tbl =
+                       rtl8411b_qfn64_sd_pull_ctl_enable_tbl;
+               pcr->sd_pull_ctl_disable_tbl =
+                       rtl8411b_qfn64_sd_pull_ctl_disable_tbl;
+               pcr->ms_pull_ctl_enable_tbl =
+                       rtl8411b_qfn64_ms_pull_ctl_enable_tbl;
+               pcr->ms_pull_ctl_disable_tbl =
+                       rtl8411b_qfn64_ms_pull_ctl_disable_tbl;
+       }
+}
index e968c01..dd186c4 100644 (file)
@@ -57,6 +57,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
        { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { 0, }
 };
 
@@ -1038,6 +1039,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
        case 0x5249:
                rts5249_init_params(pcr);
                break;
+
+       case 0x5287:
+               rtl8411b_init_params(pcr);
+               break;
        }
 
        dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
index 55fcfc2..c0cac7e 100644 (file)
@@ -33,5 +33,6 @@ void rts5229_init_params(struct rtsx_pcr *pcr);
 void rtl8411_init_params(struct rtsx_pcr *pcr);
 void rts5227_init_params(struct rtsx_pcr *pcr);
 void rts5249_init_params(struct rtsx_pcr *pcr);
+void rtl8411b_init_params(struct rtsx_pcr *pcr);
 
 #endif
index 77ee26e..7976768 100644 (file)
@@ -25,6 +25,9 @@
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/rtc.h>
+#include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s5m8763.h>
+#include <linux/mfd/samsung/s5m8767.h>
 #include <linux/regmap.h>
 
 static struct mfd_cell s5m8751_devs[] = {
@@ -105,6 +108,26 @@ static struct regmap_config sec_regmap_config = {
        .val_bits = 8,
 };
 
+static struct regmap_config s2mps11_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = S2MPS11_REG_L38CTRL,
+};
+
+static struct regmap_config s5m8763_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = S5M8763_REG_LBCNFG2,
+};
+
+static struct regmap_config s5m8767_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = S5M8767_REG_LDO28CTRL,
+};
 
 #ifdef CONFIG_OF
 /*
@@ -160,6 +183,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct sec_platform_data *pdata = i2c->dev.platform_data;
+       const struct regmap_config *regmap;
        struct sec_pmic_dev *sec_pmic;
        int ret;
 
@@ -190,7 +214,22 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                sec_pmic->pdata = pdata;
        }
 
-       sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config);
+       switch (sec_pmic->device_type) {
+       case S2MPS11X:
+               regmap = &s2mps11_regmap_config;
+               break;
+       case S5M8763X:
+               regmap = &s5m8763_regmap_config;
+               break;
+       case S5M8767X:
+               regmap = &s5m8767_regmap_config;
+               break;
+       default:
+               regmap = &sec_regmap_config;
+               break;
+       }
+
+       sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap);
        if (IS_ERR(sec_pmic->regmap)) {
                ret = PTR_ERR(sec_pmic->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -230,13 +269,12 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                BUG();
        }
 
-       if (ret < 0)
+       if (ret)
                goto err;
 
        return ret;
 
 err:
-       mfd_remove_devices(sec_pmic->dev);
        sec_irq_exit(sec_pmic);
        i2c_unregister_device(sec_pmic->rtc);
        return ret;
similarity index 100%
rename from drivers/ssbi/ssbi.c
rename to drivers/mfd/ssbi.c
index b32940e..a21bff2 100644 (file)
@@ -422,7 +422,6 @@ static int t7l66xb_remove(struct platform_device *dev)
        iounmap(t7l66xb->scr);
        release_resource(&t7l66xb->rscr);
        mfd_remove_devices(&dev->dev);
-       platform_set_drvdata(dev, NULL);
        kfree(t7l66xb);
 
        return ret;
index 366f7b9..65c425a 100644 (file)
@@ -217,7 +217,6 @@ static int tc6387xb_remove(struct platform_device *dev)
        release_resource(&tc6387xb->rscr);
        clk_disable(tc6387xb->clk32k);
        clk_put(tc6387xb->clk32k);
-       platform_set_drvdata(dev, NULL);
        kfree(tc6387xb);
 
        return 0;
index 15e1463..a563dfa 100644 (file)
@@ -756,7 +756,6 @@ static int tc6393xb_remove(struct platform_device *dev)
        clk_disable(tc6393xb->clk);
        iounmap(tc6393xb->scr);
        release_resource(&tc6393xb->rscr);
-       platform_set_drvdata(dev, NULL);
        clk_put(tc6393xb->clk);
        kfree(tc6393xb);
 
index e9f3fb5..b003a16 100644 (file)
 #include <linux/regmap.h>
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
-#include <linux/input/ti_am335x_tsc.h>
-#include <linux/platform_data/ti_am335x_adc.h>
 
 static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
 {
@@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = {
        .val_bits = 32,
 };
 
+void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
+{
+       tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
+
+void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
+{
+       spin_lock(&tsadc->reg_lock);
+       tsadc->reg_se_cache |= val;
+       spin_unlock(&tsadc->reg_lock);
+
+       am335x_tsc_se_update(tsadc);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
+
+void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
+{
+       spin_lock(&tsadc->reg_lock);
+       tsadc->reg_se_cache &= ~val;
+       spin_unlock(&tsadc->reg_lock);
+
+       am335x_tsc_se_update(tsadc);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
+
 static void tscadc_idle_config(struct ti_tscadc_dev *config)
 {
        unsigned int idleconfig;
@@ -63,27 +89,48 @@ static      int ti_tscadc_probe(struct platform_device *pdev)
        struct ti_tscadc_dev    *tscadc;
        struct resource         *res;
        struct clk              *clk;
-       struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
+       struct device_node      *node = pdev->dev.of_node;
        struct mfd_cell         *cell;
+       struct property         *prop;
+       const __be32            *cur;
+       u32                     val;
        int                     err, ctrl;
        int                     clk_value, clock_rate;
-       int                     tsc_wires, adc_channels = 0, total_channels;
+       int                     tsc_wires = 0, adc_channels = 0, total_channels;
+       int                     readouts = 0;
 
-       if (!pdata) {
-               dev_err(&pdev->dev, "Could not find platform data\n");
+       if (!pdev->dev.of_node) {
+               dev_err(&pdev->dev, "Could not find valid DT data.\n");
                return -EINVAL;
        }
 
-       if (pdata->adc_init)
-               adc_channels = pdata->adc_init->adc_channels;
-
-       tsc_wires = pdata->tsc_init->wires;
+       node = of_get_child_by_name(pdev->dev.of_node, "tsc");
+       of_property_read_u32(node, "ti,wires", &tsc_wires);
+       of_property_read_u32(node, "ti,coordiante-readouts", &readouts);
+
+       node = of_get_child_by_name(pdev->dev.of_node, "adc");
+       of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+               adc_channels++;
+               if (val > 7) {
+                       dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
+                                       val);
+                       return -EINVAL;
+               }
+       }
        total_channels = tsc_wires + adc_channels;
-
        if (total_channels > 8) {
                dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
                return -EINVAL;
        }
+       if (total_channels == 0) {
+               dev_err(&pdev->dev, "Need atleast one channel.\n");
+               return -EINVAL;
+       }
+
+       if (readouts * 2 + 2 + adc_channels > 16) {
+               dev_err(&pdev->dev, "Too many step configurations requested\n");
+               return -EINVAL;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -129,6 +176,7 @@ static      int ti_tscadc_probe(struct platform_device *pdev)
                goto ret;
        }
 
+       spin_lock_init(&tscadc->reg_lock);
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
 
@@ -173,26 +221,37 @@ static    int ti_tscadc_probe(struct platform_device *pdev)
        ctrl |= CNTRLREG_TSCSSENB;
        tscadc_writel(tscadc, REG_CTRL, ctrl);
 
+       tscadc->used_cells = 0;
+       tscadc->tsc_cell = -1;
+       tscadc->adc_cell = -1;
+
        /* TSC Cell */
-       cell = &tscadc->cells[TSC_CELL];
-       cell->name = "tsc";
-       cell->platform_data = tscadc;
-       cell->pdata_size = sizeof(*tscadc);
+       if (tsc_wires > 0) {
+               tscadc->tsc_cell = tscadc->used_cells;
+               cell = &tscadc->cells[tscadc->used_cells++];
+               cell->name = "TI-am335x-tsc";
+               cell->of_compatible = "ti,am3359-tsc";
+               cell->platform_data = &tscadc;
+               cell->pdata_size = sizeof(tscadc);
+       }
 
        /* ADC Cell */
-       cell = &tscadc->cells[ADC_CELL];
-       cell->name = "tiadc";
-       cell->platform_data = tscadc;
-       cell->pdata_size = sizeof(*tscadc);
+       if (adc_channels > 0) {
+               tscadc->adc_cell = tscadc->used_cells;
+               cell = &tscadc->cells[tscadc->used_cells++];
+               cell->name = "TI-am335x-adc";
+               cell->of_compatible = "ti,am3359-adc";
+               cell->platform_data = &tscadc;
+               cell->pdata_size = sizeof(tscadc);
+       }
 
        err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-                       TSCADC_CELLS, NULL, 0, NULL);
+                       tscadc->used_cells, NULL, 0, NULL);
        if (err < 0)
                goto err_disable_clk;
 
        device_init_wakeup(&pdev->dev, true);
        platform_set_drvdata(pdev, tscadc);
-
        return 0;
 
 err_disable_clk:
@@ -239,7 +298,7 @@ static int tscadc_resume(struct device *dev)
                        CNTRLREG_STEPID | CNTRLREG_4WIRE;
        tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
        tscadc_idle_config(tscadc_dev);
-       tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
+       am335x_tsc_se_update(tscadc_dev);
        restore = tscadc_readl(tscadc_dev, REG_CTRL);
        tscadc_writel(tscadc_dev, REG_CTRL,
                        (restore | CNTRLREG_TSCSSENB));
@@ -256,11 +315,18 @@ static const struct dev_pm_ops tscadc_pm_ops = {
 #define TSCADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_tscadc_dt_ids[] = {
+       { .compatible = "ti,am3359-tscadc", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
+
 static struct platform_driver ti_tscadc_driver = {
        .driver = {
-               .name   = "ti_tscadc",
+               .name   = "ti_am3359-tscadc",
                .owner  = THIS_MODULE,
                .pm     = TSCADC_PM_OPS,
+               .of_match_table = of_match_ptr(ti_tscadc_dt_ids),
        },
        .probe  = ti_tscadc_probe,
        .remove = ti_tscadc_remove,
index aeb8e40..479886a 100644 (file)
@@ -162,7 +162,6 @@ int tps65912_device_init(struct tps65912 *tps65912)
 err:
        kfree(init_data);
        mfd_remove_devices(tps65912->dev);
-       kfree(tps65912);
        return ret;
 }
 
@@ -170,7 +169,6 @@ void tps65912_device_exit(struct tps65912 *tps65912)
 {
        mfd_remove_devices(tps65912->dev);
        tps65912_irq_exit(tps65912);
-       kfree(tps65912);
 }
 
 MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
index c041f2c..6a6343e 100644 (file)
@@ -77,7 +77,8 @@ static int tps65912_i2c_probe(struct i2c_client *i2c,
 {
        struct tps65912 *tps65912;
 
-       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       tps65912 = devm_kzalloc(&i2c->dev,
+                               sizeof(struct tps65912), GFP_KERNEL);
        if (tps65912 == NULL)
                return -ENOMEM;
 
index b45f460..69a5178 100644 (file)
@@ -85,7 +85,8 @@ static int tps65912_spi_probe(struct spi_device *spi)
 {
        struct tps65912 *tps65912;
 
-       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       tps65912 = devm_kzalloc(&spi->dev,
+                               sizeof(struct tps65912), GFP_KERNEL);
        if (tps65912 == NULL)
                return -ENOMEM;
 
index 89ab4d9..7f150d9 100644 (file)
 #define TWL6030_BASEADD_GASGAUGE       0x00C0
 #define TWL6030_BASEADD_PIH            0x00D0
 #define TWL6030_BASEADD_CHARGER                0x00E0
-#define TWL6025_BASEADD_CHARGER                0x00DA
+#define TWL6032_BASEADD_CHARGER                0x00DA
 #define TWL6030_BASEADD_LED            0x00F4
 
 /* subchip/slave 2 0x4A - DFT */
@@ -718,9 +718,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                                        | REGULATOR_CHANGE_STATUS,
                        };
 
-                       if (features & TWL6025_SUBCLASS) {
+                       if (features & TWL6032_SUBCLASS) {
                                usb3v3.supply = "ldousb";
-                               regulator = TWL6025_REG_LDOUSB;
+                               regulator = TWL6032_REG_LDOUSB;
                        } else {
                                usb3v3.supply = "vusb";
                                regulator = TWL6030_REG_VUSB;
@@ -747,8 +747,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        usb3v3.dev_name = dev_name(child);
        } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
                   twl_class_is_6030()) {
-               if (features & TWL6025_SUBCLASS)
-                       child = add_regulator(TWL6025_REG_LDOUSB,
+               if (features & TWL6032_SUBCLASS)
+                       child = add_regulator(TWL6032_REG_LDOUSB,
                                                pdata->ldousb, features);
                else
                        child = add_regulator(TWL6030_REG_VUSB,
@@ -872,7 +872,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
        /* twl6030 regulators */
        if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
-                       !(features & TWL6025_SUBCLASS)) {
+                       !(features & TWL6032_SUBCLASS)) {
                child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
                                        features);
                if (IS_ERR(child))
@@ -952,60 +952,60 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       /* twl6025 regulators */
+       /* twl6032 regulators */
        if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
-                       (features & TWL6025_SUBCLASS)) {
-               child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
+                       (features & TWL6032_SUBCLASS)) {
+               child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
+               child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
+               child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
+               child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
+               child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
+               child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
+               child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
+               child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
+               child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
+               child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
+               child = add_regulator(TWL6032_REG_VIO, pdata->vio6025,
                                        features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
@@ -1023,6 +1023,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
+       if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
+               child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
+                                 pdata->power, sizeof(*pdata->power), false,
+                                 0, 0);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+       }
+
        return 0;
 }
 
@@ -1176,10 +1184,10 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if ((id->driver_data) & TWL6030_CLASS) {
                twl_priv->twl_id = TWL6030_CLASS_ID;
                twl_priv->twl_map = &twl6030_map[0];
-               /* The charger base address is different in twl6025 */
-               if ((id->driver_data) & TWL6025_SUBCLASS)
+               /* The charger base address is different in twl6032 */
+               if ((id->driver_data) & TWL6032_SUBCLASS)
                        twl_priv->twl_map[TWL_MODULE_MAIN_CHARGE].base =
-                                                       TWL6025_BASEADD_CHARGER;
+                                                       TWL6032_BASEADD_CHARGER;
                twl_regmap_config = twl6030_regmap_config;
        } else {
                twl_priv->twl_id = TWL4030_CLASS_ID;
@@ -1234,10 +1242,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                WARN(status < 0, "Error: reading twl_idcode register value\n");
        }
 
-       /* load power event scripts */
-       if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata && pdata->power)
-               twl4030_power_init(pdata->power);
-
        /* Maybe init the T2 Interrupt subsystem */
        if (client->irq) {
                if (twl_class_is_4030()) {
@@ -1292,7 +1296,7 @@ static const struct i2c_device_id twl_ids[] = {
        { "tps65921", TPS_SUBSET },     /* fewer LDOs; no codec, no LED
                                           and vibrator. Charger in USB module*/
        { "twl6030", TWL6030_CLASS },   /* "Phoenix power chip" */
-       { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
+       { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */
        { /* end of list */ },
 };
 MODULE_DEVICE_TABLE(i2c, twl_ids);
@@ -1305,17 +1309,7 @@ static struct i2c_driver twl_driver = {
        .remove         = twl_remove,
 };
 
-static int __init twl_init(void)
-{
-       return i2c_add_driver(&twl_driver);
-}
-subsys_initcall(twl_init);
-
-static void __exit twl_exit(void)
-{
-       i2c_del_driver(&twl_driver);
-}
-module_exit(twl_exit);
+module_i2c_driver(twl_driver);
 
 MODULE_AUTHOR("Texas Instruments, Inc.");
 MODULE_DESCRIPTION("I2C Core interface for TWL");
index d2ab222..a31fba9 100644 (file)
@@ -261,10 +261,8 @@ static int twl4030_audio_probe(struct platform_device *pdev)
                ret = -ENODEV;
        }
 
-       if (ret) {
-               platform_set_drvdata(pdev, NULL);
+       if (ret)
                twl4030_audio_dev = NULL;
-       }
 
        return ret;
 }
@@ -272,7 +270,6 @@ static int twl4030_audio_probe(struct platform_device *pdev)
 static int twl4030_audio_remove(struct platform_device *pdev)
 {
        mfd_remove_devices(&pdev->dev);
-       platform_set_drvdata(pdev, NULL);
        twl4030_audio_dev = NULL;
 
        return 0;
index 9d2d1ba..9aa6d1e 100644 (file)
@@ -570,6 +570,7 @@ static struct irq_chip twl4030_sih_irq_chip = {
        .irq_set_type   = twl4030_sih_set_type,
        .irq_bus_lock   = twl4030_sih_bus_lock,
        .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock,
+       .flags          = IRQCHIP_SKIP_SET_WAKE,
 };
 
 /*----------------------------------------------------------------------*/
index 42bd3ea..1ea54d4 100644 (file)
@@ -775,12 +775,10 @@ static int twl4030_madc_probe(struct platform_device *pdev)
                                   IRQF_TRIGGER_RISING, "twl4030_madc", madc);
        if (ret) {
                dev_dbg(&pdev->dev, "could not request irq\n");
-               goto err_irq;
+               goto err_i2c;
        }
        twl4030_madc = madc;
        return 0;
-err_irq:
-       platform_set_drvdata(pdev, NULL);
 err_i2c:
        twl4030_madc_set_current_generator(madc, 0, 0);
 err_current_generator:
@@ -796,7 +794,6 @@ static int twl4030_madc_remove(struct platform_device *pdev)
        struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
 
        free_irq(platform_get_irq(pdev, 0), madc);
-       platform_set_drvdata(pdev, NULL);
        twl4030_madc_set_current_generator(madc, 0, 0);
        twl4030_madc_set_power(madc, 0);
        kfree(madc);
index dd362c1..a5fd3c7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pm.h>
 #include <linux/i2c/twl.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 #include <asm/mach-types.h>
 
@@ -492,6 +493,39 @@ int twl4030_remove_script(u8 flags)
        return err;
 }
 
+int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
+{
+       int err;
+       int i;
+       u8 address = twl4030_start_script_address;
+
+       for (i = 0; i < pdata->num; i++) {
+               err = load_twl4030_script(pdata->scripts[i], address);
+               if (err)
+                       return err;
+               address += pdata->scripts[i]->size;
+       }
+
+       return 0;
+}
+
+int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
+{
+       struct twl4030_resconfig *resconfig = pdata->resource_config;
+       int err;
+
+       if (resconfig) {
+               while (resconfig->resource) {
+                       err = twl4030_configure_resource(resconfig);
+                       if (err)
+                               return err;
+                       resconfig++;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * In master mode, start the power off sequence.
  * After a successful execution, TWL shuts down the power to the SoC
@@ -507,43 +541,58 @@ void twl4030_power_off(void)
                pr_err("TWL4030 Unable to power off\n");
 }
 
-void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
+                                       struct device_node *node)
 {
+       if (pdata && pdata->use_poweroff)
+               return true;
+
+       if (of_property_read_bool(node, "ti,use_poweroff"))
+               return true;
+
+       return false;
+}
+
+int twl4030_power_probe(struct platform_device *pdev)
+{
+       struct twl4030_power_data *pdata = pdev->dev.platform_data;
+       struct device_node *node = pdev->dev.of_node;
        int err = 0;
-       int i;
-       struct twl4030_resconfig *resconfig;
-       u8 val, address = twl4030_start_script_address;
+       int err2 = 0;
+       u8 val;
+
+       if (!pdata && !node) {
+               dev_err(&pdev->dev, "Platform data is missing\n");
+               return -EINVAL;
+       }
 
        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
                               TWL4030_PM_MASTER_PROTECT_KEY);
-       if (err)
-               goto unlock;
-
-       err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+       err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
+                              TWL4030_PM_MASTER_KEY_CFG2,
                               TWL4030_PM_MASTER_PROTECT_KEY);
-       if (err)
-               goto unlock;
 
-       for (i = 0; i < twl4030_scripts->num; i++) {
-               err = load_twl4030_script(twl4030_scripts->scripts[i], address);
-               if (err)
-                       goto load;
-               address += twl4030_scripts->scripts[i]->size;
+       if (err) {
+               pr_err("TWL4030 Unable to unlock registers\n");
+               return err;
        }
 
-       resconfig = twl4030_scripts->resource_config;
-       if (resconfig) {
-               while (resconfig->resource) {
-                       err = twl4030_configure_resource(resconfig);
-                       if (err)
-                               goto resource;
-                       resconfig++;
-
+       if (pdata) {
+               /* TODO: convert to device tree */
+               err = twl4030_power_configure_scripts(pdata);
+               if (err) {
+                       pr_err("TWL4030 failed to load scripts\n");
+                       goto relock;
+               }
+               err = twl4030_power_configure_resources(pdata);
+               if (err) {
+                       pr_err("TWL4030 failed to configure resource\n");
+                       goto relock;
                }
        }
 
        /* Board has to be wired properly to use this feature */
-       if (twl4030_scripts->use_poweroff && !pm_power_off) {
+       if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
                /* Default for SEQ_OFFSYNC is set, lets ensure this */
                err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
                                      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
@@ -564,22 +613,43 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
        }
 
 relock:
-       err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+       err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
                               TWL4030_PM_MASTER_PROTECT_KEY);
-       if (err)
+       if (err2) {
                pr_err("TWL4030 Unable to relock registers\n");
-       return;
+               return err2;
+       }
 
-unlock:
-       if (err)
-               pr_err("TWL4030 Unable to unlock registers\n");
-       return;
-load:
-       if (err)
-               pr_err("TWL4030 failed to load scripts\n");
-       return;
-resource:
-       if (err)
-               pr_err("TWL4030 failed to configure resource\n");
-       return;
+       return err;
 }
+
+static int twl4030_power_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id twl4030_power_of_match[] = {
+       {.compatible = "ti,twl4030-power", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl4030_power_of_match);
+#endif
+
+static struct platform_driver twl4030_power_driver = {
+       .driver = {
+               .name   = "twl4030_power",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(twl4030_power_of_match),
+       },
+       .probe          = twl4030_power_probe,
+       .remove         = twl4030_power_remove,
+};
+
+module_platform_driver(twl4030_power_driver);
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("Power management for TWL4030");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_power");
index 96a020b..981bef4 100644 (file)
@@ -351,6 +351,8 @@ void __init vexpress_sysreg_of_early_init(void)
 }
 
 
+#ifdef CONFIG_GPIOLIB
+
 #define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \
        [VEXPRESS_GPIO_##_name] = { \
                .reg = _reg, \
@@ -445,6 +447,8 @@ struct gpio_led_platform_data vexpress_sysreg_leds_pdata = {
        .leds = vexpress_sysreg_leds,
 };
 
+#endif
+
 
 static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -480,6 +484,9 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
        setup_timer(&vexpress_sysreg_config_timer,
                        vexpress_sysreg_config_complete, 0);
 
+       vexpress_sysreg_dev = &pdev->dev;
+
+#ifdef CONFIG_GPIOLIB
        vexpress_sysreg_gpio_chip.dev = &pdev->dev;
        err = gpiochip_add(&vexpress_sysreg_gpio_chip);
        if (err) {
@@ -490,11 +497,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
                return err;
        }
 
-       vexpress_sysreg_dev = &pdev->dev;
-
        platform_device_register_data(vexpress_sysreg_dev, "leds-gpio",
                        PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata,
                        sizeof(vexpress_sysreg_leds_pdata));
+#endif
 
        device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
 
index 00e4fe2..781115e 100644 (file)
@@ -259,20 +259,6 @@ static int wm8994_suspend(struct device *dev)
                break;
        }
 
-       switch (wm8994->type) {
-       case WM1811:
-               ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
-               if (ret < 0) {
-                       dev_err(dev, "Failed to read jackdet: %d\n", ret);
-               } else if (ret & WM1811_JACKDET_MODE_MASK) {
-                       dev_dbg(dev, "CODEC still active, ignoring suspend\n");
-                       return 0;
-               }
-               break;
-       default:
-               break;
-       }
-
        /* Disable LDO pulldowns while the device is suspended if we
         * don't know that something will be driving them. */
        if (!wm8994->ldo_ena_always_driven)
@@ -652,6 +638,17 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                return ret;
        }
 
+       /* Explicitly put the device into reset in case regulators
+        * don't get disabled in order to ensure we know the device
+        * state.
+        */
+       ret = wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+                              wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
+       if (ret != 0) {
+               dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);
+               return ret;
+       }
+
        if (regmap_patch) {
                ret = regmap_register_patch(wm8994->regmap, regmap_patch,
                                            patch_regs);
index a050e56..d3a184a 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/regmap.h>
 
 #include <linux/mfd/wm8994/core.h>
@@ -138,6 +140,55 @@ static struct regmap_irq_chip wm8994_irq_chip = {
        .runtime_pm = true,
 };
 
+static void wm8994_edge_irq_enable(struct irq_data *data)
+{
+}
+
+static void wm8994_edge_irq_disable(struct irq_data *data)
+{
+}
+
+static struct irq_chip wm8994_edge_irq_chip = {
+       .name                   = "wm8994_edge",
+       .irq_disable            = wm8994_edge_irq_disable,
+       .irq_enable             = wm8994_edge_irq_enable,
+};
+
+static irqreturn_t wm8994_edge_irq(int irq, void *data)
+{
+       struct wm8994 *wm8994 = data;
+
+       while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio))
+               handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0));
+
+       return IRQ_HANDLED;
+}
+
+static int wm8994_edge_irq_map(struct irq_domain *h, unsigned int virq,
+                              irq_hw_number_t hw)
+{
+       struct wm8994 *wm8994 = h->host_data;
+
+       irq_set_chip_data(virq, wm8994);
+       irq_set_chip_and_handler(virq, &wm8994_edge_irq_chip, handle_edge_irq);
+       irq_set_nested_thread(virq, 1);
+
+       /* ARM needs us to explicitly flag the IRQ as valid
+        * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+       set_irq_flags(virq, IRQF_VALID);
+#else
+       irq_set_noprobe(virq);
+#endif
+
+       return 0;
+}
+
+static struct irq_domain_ops wm8994_edge_irq_ops = {
+       .map    = wm8994_edge_irq_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
 int wm8994_irq_init(struct wm8994 *wm8994)
 {
        int ret;
@@ -156,10 +207,51 @@ int wm8994_irq_init(struct wm8994 *wm8994)
        if (pdata->irq_flags)
                irqflags = pdata->irq_flags;
 
-       ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
-                                 irqflags,
-                                 wm8994->irq_base, &wm8994_irq_chip,
-                                 &wm8994->irq_data);
+       /* use a GPIO for edge triggered controllers */
+       if (irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+               if (gpio_to_irq(pdata->irq_gpio) != wm8994->irq) {
+                       dev_warn(wm8994->dev, "IRQ %d is not GPIO %d (%d)\n",
+                                wm8994->irq, pdata->irq_gpio,
+                                gpio_to_irq(pdata->irq_gpio));
+                       wm8994->irq = gpio_to_irq(pdata->irq_gpio);
+               }
+
+               ret = devm_gpio_request_one(wm8994->dev, pdata->irq_gpio,
+                                           GPIOF_IN, "WM8994 IRQ");
+
+               if (ret != 0) {
+                       dev_err(wm8994->dev, "Failed to get IRQ GPIO: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               wm8994->edge_irq = irq_domain_add_linear(NULL, 1,
+                                                        &wm8994_edge_irq_ops,
+                                                        wm8994);
+
+               ret = regmap_add_irq_chip(wm8994->regmap,
+                                         irq_create_mapping(wm8994->edge_irq,
+                                                            0),
+                                         IRQF_ONESHOT,
+                                         wm8994->irq_base, &wm8994_irq_chip,
+                                         &wm8994->irq_data);
+               if (ret != 0) {
+                       dev_err(wm8994->dev, "Failed to get IRQ: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = request_threaded_irq(wm8994->irq,
+                                          NULL, wm8994_edge_irq,
+                                          irqflags,
+                                          "WM8994 edge", wm8994);
+       } else {
+               ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
+                                         irqflags,
+                                         wm8994->irq_base, &wm8994_irq_chip,
+                                         &wm8994->irq_data);
+       }
+
        if (ret != 0) {
                dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret);
                return ret;
diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c
new file mode 100644 (file)
index 0000000..5aa8076
--- /dev/null
@@ -0,0 +1,1525 @@
+/*
+ * wm8997-tables.c  --  WM8997 data tables
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.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/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+
+#include "arizona.h"
+
+static const struct reg_default wm8997_reva_patch[] = {
+       { 0x80, 0x0003 },
+       { 0x214, 0x0008 },
+       { 0x458, 0x0000 },
+       { 0x0081, 0xE022 },
+       { 0x294, 0x0000 },
+       { 0x80, 0x0000 },
+       { 0x171, 0x0000 },
+};
+
+/* We use a function so we can use ARRAY_SIZE() */
+int wm8997_patch(struct arizona *arizona)
+{
+       switch (arizona->rev) {
+       case 0:
+               return regmap_register_patch(arizona->regmap,
+                                            wm8997_reva_patch,
+                                            ARRAY_SIZE(wm8997_reva_patch));
+       default:
+               return 0;
+       }
+}
+EXPORT_SYMBOL_GPL(wm8997_patch);
+
+static const struct regmap_irq wm8997_aod_irqs[ARIZONA_NUM_IRQ] = {
+       [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 },
+       [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 },
+       [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 },
+       [ARIZONA_IRQ_JD_RISE] = { .mask = ARIZONA_JD1_RISE_EINT1 },
+};
+
+const struct regmap_irq_chip wm8997_aod = {
+       .name = "wm8997 AOD",
+       .status_base = ARIZONA_AOD_IRQ1,
+       .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1,
+       .ack_base = ARIZONA_AOD_IRQ1,
+       .num_regs = 1,
+       .irqs = wm8997_aod_irqs,
+       .num_irqs = ARRAY_SIZE(wm8997_aod_irqs),
+};
+EXPORT_SYMBOL_GPL(wm8997_aod);
+
+static const struct regmap_irq wm8997_irqs[ARIZONA_NUM_IRQ] = {
+       [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 },
+       [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 },
+       [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
+       [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
+
+       [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
+               .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+       },
+       [ARIZONA_IRQ_SPK_SHUTDOWN] = {
+               .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+       },
+       [ARIZONA_IRQ_HPDET] = {
+               .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
+       },
+       [ARIZONA_IRQ_MICDET] = {
+               .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1
+       },
+       [ARIZONA_IRQ_WSEQ_DONE] = {
+               .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1
+       },
+       [ARIZONA_IRQ_DRC1_SIG_DET] = {
+               .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1
+       },
+       [ARIZONA_IRQ_UNDERCLOCKED] = {
+               .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1
+       },
+       [ARIZONA_IRQ_OVERCLOCKED] = {
+               .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1
+       },
+       [ARIZONA_IRQ_FLL2_LOCK] = {
+               .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1
+       },
+       [ARIZONA_IRQ_FLL1_LOCK] = {
+               .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1
+       },
+       [ARIZONA_IRQ_CLKGEN_ERR] = {
+               .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1
+       },
+       [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = {
+               .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1
+       },
+
+       [ARIZONA_IRQ_AIF2_ERR] = {
+               .reg_offset = 3, .mask = ARIZONA_AIF2_ERR_EINT1
+       },
+       [ARIZONA_IRQ_AIF1_ERR] = {
+               .reg_offset = 3, .mask = ARIZONA_AIF1_ERR_EINT1
+       },
+       [ARIZONA_IRQ_CTRLIF_ERR] = {
+               .reg_offset = 3, .mask = ARIZONA_CTRLIF_ERR_EINT1
+       },
+       [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = {
+               .reg_offset = 3, .mask = ARIZONA_MIXER_DROPPED_SAMPLE_EINT1
+       },
+       [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = {
+               .reg_offset = 3, .mask = ARIZONA_ASYNC_CLK_ENA_LOW_EINT1
+       },
+       [ARIZONA_IRQ_SYSCLK_ENA_LOW] = {
+               .reg_offset = 3, .mask = ARIZONA_SYSCLK_ENA_LOW_EINT1
+       },
+       [ARIZONA_IRQ_ISRC1_CFG_ERR] = {
+               .reg_offset = 3, .mask = ARIZONA_ISRC1_CFG_ERR_EINT1
+       },
+       [ARIZONA_IRQ_ISRC2_CFG_ERR] = {
+               .reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1
+       },
+
+       [ARIZONA_IRQ_BOOT_DONE] = {
+               .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
+       },
+       [ARIZONA_IRQ_DCS_DAC_DONE] = {
+               .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1
+       },
+       [ARIZONA_IRQ_DCS_HP_DONE] = {
+               .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1
+       },
+       [ARIZONA_IRQ_FLL2_CLOCK_OK] = {
+               .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
+       },
+       [ARIZONA_IRQ_FLL1_CLOCK_OK] = {
+               .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1
+       },
+};
+
+const struct regmap_irq_chip wm8997_irq = {
+       .name = "wm8997 IRQ",
+       .status_base = ARIZONA_INTERRUPT_STATUS_1,
+       .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK,
+       .ack_base = ARIZONA_INTERRUPT_STATUS_1,
+       .num_regs = 5,
+       .irqs = wm8997_irqs,
+       .num_irqs = ARRAY_SIZE(wm8997_irqs),
+};
+EXPORT_SYMBOL_GPL(wm8997_irq);
+
+static const struct reg_default wm8997_reg_default[] = {
+       { 0x00000009, 0x0001 },    /* R9     - Ctrl IF I2C1 CFG 1 */
+       { 0x00000016, 0x0000 },    /* R22    - Write Sequencer Ctrl 0 */
+       { 0x00000017, 0x0000 },    /* R23    - Write Sequencer Ctrl 1 */
+       { 0x00000018, 0x0000 },    /* R24    - Write Sequencer Ctrl 2 */
+       { 0x00000020, 0x0000 },    /* R32    - Tone Generator 1 */
+       { 0x00000021, 0x1000 },    /* R33    - Tone Generator 2 */
+       { 0x00000022, 0x0000 },    /* R34    - Tone Generator 3 */
+       { 0x00000023, 0x1000 },    /* R35    - Tone Generator 4 */
+       { 0x00000024, 0x0000 },    /* R36    - Tone Generator 5 */
+       { 0x00000030, 0x0000 },    /* R48    - PWM Drive 1 */
+       { 0x00000031, 0x0100 },    /* R49    - PWM Drive 2 */
+       { 0x00000032, 0x0100 },    /* R50    - PWM Drive 3 */
+       { 0x00000040, 0x0000 },    /* R64    - Wake control */
+       { 0x00000041, 0x0000 },    /* R65    - Sequence control */
+       { 0x00000061, 0x01FF },    /* R97    - Sample Rate Sequence Select 1 */
+       { 0x00000062, 0x01FF },    /* R98    - Sample Rate Sequence Select 2 */
+       { 0x00000063, 0x01FF },    /* R99    - Sample Rate Sequence Select 3 */
+       { 0x00000064, 0x01FF },    /* R100   - Sample Rate Sequence Select 4 */
+       { 0x00000068, 0x01FF },    /* R104   - Always On Triggers Sequence Select 1 */
+       { 0x00000069, 0x01FF },    /* R105   - Always On Triggers Sequence Select 2 */
+       { 0x0000006A, 0x01FF },    /* R106   - Always On Triggers Sequence Select 3 */
+       { 0x0000006B, 0x01FF },    /* R107   - Always On Triggers Sequence Select 4 */
+       { 0x00000070, 0x0000 },    /* R112   - Comfort Noise Generator */
+       { 0x00000090, 0x0000 },    /* R144   - Haptics Control 1 */
+       { 0x00000091, 0x7FFF },    /* R145   - Haptics Control 2 */
+       { 0x00000092, 0x0000 },    /* R146   - Haptics phase 1 intensity */
+       { 0x00000093, 0x0000 },    /* R147   - Haptics phase 1 duration */
+       { 0x00000094, 0x0000 },    /* R148   - Haptics phase 2 intensity */
+       { 0x00000095, 0x0000 },    /* R149   - Haptics phase 2 duration */
+       { 0x00000096, 0x0000 },    /* R150   - Haptics phase 3 intensity */
+       { 0x00000097, 0x0000 },    /* R151   - Haptics phase 3 duration */
+       { 0x00000100, 0x0002 },    /* R256   - Clock 32k 1 */
+       { 0x00000101, 0x0304 },    /* R257   - System Clock 1 */
+       { 0x00000102, 0x0011 },    /* R258   - Sample rate 1 */
+       { 0x00000103, 0x0011 },    /* R259   - Sample rate 2 */
+       { 0x00000104, 0x0011 },    /* R260   - Sample rate 3 */
+       { 0x00000112, 0x0305 },    /* R274   - Async clock 1 */
+       { 0x00000113, 0x0011 },    /* R275   - Async sample rate 1 */
+       { 0x00000149, 0x0000 },    /* R329   - Output system clock */
+       { 0x0000014A, 0x0000 },    /* R330   - Output async clock */
+       { 0x00000152, 0x0000 },    /* R338   - Rate Estimator 1 */
+       { 0x00000153, 0x0000 },    /* R339   - Rate Estimator 2 */
+       { 0x00000154, 0x0000 },    /* R340   - Rate Estimator 3 */
+       { 0x00000155, 0x0000 },    /* R341   - Rate Estimator 4 */
+       { 0x00000156, 0x0000 },    /* R342   - Rate Estimator 5 */
+       { 0x00000161, 0x0000 },    /* R353   - Dynamic Frequency Scaling 1 */
+       { 0x00000171, 0x0000 },    /* R369   - FLL1 Control 1 */
+       { 0x00000172, 0x0008 },    /* R370   - FLL1 Control 2 */
+       { 0x00000173, 0x0018 },    /* R371   - FLL1 Control 3 */
+       { 0x00000174, 0x007D },    /* R372   - FLL1 Control 4 */
+       { 0x00000175, 0x0004 },    /* R373   - FLL1 Control 5 */
+       { 0x00000176, 0x0000 },    /* R374   - FLL1 Control 6 */
+       { 0x00000177, 0x0181 },    /* R375   - FLL1 Loop Filter Test 1 */
+       { 0x00000181, 0x0000 },    /* R385   - FLL1 Synchroniser 1 */
+       { 0x00000182, 0x0000 },    /* R386   - FLL1 Synchroniser 2 */
+       { 0x00000183, 0x0000 },    /* R387   - FLL1 Synchroniser 3 */
+       { 0x00000184, 0x0000 },    /* R388   - FLL1 Synchroniser 4 */
+       { 0x00000185, 0x0000 },    /* R389   - FLL1 Synchroniser 5 */
+       { 0x00000186, 0x0000 },    /* R390   - FLL1 Synchroniser 6 */
+       { 0x00000189, 0x0000 },    /* R393   - FLL1 Spread Spectrum */
+       { 0x0000018A, 0x0004 },    /* R394   - FLL1 GPIO Clock */
+       { 0x00000191, 0x0000 },    /* R401   - FLL2 Control 1 */
+       { 0x00000192, 0x0008 },    /* R402   - FLL2 Control 2 */
+       { 0x00000193, 0x0018 },    /* R403   - FLL2 Control 3 */
+       { 0x00000194, 0x007D },    /* R404   - FLL2 Control 4 */
+       { 0x00000195, 0x0004 },    /* R405   - FLL2 Control 5 */
+       { 0x00000196, 0x0000 },    /* R406   - FLL2 Control 6 */
+       { 0x00000197, 0x0000 },    /* R407   - FLL2 Loop Filter Test 1 */
+       { 0x000001A1, 0x0000 },    /* R417   - FLL2 Synchroniser 1 */
+       { 0x000001A2, 0x0000 },    /* R418   - FLL2 Synchroniser 2 */
+       { 0x000001A3, 0x0000 },    /* R419   - FLL2 Synchroniser 3 */
+       { 0x000001A4, 0x0000 },    /* R420   - FLL2 Synchroniser 4 */
+       { 0x000001A5, 0x0000 },    /* R421   - FLL2 Synchroniser 5 */
+       { 0x000001A6, 0x0000 },    /* R422   - FLL2 Synchroniser 6 */
+       { 0x000001A9, 0x0000 },    /* R425   - FLL2 Spread Spectrum */
+       { 0x000001AA, 0x0004 },    /* R426   - FLL2 GPIO Clock */
+       { 0x00000200, 0x0006 },    /* R512   - Mic Charge Pump 1 */
+       { 0x00000210, 0x00D4 },    /* R528   - LDO1 Control 1 */
+       { 0x00000212, 0x0000 },    /* R530   - LDO1 Control 2 */
+       { 0x00000213, 0x0344 },    /* R531   - LDO2 Control 1 */
+       { 0x00000218, 0x01A6 },    /* R536   - Mic Bias Ctrl 1 */
+       { 0x00000219, 0x01A6 },    /* R537   - Mic Bias Ctrl 2 */
+       { 0x0000021A, 0x01A6 },    /* R538   - Mic Bias Ctrl 3 */
+       { 0x00000293, 0x0000 },    /* R659   - Accessory Detect Mode 1 */
+       { 0x0000029B, 0x0020 },    /* R667   - Headphone Detect 1 */
+       { 0x000002A3, 0x1102 },    /* R675   - Mic Detect 1 */
+       { 0x000002A4, 0x009F },    /* R676   - Mic Detect 2 */
+       { 0x000002A5, 0x0000 },    /* R677   - Mic Detect 3 */
+       { 0x000002C3, 0x0000 },    /* R707   - Mic noise mix control 1 */
+       { 0x000002CB, 0x0000 },    /* R715   - Isolation control */
+       { 0x000002D3, 0x0000 },    /* R723   - Jack detect analogue */
+       { 0x00000300, 0x0000 },    /* R768   - Input Enables */
+       { 0x00000308, 0x0000 },    /* R776   - Input Rate */
+       { 0x00000309, 0x0022 },    /* R777   - Input Volume Ramp */
+       { 0x00000310, 0x2080 },    /* R784   - IN1L Control */
+       { 0x00000311, 0x0180 },    /* R785   - ADC Digital Volume 1L */
+       { 0x00000312, 0x0000 },    /* R786   - DMIC1L Control */
+       { 0x00000314, 0x0080 },    /* R788   - IN1R Control */
+       { 0x00000315, 0x0180 },    /* R789   - ADC Digital Volume 1R */
+       { 0x00000316, 0x0000 },    /* R790   - DMIC1R Control */
+       { 0x00000318, 0x2080 },    /* R792   - IN2L Control */
+       { 0x00000319, 0x0180 },    /* R793   - ADC Digital Volume 2L */
+       { 0x0000031A, 0x0000 },    /* R794   - DMIC2L Control */
+       { 0x0000031C, 0x0080 },    /* R796   - IN2R Control */
+       { 0x0000031D, 0x0180 },    /* R797   - ADC Digital Volume 2R */
+       { 0x0000031E, 0x0000 },    /* R798   - DMIC2R Control */
+       { 0x00000400, 0x0000 },    /* R1024  - Output Enables 1 */
+       { 0x00000408, 0x0000 },    /* R1032  - Output Rate 1 */
+       { 0x00000409, 0x0022 },    /* R1033  - Output Volume Ramp */
+       { 0x00000410, 0x0080 },    /* R1040  - Output Path Config 1L */
+       { 0x00000411, 0x0180 },    /* R1041  - DAC Digital Volume 1L */
+       { 0x00000412, 0x0080 },    /* R1042  - DAC Volume Limit 1L */
+       { 0x00000413, 0x0001 },    /* R1043  - Noise Gate Select 1L */
+       { 0x00000414, 0x0080 },    /* R1044  - Output Path Config 1R */
+       { 0x00000415, 0x0180 },    /* R1045  - DAC Digital Volume 1R */
+       { 0x00000416, 0x0080 },    /* R1046  - DAC Volume Limit 1R */
+       { 0x00000417, 0x0002 },    /* R1047  - Noise Gate Select 1R */
+       { 0x00000420, 0x0080 },    /* R1056  - Output Path Config 3L */
+       { 0x00000421, 0x0180 },    /* R1057  - DAC Digital Volume 3L */
+       { 0x00000422, 0x0080 },    /* R1058  - DAC Volume Limit 3L */
+       { 0x00000423, 0x0010 },    /* R1059  - Noise Gate Select 3L */
+       { 0x00000428, 0x0000 },    /* R1064  - Output Path Config 4L */
+       { 0x00000429, 0x0180 },    /* R1065  - DAC Digital Volume 4L */
+       { 0x0000042A, 0x0080 },    /* R1066  - Out Volume 4L */
+       { 0x0000042B, 0x0040 },    /* R1067  - Noise Gate Select 4L */
+       { 0x00000430, 0x0000 },    /* R1072  - Output Path Config 5L */
+       { 0x00000431, 0x0180 },    /* R1073  - DAC Digital Volume 5L */
+       { 0x00000432, 0x0080 },    /* R1074  - DAC Volume Limit 5L */
+       { 0x00000433, 0x0100 },    /* R1075  - Noise Gate Select 5L */
+       { 0x00000435, 0x0180 },    /* R1077  - DAC Digital Volume 5R */
+       { 0x00000436, 0x0080 },    /* R1078  - DAC Volume Limit 5R */
+       { 0x00000437, 0x0200 },    /* R1079  - Noise Gate Select 5R */
+       { 0x00000450, 0x0000 },    /* R1104  - DAC AEC Control 1 */
+       { 0x00000458, 0x0000 },    /* R1112  - Noise Gate Control */
+       { 0x00000490, 0x0069 },    /* R1168  - PDM SPK1 CTRL 1 */
+       { 0x00000491, 0x0000 },    /* R1169  - PDM SPK1 CTRL 2 */
+       { 0x00000500, 0x000C },    /* R1280  - AIF1 BCLK Ctrl */
+       { 0x00000501, 0x0008 },    /* R1281  - AIF1 Tx Pin Ctrl */
+       { 0x00000502, 0x0000 },    /* R1282  - AIF1 Rx Pin Ctrl */
+       { 0x00000503, 0x0000 },    /* R1283  - AIF1 Rate Ctrl */
+       { 0x00000504, 0x0000 },    /* R1284  - AIF1 Format */
+       { 0x00000505, 0x0040 },    /* R1285  - AIF1 Tx BCLK Rate */
+       { 0x00000506, 0x0040 },    /* R1286  - AIF1 Rx BCLK Rate */
+       { 0x00000507, 0x1818 },    /* R1287  - AIF1 Frame Ctrl 1 */
+       { 0x00000508, 0x1818 },    /* R1288  - AIF1 Frame Ctrl 2 */
+       { 0x00000509, 0x0000 },    /* R1289  - AIF1 Frame Ctrl 3 */
+       { 0x0000050A, 0x0001 },    /* R1290  - AIF1 Frame Ctrl 4 */
+       { 0x0000050B, 0x0002 },    /* R1291  - AIF1 Frame Ctrl 5 */
+       { 0x0000050C, 0x0003 },    /* R1292  - AIF1 Frame Ctrl 6 */
+       { 0x0000050D, 0x0004 },    /* R1293  - AIF1 Frame Ctrl 7 */
+       { 0x0000050E, 0x0005 },    /* R1294  - AIF1 Frame Ctrl 8 */
+       { 0x0000050F, 0x0006 },    /* R1295  - AIF1 Frame Ctrl 9 */
+       { 0x00000510, 0x0007 },    /* R1296  - AIF1 Frame Ctrl 10 */
+       { 0x00000511, 0x0000 },    /* R1297  - AIF1 Frame Ctrl 11 */
+       { 0x00000512, 0x0001 },    /* R1298  - AIF1 Frame Ctrl 12 */
+       { 0x00000513, 0x0002 },    /* R1299  - AIF1 Frame Ctrl 13 */
+       { 0x00000514, 0x0003 },    /* R1300  - AIF1 Frame Ctrl 14 */
+       { 0x00000515, 0x0004 },    /* R1301  - AIF1 Frame Ctrl 15 */
+       { 0x00000516, 0x0005 },    /* R1302  - AIF1 Frame Ctrl 16 */
+       { 0x00000517, 0x0006 },    /* R1303  - AIF1 Frame Ctrl 17 */
+       { 0x00000518, 0x0007 },    /* R1304  - AIF1 Frame Ctrl 18 */
+       { 0x00000519, 0x0000 },    /* R1305  - AIF1 Tx Enables */
+       { 0x0000051A, 0x0000 },    /* R1306  - AIF1 Rx Enables */
+       { 0x00000540, 0x000C },    /* R1344  - AIF2 BCLK Ctrl */
+       { 0x00000541, 0x0008 },    /* R1345  - AIF2 Tx Pin Ctrl */
+       { 0x00000542, 0x0000 },    /* R1346  - AIF2 Rx Pin Ctrl */
+       { 0x00000543, 0x0000 },    /* R1347  - AIF2 Rate Ctrl */
+       { 0x00000544, 0x0000 },    /* R1348  - AIF2 Format */
+       { 0x00000545, 0x0040 },    /* R1349  - AIF2 Tx BCLK Rate */
+       { 0x00000546, 0x0040 },    /* R1350  - AIF2 Rx BCLK Rate */
+       { 0x00000547, 0x1818 },    /* R1351  - AIF2 Frame Ctrl 1 */
+       { 0x00000548, 0x1818 },    /* R1352  - AIF2 Frame Ctrl 2 */
+       { 0x00000549, 0x0000 },    /* R1353  - AIF2 Frame Ctrl 3 */
+       { 0x0000054A, 0x0001 },    /* R1354  - AIF2 Frame Ctrl 4 */
+       { 0x00000551, 0x0000 },    /* R1361  - AIF2 Frame Ctrl 11 */
+       { 0x00000552, 0x0001 },    /* R1362  - AIF2 Frame Ctrl 12 */
+       { 0x00000559, 0x0000 },    /* R1369  - AIF2 Tx Enables */
+       { 0x0000055A, 0x0000 },    /* R1370  - AIF2 Rx Enables */
+       { 0x000005E3, 0x0004 },    /* R1507  - SLIMbus Framer Ref Gear */
+       { 0x000005E5, 0x0000 },    /* R1509  - SLIMbus Rates 1 */
+       { 0x000005E6, 0x0000 },    /* R1510  - SLIMbus Rates 2 */
+       { 0x000005E7, 0x0000 },    /* R1511  - SLIMbus Rates 3 */
+       { 0x000005E8, 0x0000 },    /* R1512  - SLIMbus Rates 4 */
+       { 0x000005E9, 0x0000 },    /* R1513  - SLIMbus Rates 5 */
+       { 0x000005EA, 0x0000 },    /* R1514  - SLIMbus Rates 6 */
+       { 0x000005EB, 0x0000 },    /* R1515  - SLIMbus Rates 7 */
+       { 0x000005EC, 0x0000 },    /* R1516  - SLIMbus Rates 8 */
+       { 0x000005F5, 0x0000 },    /* R1525  - SLIMbus RX Channel Enable */
+       { 0x000005F6, 0x0000 },    /* R1526  - SLIMbus TX Channel Enable */
+       { 0x00000640, 0x0000 },    /* R1600  - PWM1MIX Input 1 Source */
+       { 0x00000641, 0x0080 },    /* R1601  - PWM1MIX Input 1 Volume */
+       { 0x00000642, 0x0000 },    /* R1602  - PWM1MIX Input 2 Source */
+       { 0x00000643, 0x0080 },    /* R1603  - PWM1MIX Input 2 Volume */
+       { 0x00000644, 0x0000 },    /* R1604  - PWM1MIX Input 3 Source */
+       { 0x00000645, 0x0080 },    /* R1605  - PWM1MIX Input 3 Volume */
+       { 0x00000646, 0x0000 },    /* R1606  - PWM1MIX Input 4 Source */
+       { 0x00000647, 0x0080 },    /* R1607  - PWM1MIX Input 4 Volume */
+       { 0x00000648, 0x0000 },    /* R1608  - PWM2MIX Input 1 Source */
+       { 0x00000649, 0x0080 },    /* R1609  - PWM2MIX Input 1 Volume */
+       { 0x0000064A, 0x0000 },    /* R1610  - PWM2MIX Input 2 Source */
+       { 0x0000064B, 0x0080 },    /* R1611  - PWM2MIX Input 2 Volume */
+       { 0x0000064C, 0x0000 },    /* R1612  - PWM2MIX Input 3 Source */
+       { 0x0000064D, 0x0080 },    /* R1613  - PWM2MIX Input 3 Volume */
+       { 0x0000064E, 0x0000 },    /* R1614  - PWM2MIX Input 4 Source */
+       { 0x0000064F, 0x0080 },    /* R1615  - PWM2MIX Input 4 Volume */
+       { 0x00000660, 0x0000 },    /* R1632  - MICMIX Input 1 Source */
+       { 0x00000661, 0x0080 },    /* R1633  - MICMIX Input 1 Volume */
+       { 0x00000662, 0x0000 },    /* R1634  - MICMIX Input 2 Source */
+       { 0x00000663, 0x0080 },    /* R1635  - MICMIX Input 2 Volume */
+       { 0x00000664, 0x0000 },    /* R1636  - MICMIX Input 3 Source */
+       { 0x00000665, 0x0080 },    /* R1637  - MICMIX Input 3 Volume */
+       { 0x00000666, 0x0000 },    /* R1638  - MICMIX Input 4 Source */
+       { 0x00000667, 0x0080 },    /* R1639  - MICMIX Input 4 Volume */
+       { 0x00000668, 0x0000 },    /* R1640  - NOISEMIX Input 1 Source */
+       { 0x00000669, 0x0080 },    /* R1641  - NOISEMIX Input 1 Volume */
+       { 0x0000066A, 0x0000 },    /* R1642  - NOISEMIX Input 2 Source */
+       { 0x0000066B, 0x0080 },    /* R1643  - NOISEMIX Input 2 Volume */
+       { 0x0000066C, 0x0000 },    /* R1644  - NOISEMIX Input 3 Source */
+       { 0x0000066D, 0x0080 },    /* R1645  - NOISEMIX Input 3 Volume */
+       { 0x0000066E, 0x0000 },    /* R1646  - NOISEMIX Input 4 Source */
+       { 0x0000066F, 0x0080 },    /* R1647  - NOISEMIX Input 4 Volume */
+       { 0x00000680, 0x0000 },    /* R1664  - OUT1LMIX Input 1 Source */
+       { 0x00000681, 0x0080 },    /* R1665  - OUT1LMIX Input 1 Volume */
+       { 0x00000682, 0x0000 },    /* R1666  - OUT1LMIX Input 2 Source */
+       { 0x00000683, 0x0080 },    /* R1667  - OUT1LMIX Input 2 Volume */
+       { 0x00000684, 0x0000 },    /* R1668  - OUT1LMIX Input 3 Source */
+       { 0x00000685, 0x0080 },    /* R1669  - OUT1LMIX Input 3 Volume */
+       { 0x00000686, 0x0000 },    /* R1670  - OUT1LMIX Input 4 Source */
+       { 0x00000687, 0x0080 },    /* R1671  - OUT1LMIX Input 4 Volume */
+       { 0x00000688, 0x0000 },    /* R1672  - OUT1RMIX Input 1 Source */
+       { 0x00000689, 0x0080 },    /* R1673  - OUT1RMIX Input 1 Volume */
+       { 0x0000068A, 0x0000 },    /* R1674  - OUT1RMIX Input 2 Source */
+       { 0x0000068B, 0x0080 },    /* R1675  - OUT1RMIX Input 2 Volume */
+       { 0x0000068C, 0x0000 },    /* R1676  - OUT1RMIX Input 3 Source */
+       { 0x0000068D, 0x0080 },    /* R1677  - OUT1RMIX Input 3 Volume */
+       { 0x0000068E, 0x0000 },    /* R1678  - OUT1RMIX Input 4 Source */
+       { 0x0000068F, 0x0080 },    /* R1679  - OUT1RMIX Input 4 Volume */
+       { 0x000006A0, 0x0000 },    /* R1696  - OUT3LMIX Input 1 Source */
+       { 0x000006A1, 0x0080 },    /* R1697  - OUT3LMIX Input 1 Volume */
+       { 0x000006A2, 0x0000 },    /* R1698  - OUT3LMIX Input 2 Source */
+       { 0x000006A3, 0x0080 },    /* R1699  - OUT3LMIX Input 2 Volume */
+       { 0x000006A4, 0x0000 },    /* R1700  - OUT3LMIX Input 3 Source */
+       { 0x000006A5, 0x0080 },    /* R1701  - OUT3LMIX Input 3 Volume */
+       { 0x000006A6, 0x0000 },    /* R1702  - OUT3LMIX Input 4 Source */
+       { 0x000006A7, 0x0080 },    /* R1703  - OUT3LMIX Input 4 Volume */
+       { 0x000006B0, 0x0000 },    /* R1712  - OUT4LMIX Input 1 Source */
+       { 0x000006B1, 0x0080 },    /* R1713  - OUT4LMIX Input 1 Volume */
+       { 0x000006B2, 0x0000 },    /* R1714  - OUT4LMIX Input 2 Source */
+       { 0x000006B3, 0x0080 },    /* R1715  - OUT4LMIX Input 2 Volume */
+       { 0x000006B4, 0x0000 },    /* R1716  - OUT4LMIX Input 3 Source */
+       { 0x000006B5, 0x0080 },    /* R1717  - OUT4LMIX Input 3 Volume */
+       { 0x000006B6, 0x0000 },    /* R1718  - OUT4LMIX Input 4 Source */
+       { 0x000006B7, 0x0080 },    /* R1719  - OUT4LMIX Input 4 Volume */
+       { 0x000006C0, 0x0000 },    /* R1728  - OUT5LMIX Input 1 Source */
+       { 0x000006C1, 0x0080 },    /* R1729  - OUT5LMIX Input 1 Volume */
+       { 0x000006C2, 0x0000 },    /* R1730  - OUT5LMIX Input 2 Source */
+       { 0x000006C3, 0x0080 },    /* R1731  - OUT5LMIX Input 2 Volume */
+       { 0x000006C4, 0x0000 },    /* R1732  - OUT5LMIX Input 3 Source */
+       { 0x000006C5, 0x0080 },    /* R1733  - OUT5LMIX Input 3 Volume */
+       { 0x000006C6, 0x0000 },    /* R1734  - OUT5LMIX Input 4 Source */
+       { 0x000006C7, 0x0080 },    /* R1735  - OUT5LMIX Input 4 Volume */
+       { 0x000006C8, 0x0000 },    /* R1736  - OUT5RMIX Input 1 Source */
+       { 0x000006C9, 0x0080 },    /* R1737  - OUT5RMIX Input 1 Volume */
+       { 0x000006CA, 0x0000 },    /* R1738  - OUT5RMIX Input 2 Source */
+       { 0x000006CB, 0x0080 },    /* R1739  - OUT5RMIX Input 2 Volume */
+       { 0x000006CC, 0x0000 },    /* R1740  - OUT5RMIX Input 3 Source */
+       { 0x000006CD, 0x0080 },    /* R1741  - OUT5RMIX Input 3 Volume */
+       { 0x000006CE, 0x0000 },    /* R1742  - OUT5RMIX Input 4 Source */
+       { 0x000006CF, 0x0080 },    /* R1743  - OUT5RMIX Input 4 Volume */
+       { 0x00000700, 0x0000 },    /* R1792  - AIF1TX1MIX Input 1 Source */
+       { 0x00000701, 0x0080 },    /* R1793  - AIF1TX1MIX Input 1 Volume */
+       { 0x00000702, 0x0000 },    /* R1794  - AIF1TX1MIX Input 2 Source */
+       { 0x00000703, 0x0080 },    /* R1795  - AIF1TX1MIX Input 2 Volume */
+       { 0x00000704, 0x0000 },    /* R1796  - AIF1TX1MIX Input 3 Source */
+       { 0x00000705, 0x0080 },    /* R1797  - AIF1TX1MIX Input 3 Volume */
+       { 0x00000706, 0x0000 },    /* R1798  - AIF1TX1MIX Input 4 Source */
+       { 0x00000707, 0x0080 },    /* R1799  - AIF1TX1MIX Input 4 Volume */
+       { 0x00000708, 0x0000 },    /* R1800  - AIF1TX2MIX Input 1 Source */
+       { 0x00000709, 0x0080 },    /* R1801  - AIF1TX2MIX Input 1 Volume */
+       { 0x0000070A, 0x0000 },    /* R1802  - AIF1TX2MIX Input 2 Source */
+       { 0x0000070B, 0x0080 },    /* R1803  - AIF1TX2MIX Input 2 Volume */
+       { 0x0000070C, 0x0000 },    /* R1804  - AIF1TX2MIX Input 3 Source */
+       { 0x0000070D, 0x0080 },    /* R1805  - AIF1TX2MIX Input 3 Volume */
+       { 0x0000070E, 0x0000 },    /* R1806  - AIF1TX2MIX Input 4 Source */
+       { 0x0000070F, 0x0080 },    /* R1807  - AIF1TX2MIX Input 4 Volume */
+       { 0x00000710, 0x0000 },    /* R1808  - AIF1TX3MIX Input 1 Source */
+       { 0x00000711, 0x0080 },    /* R1809  - AIF1TX3MIX Input 1 Volume */
+       { 0x00000712, 0x0000 },    /* R1810  - AIF1TX3MIX Input 2 Source */
+       { 0x00000713, 0x0080 },    /* R1811  - AIF1TX3MIX Input 2 Volume */
+       { 0x00000714, 0x0000 },    /* R1812  - AIF1TX3MIX Input 3 Source */
+       { 0x00000715, 0x0080 },    /* R1813  - AIF1TX3MIX Input 3 Volume */
+       { 0x00000716, 0x0000 },    /* R1814  - AIF1TX3MIX Input 4 Source */
+       { 0x00000717, 0x0080 },    /* R1815  - AIF1TX3MIX Input 4 Volume */
+       { 0x00000718, 0x0000 },    /* R1816  - AIF1TX4MIX Input 1 Source */
+       { 0x00000719, 0x0080 },    /* R1817  - AIF1TX4MIX Input 1 Volume */
+       { 0x0000071A, 0x0000 },    /* R1818  - AIF1TX4MIX Input 2 Source */
+       { 0x0000071B, 0x0080 },    /* R1819  - AIF1TX4MIX Input 2 Volume */
+       { 0x0000071C, 0x0000 },    /* R1820  - AIF1TX4MIX Input 3 Source */
+       { 0x0000071D, 0x0080 },    /* R1821  - AIF1TX4MIX Input 3 Volume */
+       { 0x0000071E, 0x0000 },    /* R1822  - AIF1TX4MIX Input 4 Source */
+       { 0x0000071F, 0x0080 },    /* R1823  - AIF1TX4MIX Input 4 Volume */
+       { 0x00000720, 0x0000 },    /* R1824  - AIF1TX5MIX Input 1 Source */
+       { 0x00000721, 0x0080 },    /* R1825  - AIF1TX5MIX Input 1 Volume */
+       { 0x00000722, 0x0000 },    /* R1826  - AIF1TX5MIX Input 2 Source */
+       { 0x00000723, 0x0080 },    /* R1827  - AIF1TX5MIX Input 2 Volume */
+       { 0x00000724, 0x0000 },    /* R1828  - AIF1TX5MIX Input 3 Source */
+       { 0x00000725, 0x0080 },    /* R1829  - AIF1TX5MIX Input 3 Volume */
+       { 0x00000726, 0x0000 },    /* R1830  - AIF1TX5MIX Input 4 Source */
+       { 0x00000727, 0x0080 },    /* R1831  - AIF1TX5MIX Input 4 Volume */
+       { 0x00000728, 0x0000 },    /* R1832  - AIF1TX6MIX Input 1 Source */
+       { 0x00000729, 0x0080 },    /* R1833  - AIF1TX6MIX Input 1 Volume */
+       { 0x0000072A, 0x0000 },    /* R1834  - AIF1TX6MIX Input 2 Source */
+       { 0x0000072B, 0x0080 },    /* R1835  - AIF1TX6MIX Input 2 Volume */
+       { 0x0000072C, 0x0000 },    /* R1836  - AIF1TX6MIX Input 3 Source */
+       { 0x0000072D, 0x0080 },    /* R1837  - AIF1TX6MIX Input 3 Volume */
+       { 0x0000072E, 0x0000 },    /* R1838  - AIF1TX6MIX Input 4 Source */
+       { 0x0000072F, 0x0080 },    /* R1839  - AIF1TX6MIX Input 4 Volume */
+       { 0x00000730, 0x0000 },    /* R1840  - AIF1TX7MIX Input 1 Source */
+       { 0x00000731, 0x0080 },    /* R1841  - AIF1TX7MIX Input 1 Volume */
+       { 0x00000732, 0x0000 },    /* R1842  - AIF1TX7MIX Input 2 Source */
+       { 0x00000733, 0x0080 },    /* R1843  - AIF1TX7MIX Input 2 Volume */
+       { 0x00000734, 0x0000 },    /* R1844  - AIF1TX7MIX Input 3 Source */
+       { 0x00000735, 0x0080 },    /* R1845  - AIF1TX7MIX Input 3 Volume */
+       { 0x00000736, 0x0000 },    /* R1846  - AIF1TX7MIX Input 4 Source */
+       { 0x00000737, 0x0080 },    /* R1847  - AIF1TX7MIX Input 4 Volume */
+       { 0x00000738, 0x0000 },    /* R1848  - AIF1TX8MIX Input 1 Source */
+       { 0x00000739, 0x0080 },    /* R1849  - AIF1TX8MIX Input 1 Volume */
+       { 0x0000073A, 0x0000 },    /* R1850  - AIF1TX8MIX Input 2 Source */
+       { 0x0000073B, 0x0080 },    /* R1851  - AIF1TX8MIX Input 2 Volume */
+       { 0x0000073C, 0x0000 },    /* R1852  - AIF1TX8MIX Input 3 Source */
+       { 0x0000073D, 0x0080 },    /* R1853  - AIF1TX8MIX Input 3 Volume */
+       { 0x0000073E, 0x0000 },    /* R1854  - AIF1TX8MIX Input 4 Source */
+       { 0x0000073F, 0x0080 },    /* R1855  - AIF1TX8MIX Input 4 Volume */
+       { 0x00000740, 0x0000 },    /* R1856  - AIF2TX1MIX Input 1 Source */
+       { 0x00000741, 0x0080 },    /* R1857  - AIF2TX1MIX Input 1 Volume */
+       { 0x00000742, 0x0000 },    /* R1858  - AIF2TX1MIX Input 2 Source */
+       { 0x00000743, 0x0080 },    /* R1859  - AIF2TX1MIX Input 2 Volume */
+       { 0x00000744, 0x0000 },    /* R1860  - AIF2TX1MIX Input 3 Source */
+       { 0x00000745, 0x0080 },    /* R1861  - AIF2TX1MIX Input 3 Volume */
+       { 0x00000746, 0x0000 },    /* R1862  - AIF2TX1MIX Input 4 Source */
+       { 0x00000747, 0x0080 },    /* R1863  - AIF2TX1MIX Input 4 Volume */
+       { 0x00000748, 0x0000 },    /* R1864  - AIF2TX2MIX Input 1 Source */
+       { 0x00000749, 0x0080 },    /* R1865  - AIF2TX2MIX Input 1 Volume */
+       { 0x0000074A, 0x0000 },    /* R1866  - AIF2TX2MIX Input 2 Source */
+       { 0x0000074B, 0x0080 },    /* R1867  - AIF2TX2MIX Input 2 Volume */
+       { 0x0000074C, 0x0000 },    /* R1868  - AIF2TX2MIX Input 3 Source */
+       { 0x0000074D, 0x0080 },    /* R1869  - AIF2TX2MIX Input 3 Volume */
+       { 0x0000074E, 0x0000 },    /* R1870  - AIF2TX2MIX Input 4 Source */
+       { 0x0000074F, 0x0080 },    /* R1871  - AIF2TX2MIX Input 4 Volume */
+       { 0x000007C0, 0x0000 },    /* R1984  - SLIMTX1MIX Input 1 Source */
+       { 0x000007C1, 0x0080 },    /* R1985  - SLIMTX1MIX Input 1 Volume */
+       { 0x000007C2, 0x0000 },    /* R1986  - SLIMTX1MIX Input 2 Source */
+       { 0x000007C3, 0x0080 },    /* R1987  - SLIMTX1MIX Input 2 Volume */
+       { 0x000007C4, 0x0000 },    /* R1988  - SLIMTX1MIX Input 3 Source */
+       { 0x000007C5, 0x0080 },    /* R1989  - SLIMTX1MIX Input 3 Volume */
+       { 0x000007C6, 0x0000 },    /* R1990  - SLIMTX1MIX Input 4 Source */
+       { 0x000007C7, 0x0080 },    /* R1991  - SLIMTX1MIX Input 4 Volume */
+       { 0x000007C8, 0x0000 },    /* R1992  - SLIMTX2MIX Input 1 Source */
+       { 0x000007C9, 0x0080 },    /* R1993  - SLIMTX2MIX Input 1 Volume */
+       { 0x000007CA, 0x0000 },    /* R1994  - SLIMTX2MIX Input 2 Source */
+       { 0x000007CB, 0x0080 },    /* R1995  - SLIMTX2MIX Input 2 Volume */
+       { 0x000007CC, 0x0000 },    /* R1996  - SLIMTX2MIX Input 3 Source */
+       { 0x000007CD, 0x0080 },    /* R1997  - SLIMTX2MIX Input 3 Volume */
+       { 0x000007CE, 0x0000 },    /* R1998  - SLIMTX2MIX Input 4 Source */
+       { 0x000007CF, 0x0080 },    /* R1999  - SLIMTX2MIX Input 4 Volume */
+       { 0x000007D0, 0x0000 },    /* R2000  - SLIMTX3MIX Input 1 Source */
+       { 0x000007D1, 0x0080 },    /* R2001  - SLIMTX3MIX Input 1 Volume */
+       { 0x000007D2, 0x0000 },    /* R2002  - SLIMTX3MIX Input 2 Source */
+       { 0x000007D3, 0x0080 },    /* R2003  - SLIMTX3MIX Input 2 Volume */
+       { 0x000007D4, 0x0000 },    /* R2004  - SLIMTX3MIX Input 3 Source */
+       { 0x000007D5, 0x0080 },    /* R2005  - SLIMTX3MIX Input 3 Volume */
+       { 0x000007D6, 0x0000 },    /* R2006  - SLIMTX3MIX Input 4 Source */
+       { 0x000007D7, 0x0080 },    /* R2007  - SLIMTX3MIX Input 4 Volume */
+       { 0x000007D8, 0x0000 },    /* R2008  - SLIMTX4MIX Input 1 Source */
+       { 0x000007D9, 0x0080 },    /* R2009  - SLIMTX4MIX Input 1 Volume */
+       { 0x000007DA, 0x0000 },    /* R2010  - SLIMTX4MIX Input 2 Source */
+       { 0x000007DB, 0x0080 },    /* R2011  - SLIMTX4MIX Input 2 Volume */
+       { 0x000007DC, 0x0000 },    /* R2012  - SLIMTX4MIX Input 3 Source */
+       { 0x000007DD, 0x0080 },    /* R2013  - SLIMTX4MIX Input 3 Volume */
+       { 0x000007DE, 0x0000 },    /* R2014  - SLIMTX4MIX Input 4 Source */
+       { 0x000007DF, 0x0080 },    /* R2015  - SLIMTX4MIX Input 4 Volume */
+       { 0x000007E0, 0x0000 },    /* R2016  - SLIMTX5MIX Input 1 Source */
+       { 0x000007E1, 0x0080 },    /* R2017  - SLIMTX5MIX Input 1 Volume */
+       { 0x000007E2, 0x0000 },    /* R2018  - SLIMTX5MIX Input 2 Source */
+       { 0x000007E3, 0x0080 },    /* R2019  - SLIMTX5MIX Input 2 Volume */
+       { 0x000007E4, 0x0000 },    /* R2020  - SLIMTX5MIX Input 3 Source */
+       { 0x000007E5, 0x0080 },    /* R2021  - SLIMTX5MIX Input 3 Volume */
+       { 0x000007E6, 0x0000 },    /* R2022  - SLIMTX5MIX Input 4 Source */
+       { 0x000007E7, 0x0080 },    /* R2023  - SLIMTX5MIX Input 4 Volume */
+       { 0x000007E8, 0x0000 },    /* R2024  - SLIMTX6MIX Input 1 Source */
+       { 0x000007E9, 0x0080 },    /* R2025  - SLIMTX6MIX Input 1 Volume */
+       { 0x000007EA, 0x0000 },    /* R2026  - SLIMTX6MIX Input 2 Source */
+       { 0x000007EB, 0x0080 },    /* R2027  - SLIMTX6MIX Input 2 Volume */
+       { 0x000007EC, 0x0000 },    /* R2028  - SLIMTX6MIX Input 3 Source */
+       { 0x000007ED, 0x0080 },    /* R2029  - SLIMTX6MIX Input 3 Volume */
+       { 0x000007EE, 0x0000 },    /* R2030  - SLIMTX6MIX Input 4 Source */
+       { 0x000007EF, 0x0080 },    /* R2031  - SLIMTX6MIX Input 4 Volume */
+       { 0x000007F0, 0x0000 },    /* R2032  - SLIMTX7MIX Input 1 Source */
+       { 0x000007F1, 0x0080 },    /* R2033  - SLIMTX7MIX Input 1 Volume */
+       { 0x000007F2, 0x0000 },    /* R2034  - SLIMTX7MIX Input 2 Source */
+       { 0x000007F3, 0x0080 },    /* R2035  - SLIMTX7MIX Input 2 Volume */
+       { 0x000007F4, 0x0000 },    /* R2036  - SLIMTX7MIX Input 3 Source */
+       { 0x000007F5, 0x0080 },    /* R2037  - SLIMTX7MIX Input 3 Volume */
+       { 0x000007F6, 0x0000 },    /* R2038  - SLIMTX7MIX Input 4 Source */
+       { 0x000007F7, 0x0080 },    /* R2039  - SLIMTX7MIX Input 4 Volume */
+       { 0x000007F8, 0x0000 },    /* R2040  - SLIMTX8MIX Input 1 Source */
+       { 0x000007F9, 0x0080 },    /* R2041  - SLIMTX8MIX Input 1 Volume */
+       { 0x000007FA, 0x0000 },    /* R2042  - SLIMTX8MIX Input 2 Source */
+       { 0x000007FB, 0x0080 },    /* R2043  - SLIMTX8MIX Input 2 Volume */
+       { 0x000007FC, 0x0000 },    /* R2044  - SLIMTX8MIX Input 3 Source */
+       { 0x000007FD, 0x0080 },    /* R2045  - SLIMTX8MIX Input 3 Volume */
+       { 0x000007FE, 0x0000 },    /* R2046  - SLIMTX8MIX Input 4 Source */
+       { 0x000007FF, 0x0080 },    /* R2047  - SLIMTX8MIX Input 4 Volume */
+       { 0x00000880, 0x0000 },    /* R2176  - EQ1MIX Input 1 Source */
+       { 0x00000881, 0x0080 },    /* R2177  - EQ1MIX Input 1 Volume */
+       { 0x00000882, 0x0000 },    /* R2178  - EQ1MIX Input 2 Source */
+       { 0x00000883, 0x0080 },    /* R2179  - EQ1MIX Input 2 Volume */
+       { 0x00000884, 0x0000 },    /* R2180  - EQ1MIX Input 3 Source */
+       { 0x00000885, 0x0080 },    /* R2181  - EQ1MIX Input 3 Volume */
+       { 0x00000886, 0x0000 },    /* R2182  - EQ1MIX Input 4 Source */
+       { 0x00000887, 0x0080 },    /* R2183  - EQ1MIX Input 4 Volume */
+       { 0x00000888, 0x0000 },    /* R2184  - EQ2MIX Input 1 Source */
+       { 0x00000889, 0x0080 },    /* R2185  - EQ2MIX Input 1 Volume */
+       { 0x0000088A, 0x0000 },    /* R2186  - EQ2MIX Input 2 Source */
+       { 0x0000088B, 0x0080 },    /* R2187  - EQ2MIX Input 2 Volume */
+       { 0x0000088C, 0x0000 },    /* R2188  - EQ2MIX Input 3 Source */
+       { 0x0000088D, 0x0080 },    /* R2189  - EQ2MIX Input 3 Volume */
+       { 0x0000088E, 0x0000 },    /* R2190  - EQ2MIX Input 4 Source */
+       { 0x0000088F, 0x0080 },    /* R2191  - EQ2MIX Input 4 Volume */
+       { 0x00000890, 0x0000 },    /* R2192  - EQ3MIX Input 1 Source */
+       { 0x00000891, 0x0080 },    /* R2193  - EQ3MIX Input 1 Volume */
+       { 0x00000892, 0x0000 },    /* R2194  - EQ3MIX Input 2 Source */
+       { 0x00000893, 0x0080 },    /* R2195  - EQ3MIX Input 2 Volume */
+       { 0x00000894, 0x0000 },    /* R2196  - EQ3MIX Input 3 Source */
+       { 0x00000895, 0x0080 },    /* R2197  - EQ3MIX Input 3 Volume */
+       { 0x00000896, 0x0000 },    /* R2198  - EQ3MIX Input 4 Source */
+       { 0x00000897, 0x0080 },    /* R2199  - EQ3MIX Input 4 Volume */
+       { 0x00000898, 0x0000 },    /* R2200  - EQ4MIX Input 1 Source */
+       { 0x00000899, 0x0080 },    /* R2201  - EQ4MIX Input 1 Volume */
+       { 0x0000089A, 0x0000 },    /* R2202  - EQ4MIX Input 2 Source */
+       { 0x0000089B, 0x0080 },    /* R2203  - EQ4MIX Input 2 Volume */
+       { 0x0000089C, 0x0000 },    /* R2204  - EQ4MIX Input 3 Source */
+       { 0x0000089D, 0x0080 },    /* R2205  - EQ4MIX Input 3 Volume */
+       { 0x0000089E, 0x0000 },    /* R2206  - EQ4MIX Input 4 Source */
+       { 0x0000089F, 0x0080 },    /* R2207  - EQ4MIX Input 4 Volume */
+       { 0x000008C0, 0x0000 },    /* R2240  - DRC1LMIX Input 1 Source */
+       { 0x000008C1, 0x0080 },    /* R2241  - DRC1LMIX Input 1 Volume */
+       { 0x000008C2, 0x0000 },    /* R2242  - DRC1LMIX Input 2 Source */
+       { 0x000008C3, 0x0080 },    /* R2243  - DRC1LMIX Input 2 Volume */
+       { 0x000008C4, 0x0000 },    /* R2244  - DRC1LMIX Input 3 Source */
+       { 0x000008C5, 0x0080 },    /* R2245  - DRC1LMIX Input 3 Volume */
+       { 0x000008C6, 0x0000 },    /* R2246  - DRC1LMIX Input 4 Source */
+       { 0x000008C7, 0x0080 },    /* R2247  - DRC1LMIX Input 4 Volume */
+       { 0x000008C8, 0x0000 },    /* R2248  - DRC1RMIX Input 1 Source */
+       { 0x000008C9, 0x0080 },    /* R2249  - DRC1RMIX Input 1 Volume */
+       { 0x000008CA, 0x0000 },    /* R2250  - DRC1RMIX Input 2 Source */
+       { 0x000008CB, 0x0080 },    /* R2251  - DRC1RMIX Input 2 Volume */
+       { 0x000008CC, 0x0000 },    /* R2252  - DRC1RMIX Input 3 Source */
+       { 0x000008CD, 0x0080 },    /* R2253  - DRC1RMIX Input 3 Volume */
+       { 0x000008CE, 0x0000 },    /* R2254  - DRC1RMIX Input 4 Source */
+       { 0x000008CF, 0x0080 },    /* R2255  - DRC1RMIX Input 4 Volume */
+       { 0x00000900, 0x0000 },    /* R2304  - HPLP1MIX Input 1 Source */
+       { 0x00000901, 0x0080 },    /* R2305  - HPLP1MIX Input 1 Volume */
+       { 0x00000902, 0x0000 },    /* R2306  - HPLP1MIX Input 2 Source */
+       { 0x00000903, 0x0080 },    /* R2307  - HPLP1MIX Input 2 Volume */
+       { 0x00000904, 0x0000 },    /* R2308  - HPLP1MIX Input 3 Source */
+       { 0x00000905, 0x0080 },    /* R2309  - HPLP1MIX Input 3 Volume */
+       { 0x00000906, 0x0000 },    /* R2310  - HPLP1MIX Input 4 Source */
+       { 0x00000907, 0x0080 },    /* R2311  - HPLP1MIX Input 4 Volume */
+       { 0x00000908, 0x0000 },    /* R2312  - HPLP2MIX Input 1 Source */
+       { 0x00000909, 0x0080 },    /* R2313  - HPLP2MIX Input 1 Volume */
+       { 0x0000090A, 0x0000 },    /* R2314  - HPLP2MIX Input 2 Source */
+       { 0x0000090B, 0x0080 },    /* R2315  - HPLP2MIX Input 2 Volume */
+       { 0x0000090C, 0x0000 },    /* R2316  - HPLP2MIX Input 3 Source */
+       { 0x0000090D, 0x0080 },    /* R2317  - HPLP2MIX Input 3 Volume */
+       { 0x0000090E, 0x0000 },    /* R2318  - HPLP2MIX Input 4 Source */
+       { 0x0000090F, 0x0080 },    /* R2319  - HPLP2MIX Input 4 Volume */
+       { 0x00000910, 0x0000 },    /* R2320  - HPLP3MIX Input 1 Source */
+       { 0x00000911, 0x0080 },    /* R2321  - HPLP3MIX Input 1 Volume */
+       { 0x00000912, 0x0000 },    /* R2322  - HPLP3MIX Input 2 Source */
+       { 0x00000913, 0x0080 },    /* R2323  - HPLP3MIX Input 2 Volume */
+       { 0x00000914, 0x0000 },    /* R2324  - HPLP3MIX Input 3 Source */
+       { 0x00000915, 0x0080 },    /* R2325  - HPLP3MIX Input 3 Volume */
+       { 0x00000916, 0x0000 },    /* R2326  - HPLP3MIX Input 4 Source */
+       { 0x00000917, 0x0080 },    /* R2327  - HPLP3MIX Input 4 Volume */
+       { 0x00000918, 0x0000 },    /* R2328  - HPLP4MIX Input 1 Source */
+       { 0x00000919, 0x0080 },    /* R2329  - HPLP4MIX Input 1 Volume */
+       { 0x0000091A, 0x0000 },    /* R2330  - HPLP4MIX Input 2 Source */
+       { 0x0000091B, 0x0080 },    /* R2331  - HPLP4MIX Input 2 Volume */
+       { 0x0000091C, 0x0000 },    /* R2332  - HPLP4MIX Input 3 Source */
+       { 0x0000091D, 0x0080 },    /* R2333  - HPLP4MIX Input 3 Volume */
+       { 0x0000091E, 0x0000 },    /* R2334  - HPLP4MIX Input 4 Source */
+       { 0x0000091F, 0x0080 },    /* R2335  - HPLP4MIX Input 4 Volume */
+       { 0x00000B00, 0x0000 },    /* R2816  - ISRC1DEC1MIX Input 1 Source */
+       { 0x00000B08, 0x0000 },    /* R2824  - ISRC1DEC2MIX Input 1 Source */
+       { 0x00000B20, 0x0000 },    /* R2848  - ISRC1INT1MIX Input 1 Source */
+       { 0x00000B28, 0x0000 },    /* R2856  - ISRC1INT2MIX Input 1 Source */
+       { 0x00000B40, 0x0000 },    /* R2880  - ISRC2DEC1MIX Input 1 Source */
+       { 0x00000B48, 0x0000 },    /* R2888  - ISRC2DEC2MIX Input 1 Source */
+       { 0x00000B60, 0x0000 },    /* R2912  - ISRC2INT1MIX Input 1 Source */
+       { 0x00000B68, 0x0000 },    /* R2920  - ISRC2INT2MIX Input 1 Source */
+       { 0x00000C00, 0xA101 },    /* R3072  - GPIO1 CTRL */
+       { 0x00000C01, 0xA101 },    /* R3073  - GPIO2 CTRL */
+       { 0x00000C02, 0xA101 },    /* R3074  - GPIO3 CTRL */
+       { 0x00000C03, 0xA101 },    /* R3075  - GPIO4 CTRL */
+       { 0x00000C04, 0xA101 },    /* R3076  - GPIO5 CTRL */
+       { 0x00000C0F, 0x0400 },    /* R3087  - IRQ CTRL 1 */
+       { 0x00000C10, 0x1000 },    /* R3088  - GPIO Debounce Config */
+       { 0x00000C20, 0x8002 },    /* R3104  - Misc Pad Ctrl 1 */
+       { 0x00000C21, 0x0001 },    /* R3105  - Misc Pad Ctrl 2 */
+       { 0x00000C22, 0x0000 },    /* R3106  - Misc Pad Ctrl 3 */
+       { 0x00000C23, 0x0000 },    /* R3107  - Misc Pad Ctrl 4 */
+       { 0x00000C24, 0x0000 },    /* R3108  - Misc Pad Ctrl 5 */
+       { 0x00000D08, 0xFFFF },    /* R3336  - Interrupt Status 1 Mask */
+       { 0x00000D0A, 0xFFFF },    /* R3338  - Interrupt Status 3 Mask */
+       { 0x00000D0B, 0xFFFF },    /* R3339  - Interrupt Status 4 Mask */
+       { 0x00000D0C, 0xFEFF },    /* R3340  - Interrupt Status 5 Mask */
+       { 0x00000D0F, 0x0000 },    /* R3343  - Interrupt Control */
+       { 0x00000D18, 0xFFFF },    /* R3352  - IRQ2 Status 1 Mask */
+       { 0x00000D1A, 0xFFFF },    /* R3354  - IRQ2 Status 3 Mask */
+       { 0x00000D1B, 0xFFFF },    /* R3355  - IRQ2 Status 4 Mask */
+       { 0x00000D1C, 0xFFFF },    /* R3356  - IRQ2 Status 5 Mask */
+       { 0x00000D1F, 0x0000 },    /* R3359  - IRQ2 Control */
+       { 0x00000D53, 0xFFFF },    /* R3411  - AOD IRQ Mask IRQ1 */
+       { 0x00000D54, 0xFFFF },    /* R3412  - AOD IRQ Mask IRQ2 */
+       { 0x00000D56, 0x0000 },    /* R3414  - Jack detect debounce */
+       { 0x00000E00, 0x0000 },    /* R3584  - FX_Ctrl1 */
+       { 0x00000E01, 0x0000 },    /* R3585  - FX_Ctrl2 */
+       { 0x00000E10, 0x6318 },    /* R3600  - EQ1_1 */
+       { 0x00000E11, 0x6300 },    /* R3601  - EQ1_2 */
+       { 0x00000E12, 0x0FC8 },    /* R3602  - EQ1_3 */
+       { 0x00000E13, 0x03FE },    /* R3603  - EQ1_4 */
+       { 0x00000E14, 0x00E0 },    /* R3604  - EQ1_5 */
+       { 0x00000E15, 0x1EC4 },    /* R3605  - EQ1_6 */
+       { 0x00000E16, 0xF136 },    /* R3606  - EQ1_7 */
+       { 0x00000E17, 0x0409 },    /* R3607  - EQ1_8 */
+       { 0x00000E18, 0x04CC },    /* R3608  - EQ1_9 */
+       { 0x00000E19, 0x1C9B },    /* R3609  - EQ1_10 */
+       { 0x00000E1A, 0xF337 },    /* R3610  - EQ1_11 */
+       { 0x00000E1B, 0x040B },    /* R3611  - EQ1_12 */
+       { 0x00000E1C, 0x0CBB },    /* R3612  - EQ1_13 */
+       { 0x00000E1D, 0x16F8 },    /* R3613  - EQ1_14 */
+       { 0x00000E1E, 0xF7D9 },    /* R3614  - EQ1_15 */
+       { 0x00000E1F, 0x040A },    /* R3615  - EQ1_16 */
+       { 0x00000E20, 0x1F14 },    /* R3616  - EQ1_17 */
+       { 0x00000E21, 0x058C },    /* R3617  - EQ1_18 */
+       { 0x00000E22, 0x0563 },    /* R3618  - EQ1_19 */
+       { 0x00000E23, 0x4000 },    /* R3619  - EQ1_20 */
+       { 0x00000E24, 0x0B75 },    /* R3620  - EQ1_21 */
+       { 0x00000E26, 0x6318 },    /* R3622  - EQ2_1 */
+       { 0x00000E27, 0x6300 },    /* R3623  - EQ2_2 */
+       { 0x00000E28, 0x0FC8 },    /* R3624  - EQ2_3 */
+       { 0x00000E29, 0x03FE },    /* R3625  - EQ2_4 */
+       { 0x00000E2A, 0x00E0 },    /* R3626  - EQ2_5 */
+       { 0x00000E2B, 0x1EC4 },    /* R3627  - EQ2_6 */
+       { 0x00000E2C, 0xF136 },    /* R3628  - EQ2_7 */
+       { 0x00000E2D, 0x0409 },    /* R3629  - EQ2_8 */
+       { 0x00000E2E, 0x04CC },    /* R3630  - EQ2_9 */
+       { 0x00000E2F, 0x1C9B },    /* R3631  - EQ2_10 */
+       { 0x00000E30, 0xF337 },    /* R3632  - EQ2_11 */
+       { 0x00000E31, 0x040B },    /* R3633  - EQ2_12 */
+       { 0x00000E32, 0x0CBB },    /* R3634  - EQ2_13 */
+       { 0x00000E33, 0x16F8 },    /* R3635  - EQ2_14 */
+       { 0x00000E34, 0xF7D9 },    /* R3636  - EQ2_15 */
+       { 0x00000E35, 0x040A },    /* R3637  - EQ2_16 */
+       { 0x00000E36, 0x1F14 },    /* R3638  - EQ2_17 */
+       { 0x00000E37, 0x058C },    /* R3639  - EQ2_18 */
+       { 0x00000E38, 0x0563 },    /* R3640  - EQ2_19 */
+       { 0x00000E39, 0x4000 },    /* R3641  - EQ2_20 */
+       { 0x00000E3A, 0x0B75 },    /* R3642  - EQ2_21 */
+       { 0x00000E3C, 0x6318 },    /* R3644  - EQ3_1 */
+       { 0x00000E3D, 0x6300 },    /* R3645  - EQ3_2 */
+       { 0x00000E3E, 0x0FC8 },    /* R3646  - EQ3_3 */
+       { 0x00000E3F, 0x03FE },    /* R3647  - EQ3_4 */
+       { 0x00000E40, 0x00E0 },    /* R3648  - EQ3_5 */
+       { 0x00000E41, 0x1EC4 },    /* R3649  - EQ3_6 */
+       { 0x00000E42, 0xF136 },    /* R3650  - EQ3_7 */
+       { 0x00000E43, 0x0409 },    /* R3651  - EQ3_8 */
+       { 0x00000E44, 0x04CC },    /* R3652  - EQ3_9 */
+       { 0x00000E45, 0x1C9B },    /* R3653  - EQ3_10 */
+       { 0x00000E46, 0xF337 },    /* R3654  - EQ3_11 */
+       { 0x00000E47, 0x040B },    /* R3655  - EQ3_12 */
+       { 0x00000E48, 0x0CBB },    /* R3656  - EQ3_13 */
+       { 0x00000E49, 0x16F8 },    /* R3657  - EQ3_14 */
+       { 0x00000E4A, 0xF7D9 },    /* R3658  - EQ3_15 */
+       { 0x00000E4B, 0x040A },    /* R3659  - EQ3_16 */
+       { 0x00000E4C, 0x1F14 },    /* R3660  - EQ3_17 */
+       { 0x00000E4D, 0x058C },    /* R3661  - EQ3_18 */
+       { 0x00000E4E, 0x0563 },    /* R3662  - EQ3_19 */
+       { 0x00000E4F, 0x4000 },    /* R3663  - EQ3_20 */
+       { 0x00000E50, 0x0B75 },    /* R3664  - EQ3_21 */
+       { 0x00000E52, 0x6318 },    /* R3666  - EQ4_1 */
+       { 0x00000E53, 0x6300 },    /* R3667  - EQ4_2 */
+       { 0x00000E54, 0x0FC8 },    /* R3668  - EQ4_3 */
+       { 0x00000E55, 0x03FE },    /* R3669  - EQ4_4 */
+       { 0x00000E56, 0x00E0 },    /* R3670  - EQ4_5 */
+       { 0x00000E57, 0x1EC4 },    /* R3671  - EQ4_6 */
+       { 0x00000E58, 0xF136 },    /* R3672  - EQ4_7 */
+       { 0x00000E59, 0x0409 },    /* R3673  - EQ4_8 */
+       { 0x00000E5A, 0x04CC },    /* R3674  - EQ4_9 */
+       { 0x00000E5B, 0x1C9B },    /* R3675  - EQ4_10 */
+       { 0x00000E5C, 0xF337 },    /* R3676  - EQ4_11 */
+       { 0x00000E5D, 0x040B },    /* R3677  - EQ4_12 */
+       { 0x00000E5E, 0x0CBB },    /* R3678  - EQ4_13 */
+       { 0x00000E5F, 0x16F8 },    /* R3679  - EQ4_14 */
+       { 0x00000E60, 0xF7D9 },    /* R3680  - EQ4_15 */
+       { 0x00000E61, 0x040A },    /* R3681  - EQ4_16 */
+       { 0x00000E62, 0x1F14 },    /* R3682  - EQ4_17 */
+       { 0x00000E63, 0x058C },    /* R3683  - EQ4_18 */
+       { 0x00000E64, 0x0563 },    /* R3684  - EQ4_19 */
+       { 0x00000E65, 0x4000 },    /* R3685  - EQ4_20 */
+       { 0x00000E66, 0x0B75 },    /* R3686  - EQ4_21 */
+       { 0x00000E80, 0x0018 },    /* R3712  - DRC1 ctrl1 */
+       { 0x00000E81, 0x0933 },    /* R3713  - DRC1 ctrl2 */
+       { 0x00000E82, 0x0018 },    /* R3714  - DRC1 ctrl3 */
+       { 0x00000E83, 0x0000 },    /* R3715  - DRC1 ctrl4 */
+       { 0x00000E84, 0x0000 },    /* R3716  - DRC1 ctrl5 */
+       { 0x00000EC0, 0x0000 },    /* R3776  - HPLPF1_1 */
+       { 0x00000EC1, 0x0000 },    /* R3777  - HPLPF1_2 */
+       { 0x00000EC4, 0x0000 },    /* R3780  - HPLPF2_1 */
+       { 0x00000EC5, 0x0000 },    /* R3781  - HPLPF2_2 */
+       { 0x00000EC8, 0x0000 },    /* R3784  - HPLPF3_1 */
+       { 0x00000EC9, 0x0000 },    /* R3785  - HPLPF3_2 */
+       { 0x00000ECC, 0x0000 },    /* R3788  - HPLPF4_1 */
+       { 0x00000ECD, 0x0000 },    /* R3789  - HPLPF4_2 */
+       { 0x00000EF0, 0x0000 },    /* R3824  - ISRC 1 CTRL 1 */
+       { 0x00000EF1, 0x0000 },    /* R3825  - ISRC 1 CTRL 2 */
+       { 0x00000EF2, 0x0000 },    /* R3826  - ISRC 1 CTRL 3 */
+       { 0x00000EF3, 0x0000 },    /* R3827  - ISRC 2 CTRL 1 */
+       { 0x00000EF4, 0x0000 },    /* R3828  - ISRC 2 CTRL 2 */
+       { 0x00000EF5, 0x0000 },    /* R3829  - ISRC 2 CTRL 3 */
+       { 0x00001100, 0x0010 },    /* R4352  - DSP1 Control 1 */
+       { 0x00001101, 0x0000 },    /* R4353  - DSP1 Clocking 1 */
+};
+
+static bool wm8997_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case ARIZONA_SOFTWARE_RESET:
+       case ARIZONA_DEVICE_REVISION:
+       case ARIZONA_CTRL_IF_I2C1_CFG_1:
+       case ARIZONA_WRITE_SEQUENCER_CTRL_0:
+       case ARIZONA_WRITE_SEQUENCER_CTRL_1:
+       case ARIZONA_WRITE_SEQUENCER_CTRL_2:
+       case ARIZONA_TONE_GENERATOR_1:
+       case ARIZONA_TONE_GENERATOR_2:
+       case ARIZONA_TONE_GENERATOR_3:
+       case ARIZONA_TONE_GENERATOR_4:
+       case ARIZONA_TONE_GENERATOR_5:
+       case ARIZONA_PWM_DRIVE_1:
+       case ARIZONA_PWM_DRIVE_2:
+       case ARIZONA_PWM_DRIVE_3:
+       case ARIZONA_WAKE_CONTROL:
+       case ARIZONA_SEQUENCE_CONTROL:
+       case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+       case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+       case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+       case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+       case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+       case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+       case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3:
+       case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4:
+       case ARIZONA_COMFORT_NOISE_GENERATOR:
+       case ARIZONA_HAPTICS_CONTROL_1:
+       case ARIZONA_HAPTICS_CONTROL_2:
+       case ARIZONA_HAPTICS_PHASE_1_INTENSITY:
+       case ARIZONA_HAPTICS_PHASE_1_DURATION:
+       case ARIZONA_HAPTICS_PHASE_2_INTENSITY:
+       case ARIZONA_HAPTICS_PHASE_2_DURATION:
+       case ARIZONA_HAPTICS_PHASE_3_INTENSITY:
+       case ARIZONA_HAPTICS_PHASE_3_DURATION:
+       case ARIZONA_HAPTICS_STATUS:
+       case ARIZONA_CLOCK_32K_1:
+       case ARIZONA_SYSTEM_CLOCK_1:
+       case ARIZONA_SAMPLE_RATE_1:
+       case ARIZONA_SAMPLE_RATE_2:
+       case ARIZONA_SAMPLE_RATE_3:
+       case ARIZONA_SAMPLE_RATE_1_STATUS:
+       case ARIZONA_SAMPLE_RATE_2_STATUS:
+       case ARIZONA_SAMPLE_RATE_3_STATUS:
+       case ARIZONA_ASYNC_CLOCK_1:
+       case ARIZONA_ASYNC_SAMPLE_RATE_1:
+       case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case ARIZONA_OUTPUT_SYSTEM_CLOCK:
+       case ARIZONA_OUTPUT_ASYNC_CLOCK:
+       case ARIZONA_RATE_ESTIMATOR_1:
+       case ARIZONA_RATE_ESTIMATOR_2:
+       case ARIZONA_RATE_ESTIMATOR_3:
+       case ARIZONA_RATE_ESTIMATOR_4:
+       case ARIZONA_RATE_ESTIMATOR_5:
+       case ARIZONA_FLL1_CONTROL_1:
+       case ARIZONA_FLL1_CONTROL_2:
+       case ARIZONA_FLL1_CONTROL_3:
+       case ARIZONA_FLL1_CONTROL_4:
+       case ARIZONA_FLL1_CONTROL_5:
+       case ARIZONA_FLL1_CONTROL_6:
+       case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
+       case ARIZONA_FLL1_NCO_TEST_0:
+       case ARIZONA_FLL1_SYNCHRONISER_1:
+       case ARIZONA_FLL1_SYNCHRONISER_2:
+       case ARIZONA_FLL1_SYNCHRONISER_3:
+       case ARIZONA_FLL1_SYNCHRONISER_4:
+       case ARIZONA_FLL1_SYNCHRONISER_5:
+       case ARIZONA_FLL1_SYNCHRONISER_6:
+       case ARIZONA_FLL1_SPREAD_SPECTRUM:
+       case ARIZONA_FLL1_GPIO_CLOCK:
+       case ARIZONA_FLL2_CONTROL_1:
+       case ARIZONA_FLL2_CONTROL_2:
+       case ARIZONA_FLL2_CONTROL_3:
+       case ARIZONA_FLL2_CONTROL_4:
+       case ARIZONA_FLL2_CONTROL_5:
+       case ARIZONA_FLL2_CONTROL_6:
+       case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
+       case ARIZONA_FLL2_NCO_TEST_0:
+       case ARIZONA_FLL2_SYNCHRONISER_1:
+       case ARIZONA_FLL2_SYNCHRONISER_2:
+       case ARIZONA_FLL2_SYNCHRONISER_3:
+       case ARIZONA_FLL2_SYNCHRONISER_4:
+       case ARIZONA_FLL2_SYNCHRONISER_5:
+       case ARIZONA_FLL2_SYNCHRONISER_6:
+       case ARIZONA_FLL2_SPREAD_SPECTRUM:
+       case ARIZONA_FLL2_GPIO_CLOCK:
+       case ARIZONA_MIC_CHARGE_PUMP_1:
+       case ARIZONA_LDO1_CONTROL_1:
+       case ARIZONA_LDO2_CONTROL_1:
+       case ARIZONA_MIC_BIAS_CTRL_1:
+       case ARIZONA_MIC_BIAS_CTRL_2:
+       case ARIZONA_MIC_BIAS_CTRL_3:
+       case ARIZONA_ACCESSORY_DETECT_MODE_1:
+       case ARIZONA_HEADPHONE_DETECT_1:
+       case ARIZONA_HEADPHONE_DETECT_2:
+       case ARIZONA_MIC_DETECT_1:
+       case ARIZONA_MIC_DETECT_2:
+       case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_MIC_NOISE_MIX_CONTROL_1:
+       case ARIZONA_ISOLATION_CONTROL:
+       case ARIZONA_JACK_DETECT_ANALOGUE:
+       case ARIZONA_INPUT_ENABLES:
+       case ARIZONA_INPUT_ENABLES_STATUS:
+       case ARIZONA_INPUT_RATE:
+       case ARIZONA_INPUT_VOLUME_RAMP:
+       case ARIZONA_IN1L_CONTROL:
+       case ARIZONA_ADC_DIGITAL_VOLUME_1L:
+       case ARIZONA_DMIC1L_CONTROL:
+       case ARIZONA_IN1R_CONTROL:
+       case ARIZONA_ADC_DIGITAL_VOLUME_1R:
+       case ARIZONA_DMIC1R_CONTROL:
+       case ARIZONA_IN2L_CONTROL:
+       case ARIZONA_ADC_DIGITAL_VOLUME_2L:
+       case ARIZONA_DMIC2L_CONTROL:
+       case ARIZONA_IN2R_CONTROL:
+       case ARIZONA_ADC_DIGITAL_VOLUME_2R:
+       case ARIZONA_DMIC2R_CONTROL:
+       case ARIZONA_OUTPUT_ENABLES_1:
+       case ARIZONA_OUTPUT_STATUS_1:
+       case ARIZONA_RAW_OUTPUT_STATUS_1:
+       case ARIZONA_OUTPUT_RATE_1:
+       case ARIZONA_OUTPUT_VOLUME_RAMP:
+       case ARIZONA_OUTPUT_PATH_CONFIG_1L:
+       case ARIZONA_DAC_DIGITAL_VOLUME_1L:
+       case ARIZONA_DAC_VOLUME_LIMIT_1L:
+       case ARIZONA_NOISE_GATE_SELECT_1L:
+       case ARIZONA_OUTPUT_PATH_CONFIG_1R:
+       case ARIZONA_DAC_DIGITAL_VOLUME_1R:
+       case ARIZONA_DAC_VOLUME_LIMIT_1R:
+       case ARIZONA_NOISE_GATE_SELECT_1R:
+       case ARIZONA_OUTPUT_PATH_CONFIG_3L:
+       case ARIZONA_DAC_DIGITAL_VOLUME_3L:
+       case ARIZONA_DAC_VOLUME_LIMIT_3L:
+       case ARIZONA_NOISE_GATE_SELECT_3L:
+       case ARIZONA_OUTPUT_PATH_CONFIG_4L:
+       case ARIZONA_DAC_DIGITAL_VOLUME_4L:
+       case ARIZONA_OUT_VOLUME_4L:
+       case ARIZONA_NOISE_GATE_SELECT_4L:
+       case ARIZONA_OUTPUT_PATH_CONFIG_5L:
+       case ARIZONA_DAC_DIGITAL_VOLUME_5L:
+       case ARIZONA_DAC_VOLUME_LIMIT_5L:
+       case ARIZONA_NOISE_GATE_SELECT_5L:
+       case ARIZONA_DAC_DIGITAL_VOLUME_5R:
+       case ARIZONA_DAC_VOLUME_LIMIT_5R:
+       case ARIZONA_NOISE_GATE_SELECT_5R:
+       case ARIZONA_DAC_AEC_CONTROL_1:
+       case ARIZONA_NOISE_GATE_CONTROL:
+       case ARIZONA_PDM_SPK1_CTRL_1:
+       case ARIZONA_PDM_SPK1_CTRL_2:
+       case ARIZONA_AIF1_BCLK_CTRL:
+       case ARIZONA_AIF1_TX_PIN_CTRL:
+       case ARIZONA_AIF1_RX_PIN_CTRL:
+       case ARIZONA_AIF1_RATE_CTRL:
+       case ARIZONA_AIF1_FORMAT:
+       case ARIZONA_AIF1_TX_BCLK_RATE:
+       case ARIZONA_AIF1_RX_BCLK_RATE:
+       case ARIZONA_AIF1_FRAME_CTRL_1:
+       case ARIZONA_AIF1_FRAME_CTRL_2:
+       case ARIZONA_AIF1_FRAME_CTRL_3:
+       case ARIZONA_AIF1_FRAME_CTRL_4:
+       case ARIZONA_AIF1_FRAME_CTRL_5:
+       case ARIZONA_AIF1_FRAME_CTRL_6:
+       case ARIZONA_AIF1_FRAME_CTRL_7:
+       case ARIZONA_AIF1_FRAME_CTRL_8:
+       case ARIZONA_AIF1_FRAME_CTRL_9:
+       case ARIZONA_AIF1_FRAME_CTRL_10:
+       case ARIZONA_AIF1_FRAME_CTRL_11:
+       case ARIZONA_AIF1_FRAME_CTRL_12:
+       case ARIZONA_AIF1_FRAME_CTRL_13:
+       case ARIZONA_AIF1_FRAME_CTRL_14:
+       case ARIZONA_AIF1_FRAME_CTRL_15:
+       case ARIZONA_AIF1_FRAME_CTRL_16:
+       case ARIZONA_AIF1_FRAME_CTRL_17:
+       case ARIZONA_AIF1_FRAME_CTRL_18:
+       case ARIZONA_AIF1_TX_ENABLES:
+       case ARIZONA_AIF1_RX_ENABLES:
+       case ARIZONA_AIF2_BCLK_CTRL:
+       case ARIZONA_AIF2_TX_PIN_CTRL:
+       case ARIZONA_AIF2_RX_PIN_CTRL:
+       case ARIZONA_AIF2_RATE_CTRL:
+       case ARIZONA_AIF2_FORMAT:
+       case ARIZONA_AIF2_TX_BCLK_RATE:
+       case ARIZONA_AIF2_RX_BCLK_RATE:
+       case ARIZONA_AIF2_FRAME_CTRL_1:
+       case ARIZONA_AIF2_FRAME_CTRL_2:
+       case ARIZONA_AIF2_FRAME_CTRL_3:
+       case ARIZONA_AIF2_FRAME_CTRL_4:
+       case ARIZONA_AIF2_FRAME_CTRL_11:
+       case ARIZONA_AIF2_FRAME_CTRL_12:
+       case ARIZONA_AIF2_TX_ENABLES:
+       case ARIZONA_AIF2_RX_ENABLES:
+       case ARIZONA_SLIMBUS_FRAMER_REF_GEAR:
+       case ARIZONA_SLIMBUS_RATES_1:
+       case ARIZONA_SLIMBUS_RATES_2:
+       case ARIZONA_SLIMBUS_RATES_3:
+       case ARIZONA_SLIMBUS_RATES_4:
+       case ARIZONA_SLIMBUS_RATES_5:
+       case ARIZONA_SLIMBUS_RATES_6:
+       case ARIZONA_SLIMBUS_RATES_7:
+       case ARIZONA_SLIMBUS_RATES_8:
+       case ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE:
+       case ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE:
+       case ARIZONA_SLIMBUS_RX_PORT_STATUS:
+       case ARIZONA_SLIMBUS_TX_PORT_STATUS:
+       case ARIZONA_PWM1MIX_INPUT_1_SOURCE:
+       case ARIZONA_PWM1MIX_INPUT_1_VOLUME:
+       case ARIZONA_PWM1MIX_INPUT_2_SOURCE:
+       case ARIZONA_PWM1MIX_INPUT_2_VOLUME:
+       case ARIZONA_PWM1MIX_INPUT_3_SOURCE:
+       case ARIZONA_PWM1MIX_INPUT_3_VOLUME:
+       case ARIZONA_PWM1MIX_INPUT_4_SOURCE:
+       case ARIZONA_PWM1MIX_INPUT_4_VOLUME:
+       case ARIZONA_PWM2MIX_INPUT_1_SOURCE:
+       case ARIZONA_PWM2MIX_INPUT_1_VOLUME:
+       case ARIZONA_PWM2MIX_INPUT_2_SOURCE:
+       case ARIZONA_PWM2MIX_INPUT_2_VOLUME:
+       case ARIZONA_PWM2MIX_INPUT_3_SOURCE:
+       case ARIZONA_PWM2MIX_INPUT_3_VOLUME:
+       case ARIZONA_PWM2MIX_INPUT_4_SOURCE:
+       case ARIZONA_PWM2MIX_INPUT_4_VOLUME:
+       case ARIZONA_MICMIX_INPUT_1_SOURCE:
+       case ARIZONA_MICMIX_INPUT_1_VOLUME:
+       case ARIZONA_MICMIX_INPUT_2_SOURCE:
+       case ARIZONA_MICMIX_INPUT_2_VOLUME:
+       case ARIZONA_MICMIX_INPUT_3_SOURCE:
+       case ARIZONA_MICMIX_INPUT_3_VOLUME:
+       case ARIZONA_MICMIX_INPUT_4_SOURCE:
+       case ARIZONA_MICMIX_INPUT_4_VOLUME:
+       case ARIZONA_NOISEMIX_INPUT_1_SOURCE:
+       case ARIZONA_NOISEMIX_INPUT_1_VOLUME:
+       case ARIZONA_NOISEMIX_INPUT_2_SOURCE:
+       case ARIZONA_NOISEMIX_INPUT_2_VOLUME:
+       case ARIZONA_NOISEMIX_INPUT_3_SOURCE:
+       case ARIZONA_NOISEMIX_INPUT_3_VOLUME:
+       case ARIZONA_NOISEMIX_INPUT_4_SOURCE:
+       case ARIZONA_NOISEMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT1LMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT1LMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT1LMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT1LMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT1LMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT1LMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT1LMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT1LMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT1RMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT1RMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT1RMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT1RMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT1RMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT1RMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT1RMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT1RMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT3LMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT3LMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT3LMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT3LMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT3LMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT3LMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT3LMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT3LMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT4LMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT4LMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT4LMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT4LMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT4LMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT4LMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT4LMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT4LMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT5LMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT5LMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT5LMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT5LMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT5LMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT5LMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT5LMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT5LMIX_INPUT_4_VOLUME:
+       case ARIZONA_OUT5RMIX_INPUT_1_SOURCE:
+       case ARIZONA_OUT5RMIX_INPUT_1_VOLUME:
+       case ARIZONA_OUT5RMIX_INPUT_2_SOURCE:
+       case ARIZONA_OUT5RMIX_INPUT_2_VOLUME:
+       case ARIZONA_OUT5RMIX_INPUT_3_SOURCE:
+       case ARIZONA_OUT5RMIX_INPUT_3_VOLUME:
+       case ARIZONA_OUT5RMIX_INPUT_4_SOURCE:
+       case ARIZONA_OUT5RMIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME:
+       case ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE:
+       case ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME:
+       case ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE:
+       case ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME:
+       case ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE:
+       case ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME:
+       case ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE:
+       case ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME:
+       case ARIZONA_EQ1MIX_INPUT_1_SOURCE:
+       case ARIZONA_EQ1MIX_INPUT_1_VOLUME:
+       case ARIZONA_EQ1MIX_INPUT_2_SOURCE:
+       case ARIZONA_EQ1MIX_INPUT_2_VOLUME:
+       case ARIZONA_EQ1MIX_INPUT_3_SOURCE:
+       case ARIZONA_EQ1MIX_INPUT_3_VOLUME:
+       case ARIZONA_EQ1MIX_INPUT_4_SOURCE:
+       case ARIZONA_EQ1MIX_INPUT_4_VOLUME:
+       case ARIZONA_EQ2MIX_INPUT_1_SOURCE:
+       case ARIZONA_EQ2MIX_INPUT_1_VOLUME:
+       case ARIZONA_EQ2MIX_INPUT_2_SOURCE:
+       case ARIZONA_EQ2MIX_INPUT_2_VOLUME:
+       case ARIZONA_EQ2MIX_INPUT_3_SOURCE:
+       case ARIZONA_EQ2MIX_INPUT_3_VOLUME:
+       case ARIZONA_EQ2MIX_INPUT_4_SOURCE:
+       case ARIZONA_EQ2MIX_INPUT_4_VOLUME:
+       case ARIZONA_EQ3MIX_INPUT_1_SOURCE:
+       case ARIZONA_EQ3MIX_INPUT_1_VOLUME:
+       case ARIZONA_EQ3MIX_INPUT_2_SOURCE:
+       case ARIZONA_EQ3MIX_INPUT_2_VOLUME:
+       case ARIZONA_EQ3MIX_INPUT_3_SOURCE:
+       case ARIZONA_EQ3MIX_INPUT_3_VOLUME:
+       case ARIZONA_EQ3MIX_INPUT_4_SOURCE:
+       case ARIZONA_EQ3MIX_INPUT_4_VOLUME:
+       case ARIZONA_EQ4MIX_INPUT_1_SOURCE:
+       case ARIZONA_EQ4MIX_INPUT_1_VOLUME:
+       case ARIZONA_EQ4MIX_INPUT_2_SOURCE:
+       case ARIZONA_EQ4MIX_INPUT_2_VOLUME:
+       case ARIZONA_EQ4MIX_INPUT_3_SOURCE:
+       case ARIZONA_EQ4MIX_INPUT_3_VOLUME:
+       case ARIZONA_EQ4MIX_INPUT_4_SOURCE:
+       case ARIZONA_EQ4MIX_INPUT_4_VOLUME:
+       case ARIZONA_DRC1LMIX_INPUT_1_SOURCE:
+       case ARIZONA_DRC1LMIX_INPUT_1_VOLUME:
+       case ARIZONA_DRC1LMIX_INPUT_2_SOURCE:
+       case ARIZONA_DRC1LMIX_INPUT_2_VOLUME:
+       case ARIZONA_DRC1LMIX_INPUT_3_SOURCE:
+       case ARIZONA_DRC1LMIX_INPUT_3_VOLUME:
+       case ARIZONA_DRC1LMIX_INPUT_4_SOURCE:
+       case ARIZONA_DRC1LMIX_INPUT_4_VOLUME:
+       case ARIZONA_DRC1RMIX_INPUT_1_SOURCE:
+       case ARIZONA_DRC1RMIX_INPUT_1_VOLUME:
+       case ARIZONA_DRC1RMIX_INPUT_2_SOURCE:
+       case ARIZONA_DRC1RMIX_INPUT_2_VOLUME:
+       case ARIZONA_DRC1RMIX_INPUT_3_SOURCE:
+       case ARIZONA_DRC1RMIX_INPUT_3_VOLUME:
+       case ARIZONA_DRC1RMIX_INPUT_4_SOURCE:
+       case ARIZONA_DRC1RMIX_INPUT_4_VOLUME:
+       case ARIZONA_HPLP1MIX_INPUT_1_SOURCE:
+       case ARIZONA_HPLP1MIX_INPUT_1_VOLUME:
+       case ARIZONA_HPLP1MIX_INPUT_2_SOURCE:
+       case ARIZONA_HPLP1MIX_INPUT_2_VOLUME:
+       case ARIZONA_HPLP1MIX_INPUT_3_SOURCE:
+       case ARIZONA_HPLP1MIX_INPUT_3_VOLUME:
+       case ARIZONA_HPLP1MIX_INPUT_4_SOURCE:
+       case ARIZONA_HPLP1MIX_INPUT_4_VOLUME:
+       case ARIZONA_HPLP2MIX_INPUT_1_SOURCE:
+       case ARIZONA_HPLP2MIX_INPUT_1_VOLUME:
+       case ARIZONA_HPLP2MIX_INPUT_2_SOURCE:
+       case ARIZONA_HPLP2MIX_INPUT_2_VOLUME:
+       case ARIZONA_HPLP2MIX_INPUT_3_SOURCE:
+       case ARIZONA_HPLP2MIX_INPUT_3_VOLUME:
+       case ARIZONA_HPLP2MIX_INPUT_4_SOURCE:
+       case ARIZONA_HPLP2MIX_INPUT_4_VOLUME:
+       case ARIZONA_HPLP3MIX_INPUT_1_SOURCE:
+       case ARIZONA_HPLP3MIX_INPUT_1_VOLUME:
+       case ARIZONA_HPLP3MIX_INPUT_2_SOURCE:
+       case ARIZONA_HPLP3MIX_INPUT_2_VOLUME:
+       case ARIZONA_HPLP3MIX_INPUT_3_SOURCE:
+       case ARIZONA_HPLP3MIX_INPUT_3_VOLUME:
+       case ARIZONA_HPLP3MIX_INPUT_4_SOURCE:
+       case ARIZONA_HPLP3MIX_INPUT_4_VOLUME:
+       case ARIZONA_HPLP4MIX_INPUT_1_SOURCE:
+       case ARIZONA_HPLP4MIX_INPUT_1_VOLUME:
+       case ARIZONA_HPLP4MIX_INPUT_2_SOURCE:
+       case ARIZONA_HPLP4MIX_INPUT_2_VOLUME:
+       case ARIZONA_HPLP4MIX_INPUT_3_SOURCE:
+       case ARIZONA_HPLP4MIX_INPUT_3_VOLUME:
+       case ARIZONA_HPLP4MIX_INPUT_4_SOURCE:
+       case ARIZONA_HPLP4MIX_INPUT_4_VOLUME:
+       case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case ARIZONA_GPIO1_CTRL:
+       case ARIZONA_GPIO2_CTRL:
+       case ARIZONA_GPIO3_CTRL:
+       case ARIZONA_GPIO4_CTRL:
+       case ARIZONA_GPIO5_CTRL:
+       case ARIZONA_IRQ_CTRL_1:
+       case ARIZONA_GPIO_DEBOUNCE_CONFIG:
+       case ARIZONA_MISC_PAD_CTRL_1:
+       case ARIZONA_MISC_PAD_CTRL_2:
+       case ARIZONA_MISC_PAD_CTRL_3:
+       case ARIZONA_MISC_PAD_CTRL_4:
+       case ARIZONA_MISC_PAD_CTRL_5:
+       case ARIZONA_INTERRUPT_STATUS_1:
+       case ARIZONA_INTERRUPT_STATUS_2:
+       case ARIZONA_INTERRUPT_STATUS_3:
+       case ARIZONA_INTERRUPT_STATUS_4:
+       case ARIZONA_INTERRUPT_STATUS_5:
+       case ARIZONA_INTERRUPT_STATUS_1_MASK:
+       case ARIZONA_INTERRUPT_STATUS_3_MASK:
+       case ARIZONA_INTERRUPT_STATUS_4_MASK:
+       case ARIZONA_INTERRUPT_STATUS_5_MASK:
+       case ARIZONA_INTERRUPT_CONTROL:
+       case ARIZONA_IRQ2_STATUS_1:
+       case ARIZONA_IRQ2_STATUS_3:
+       case ARIZONA_IRQ2_STATUS_4:
+       case ARIZONA_IRQ2_STATUS_5:
+       case ARIZONA_IRQ2_STATUS_1_MASK:
+       case ARIZONA_IRQ2_STATUS_3_MASK:
+       case ARIZONA_IRQ2_STATUS_4_MASK:
+       case ARIZONA_IRQ2_STATUS_5_MASK:
+       case ARIZONA_IRQ2_CONTROL:
+       case ARIZONA_INTERRUPT_RAW_STATUS_3:
+       case ARIZONA_INTERRUPT_RAW_STATUS_4:
+       case ARIZONA_INTERRUPT_RAW_STATUS_5:
+       case ARIZONA_INTERRUPT_RAW_STATUS_6:
+       case ARIZONA_INTERRUPT_RAW_STATUS_7:
+       case ARIZONA_INTERRUPT_RAW_STATUS_8:
+       case ARIZONA_IRQ_PIN_STATUS:
+       case ARIZONA_AOD_WKUP_AND_TRIG:
+       case ARIZONA_AOD_IRQ1:
+       case ARIZONA_AOD_IRQ2:
+       case ARIZONA_AOD_IRQ_MASK_IRQ1:
+       case ARIZONA_AOD_IRQ_MASK_IRQ2:
+       case ARIZONA_AOD_IRQ_RAW_STATUS:
+       case ARIZONA_JACK_DETECT_DEBOUNCE:
+       case ARIZONA_FX_CTRL1:
+       case ARIZONA_FX_CTRL2:
+       case ARIZONA_EQ1_1:
+       case ARIZONA_EQ1_2:
+       case ARIZONA_EQ1_3:
+       case ARIZONA_EQ1_4:
+       case ARIZONA_EQ1_5:
+       case ARIZONA_EQ1_6:
+       case ARIZONA_EQ1_7:
+       case ARIZONA_EQ1_8:
+       case ARIZONA_EQ1_9:
+       case ARIZONA_EQ1_10:
+       case ARIZONA_EQ1_11:
+       case ARIZONA_EQ1_12:
+       case ARIZONA_EQ1_13:
+       case ARIZONA_EQ1_14:
+       case ARIZONA_EQ1_15:
+       case ARIZONA_EQ1_16:
+       case ARIZONA_EQ1_17:
+       case ARIZONA_EQ1_18:
+       case ARIZONA_EQ1_19:
+       case ARIZONA_EQ1_20:
+       case ARIZONA_EQ1_21:
+       case ARIZONA_EQ2_1:
+       case ARIZONA_EQ2_2:
+       case ARIZONA_EQ2_3:
+       case ARIZONA_EQ2_4:
+       case ARIZONA_EQ2_5:
+       case ARIZONA_EQ2_6:
+       case ARIZONA_EQ2_7:
+       case ARIZONA_EQ2_8:
+       case ARIZONA_EQ2_9:
+       case ARIZONA_EQ2_10:
+       case ARIZONA_EQ2_11:
+       case ARIZONA_EQ2_12:
+       case ARIZONA_EQ2_13:
+       case ARIZONA_EQ2_14:
+       case ARIZONA_EQ2_15:
+       case ARIZONA_EQ2_16:
+       case ARIZONA_EQ2_17:
+       case ARIZONA_EQ2_18:
+       case ARIZONA_EQ2_19:
+       case ARIZONA_EQ2_20:
+       case ARIZONA_EQ2_21:
+       case ARIZONA_EQ3_1:
+       case ARIZONA_EQ3_2:
+       case ARIZONA_EQ3_3:
+       case ARIZONA_EQ3_4:
+       case ARIZONA_EQ3_5:
+       case ARIZONA_EQ3_6:
+       case ARIZONA_EQ3_7:
+       case ARIZONA_EQ3_8:
+       case ARIZONA_EQ3_9:
+       case ARIZONA_EQ3_10:
+       case ARIZONA_EQ3_11:
+       case ARIZONA_EQ3_12:
+       case ARIZONA_EQ3_13:
+       case ARIZONA_EQ3_14:
+       case ARIZONA_EQ3_15:
+       case ARIZONA_EQ3_16:
+       case ARIZONA_EQ3_17:
+       case ARIZONA_EQ3_18:
+       case ARIZONA_EQ3_19:
+       case ARIZONA_EQ3_20:
+       case ARIZONA_EQ3_21:
+       case ARIZONA_EQ4_1:
+       case ARIZONA_EQ4_2:
+       case ARIZONA_EQ4_3:
+       case ARIZONA_EQ4_4:
+       case ARIZONA_EQ4_5:
+       case ARIZONA_EQ4_6:
+       case ARIZONA_EQ4_7:
+       case ARIZONA_EQ4_8:
+       case ARIZONA_EQ4_9:
+       case ARIZONA_EQ4_10:
+       case ARIZONA_EQ4_11:
+       case ARIZONA_EQ4_12:
+       case ARIZONA_EQ4_13:
+       case ARIZONA_EQ4_14:
+       case ARIZONA_EQ4_15:
+       case ARIZONA_EQ4_16:
+       case ARIZONA_EQ4_17:
+       case ARIZONA_EQ4_18:
+       case ARIZONA_EQ4_19:
+       case ARIZONA_EQ4_20:
+       case ARIZONA_EQ4_21:
+       case ARIZONA_DRC1_CTRL1:
+       case ARIZONA_DRC1_CTRL2:
+       case ARIZONA_DRC1_CTRL3:
+       case ARIZONA_DRC1_CTRL4:
+       case ARIZONA_DRC1_CTRL5:
+       case ARIZONA_HPLPF1_1:
+       case ARIZONA_HPLPF1_2:
+       case ARIZONA_HPLPF2_1:
+       case ARIZONA_HPLPF2_2:
+       case ARIZONA_HPLPF3_1:
+       case ARIZONA_HPLPF3_2:
+       case ARIZONA_HPLPF4_1:
+       case ARIZONA_HPLPF4_2:
+       case ARIZONA_ISRC_1_CTRL_1:
+       case ARIZONA_ISRC_1_CTRL_2:
+       case ARIZONA_ISRC_1_CTRL_3:
+       case ARIZONA_ISRC_2_CTRL_1:
+       case ARIZONA_ISRC_2_CTRL_2:
+       case ARIZONA_ISRC_2_CTRL_3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool wm8997_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case ARIZONA_SOFTWARE_RESET:
+       case ARIZONA_DEVICE_REVISION:
+       case ARIZONA_HAPTICS_STATUS:
+       case ARIZONA_SAMPLE_RATE_1_STATUS:
+       case ARIZONA_SAMPLE_RATE_2_STATUS:
+       case ARIZONA_SAMPLE_RATE_3_STATUS:
+       case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_HEADPHONE_DETECT_2:
+       case ARIZONA_INPUT_ENABLES_STATUS:
+       case ARIZONA_OUTPUT_STATUS_1:
+       case ARIZONA_RAW_OUTPUT_STATUS_1:
+       case ARIZONA_SLIMBUS_RX_PORT_STATUS:
+       case ARIZONA_SLIMBUS_TX_PORT_STATUS:
+       case ARIZONA_INTERRUPT_STATUS_1:
+       case ARIZONA_INTERRUPT_STATUS_2:
+       case ARIZONA_INTERRUPT_STATUS_3:
+       case ARIZONA_INTERRUPT_STATUS_4:
+       case ARIZONA_INTERRUPT_STATUS_5:
+       case ARIZONA_IRQ2_STATUS_1:
+       case ARIZONA_IRQ2_STATUS_3:
+       case ARIZONA_IRQ2_STATUS_4:
+       case ARIZONA_IRQ2_STATUS_5:
+       case ARIZONA_INTERRUPT_RAW_STATUS_3:
+       case ARIZONA_INTERRUPT_RAW_STATUS_4:
+       case ARIZONA_INTERRUPT_RAW_STATUS_5:
+       case ARIZONA_INTERRUPT_RAW_STATUS_6:
+       case ARIZONA_INTERRUPT_RAW_STATUS_7:
+       case ARIZONA_INTERRUPT_RAW_STATUS_8:
+       case ARIZONA_IRQ_PIN_STATUS:
+       case ARIZONA_AOD_WKUP_AND_TRIG:
+       case ARIZONA_AOD_IRQ1:
+       case ARIZONA_AOD_IRQ2:
+       case ARIZONA_AOD_IRQ_RAW_STATUS:
+       case ARIZONA_FX_CTRL2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+#define WM8997_MAX_REGISTER 0x31ff
+
+const struct regmap_config wm8997_i2c_regmap = {
+       .reg_bits = 32,
+       .val_bits = 16,
+
+       .max_register = WM8997_MAX_REGISTER,
+       .readable_reg = wm8997_readable_register,
+       .volatile_reg = wm8997_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8997_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(wm8997_reg_default),
+};
+EXPORT_SYMBOL_GPL(wm8997_i2c_regmap);
index a57a1b1..a4c53b2 100644 (file)
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/mfd/max8998.h>
 #include <linux/mfd/max8998-private.h>
 
@@ -589,13 +592,13 @@ static struct regulator_desc regulators[] = {
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
        }, {
-               .name           = "EN32KHz AP",
+               .name           = "EN32KHz-AP",
                .id             = MAX8998_EN32KHZ_AP,
                .ops            = &max8998_others_ops,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
        }, {
-               .name           = "EN32KHz CP",
+               .name           = "EN32KHz-CP",
                .id             = MAX8998_EN32KHZ_CP,
                .ops            = &max8998_others_ops,
                .type           = REGULATOR_VOLTAGE,
@@ -621,21 +624,140 @@ static struct regulator_desc regulators[] = {
        }
 };
 
+static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
+                       struct max8998_platform_data *pdata,
+                       struct device_node *pmic_np)
+{
+       int gpio;
+
+       gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 0);
+       if (!gpio_is_valid(gpio)) {
+               dev_err(iodev->dev, "invalid buck1 gpio[0]: %d\n", gpio);
+               return -EINVAL;
+       }
+       pdata->buck1_set1 = gpio;
+
+       gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 1);
+       if (!gpio_is_valid(gpio)) {
+               dev_err(iodev->dev, "invalid buck1 gpio[1]: %d\n", gpio);
+               return -EINVAL;
+       }
+       pdata->buck1_set2 = gpio;
+
+       gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck2-dvs-gpio", 0);
+       if (!gpio_is_valid(gpio)) {
+               dev_err(iodev->dev, "invalid buck 2 gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+       pdata->buck2_set3 = gpio;
+
+       return 0;
+}
+
+static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
+                                       struct max8998_platform_data *pdata)
+{
+       struct device_node *pmic_np = iodev->dev->of_node;
+       struct device_node *regulators_np, *reg_np;
+       struct max8998_regulator_data *rdata;
+       unsigned int i;
+       int ret;
+
+       regulators_np = of_get_child_by_name(pmic_np, "regulators");
+       if (!regulators_np) {
+               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               return -EINVAL;
+       }
+
+       /* count the number of regulators to be supported in pmic */
+       pdata->num_regulators = of_get_child_count(regulators_np);
+
+       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+                               pdata->num_regulators, GFP_KERNEL);
+       if (!rdata)
+               return -ENOMEM;
+
+       pdata->regulators = rdata;
+       for (i = 0; i < ARRAY_SIZE(regulators); ++i) {
+               reg_np = of_get_child_by_name(regulators_np,
+                                                       regulators[i].name);
+               if (!reg_np)
+                       continue;
+
+               rdata->id = regulators[i].id;
+               rdata->initdata = of_get_regulator_init_data(
+                                                       iodev->dev, reg_np);
+               rdata->reg_node = reg_np;
+               ++rdata;
+       }
+       pdata->num_regulators = rdata - pdata->regulators;
+
+       ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+       if (ret)
+               return -EINVAL;
+
+       if (of_find_property(pmic_np, "max8998,pmic-buck-voltage-lock", NULL))
+               pdata->buck_voltage_lock = true;
+
+       ret = of_property_read_u32(pmic_np,
+                                       "max8998,pmic-buck1-default-dvs-idx",
+                                       &pdata->buck1_default_idx);
+       if (!ret && pdata->buck1_default_idx >= 4) {
+               pdata->buck1_default_idx = 0;
+               dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n");
+       }
+
+       ret = of_property_read_u32(pmic_np,
+                                       "max8998,pmic-buck2-default-dvs-idx",
+                                       &pdata->buck2_default_idx);
+       if (!ret && pdata->buck2_default_idx >= 2) {
+               pdata->buck2_default_idx = 0;
+               dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n");
+       }
+
+       ret = of_property_read_u32_array(pmic_np,
+                                       "max8998,pmic-buck1-dvs-voltage",
+                                       pdata->buck1_voltage,
+                                       ARRAY_SIZE(pdata->buck1_voltage));
+       if (ret) {
+               dev_err(iodev->dev, "buck1 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       ret = of_property_read_u32_array(pmic_np,
+                                       "max8998,pmic-buck2-dvs-voltage",
+                                       pdata->buck2_voltage,
+                                       ARRAY_SIZE(pdata->buck2_voltage));
+       if (ret) {
+               dev_err(iodev->dev, "buck2 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int max8998_pmic_probe(struct platform_device *pdev)
 {
        struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct max8998_platform_data *pdata = iodev->pdata;
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct max8998_data *max8998;
        struct i2c_client *i2c;
        int i, ret, size;
+       unsigned int v;
 
        if (!pdata) {
                dev_err(pdev->dev.parent, "No platform init data supplied\n");
                return -ENODEV;
        }
 
+       if (IS_ENABLED(CONFIG_OF) && iodev->dev->of_node) {
+               ret = max8998_pmic_dt_parse_pdata(iodev, pdata);
+               if (ret)
+                       return ret;
+       }
+
        max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data),
                               GFP_KERNEL);
        if (!max8998)
@@ -688,53 +810,21 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2");
                gpio_direction_output(pdata->buck1_set2,
                                      (max8998->buck1_idx >> 1) & 0x1);
-               /* Set predefined value for BUCK1 register 1 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck1_voltage1)
-                       i++;
-               max8998->buck1_vol[0] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
-               if (ret)
-                       goto err_out;
-
-               /* Set predefined value for BUCK1 register 2 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck1_voltage2)
-                       i++;
-
-               max8998->buck1_vol[1] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
-               if (ret)
-                       goto err_out;
-
-               /* Set predefined value for BUCK1 register 3 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck1_voltage3)
-                       i++;
-
-               max8998->buck1_vol[2] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
-               if (ret)
-                       goto err_out;
-
-               /* Set predefined value for BUCK1 register 4 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck1_voltage4)
-                       i++;
-
-               max8998->buck1_vol[3] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
-               if (ret)
-                       goto err_out;
 
+               /* Set predefined values for BUCK1 registers */
+               for (v = 0; v < ARRAY_SIZE(pdata->buck1_voltage); ++v) {
+                       i = 0;
+                       while (buck12_voltage_map_desc.min +
+                              buck12_voltage_map_desc.step*i
+                              < pdata->buck1_voltage[v])
+                               i++;
+
+                       max8998->buck1_vol[v] = i;
+                       ret = max8998_write_reg(i2c,
+                                       MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
+                       if (ret)
+                               goto err_out;
+               }
        }
 
        if (gpio_is_valid(pdata->buck2_set3)) {
@@ -750,27 +840,20 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                gpio_direction_output(pdata->buck2_set3,
                                      max8998->buck2_idx & 0x1);
 
-               /* BUCK2 register 1 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck2_voltage1)
-                       i++;
-               max8998->buck2_vol[0] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
-               if (ret)
-                       goto err_out;
-
-               /* BUCK2 register 2 */
-               i = 0;
-               while (buck12_voltage_map_desc.min +
-                      buck12_voltage_map_desc.step*i
-                      < pdata->buck2_voltage2)
-                       i++;
-               max8998->buck2_vol[1] = i;
-               ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
-               if (ret)
-                       goto err_out;
+               /* Set predefined values for BUCK2 registers */
+               for (v = 0; v < ARRAY_SIZE(pdata->buck2_voltage); ++v) {
+                       i = 0;
+                       while (buck12_voltage_map_desc.min +
+                              buck12_voltage_map_desc.step*i
+                              < pdata->buck2_voltage[v])
+                               i++;
+
+                       max8998->buck2_vol[v] = i;
+                       ret = max8998_write_reg(i2c,
+                                       MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
+                       if (ret)
+                               goto err_out;
+               }
        }
 
        for (i = 0; i < pdata->num_regulators; i++) {
@@ -788,13 +871,15 @@ static int max8998_pmic_probe(struct platform_device *pdev)
                }
 
                config.dev = max8998->dev;
+               config.of_node = pdata->regulators[i].reg_node;
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = max8998;
 
                rdev[i] = regulator_register(&regulators[index], &config);
                if (IS_ERR(rdev[i])) {
                        ret = PTR_ERR(rdev[i]);
-                       dev_err(max8998->dev, "regulator init failed\n");
+                       dev_err(max8998->dev, "regulator %s init failed (%d)\n",
+                                               regulators[index].name, ret);
                        rdev[i] = NULL;
                        goto err;
                }
index 3ae44ac..d0c8785 100644 (file)
@@ -838,6 +838,9 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                                continue;
                        ramp_delay_support = true;
                        break;
+               case PALMAS_REG_SMPS10:
+                       if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST))
+                               continue;
                }
 
                if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8))
@@ -1051,6 +1054,7 @@ static struct of_device_id of_palmas_match_tbl[] = {
        { .compatible = "ti,tps65913-pmic", },
        { .compatible = "ti,tps65914-pmic", },
        { .compatible = "ti,tps80036-pmic", },
+       { .compatible = "ti,tps659038-pmic", },
        { /* end */ }
 };
 
index fb6e67d..93bc4f4 100644 (file)
@@ -109,7 +109,7 @@ struct twlreg_info {
 #define SMPS_OFFSET_EN         BIT(0)
 #define SMPS_EXTENDED_EN       BIT(1)
 
-/* twl6025 SMPS EPROM values */
+/* twl6032 SMPS EPROM values */
 #define TWL6030_SMPS_OFFSET            0xB0
 #define TWL6030_SMPS_MULT              0xB3
 #define SMPS_MULTOFFSET_SMPS4  BIT(0)
@@ -173,7 +173,7 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        int                     grp = 0, val;
 
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) {
+       if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) {
                grp = twlreg_grp(rdev);
                if (grp < 0)
                        return grp;
@@ -211,7 +211,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
        int                     grp = 0;
        int                     ret;
 
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
+       if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
                grp = twlreg_grp(rdev);
        if (grp < 0)
                return grp;
@@ -245,7 +245,7 @@ static int twl6030reg_disable(struct regulator_dev *rdev)
        int                     grp = 0;
        int                     ret;
 
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
+       if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
                grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
 
        /* For 6030, set the off state for all grps enabled */
@@ -339,7 +339,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
        int grp = 0;
        int val;
 
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
+       if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
                grp = twlreg_grp(rdev);
 
        if (grp < 0)
@@ -899,14 +899,14 @@ static const struct twlreg_info TWL6030_INFO_##label = { \
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
-static const struct twlreg_info TWL6025_INFO_##label = { \
+#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
+static const struct twlreg_info TWL6032_INFO_##label = { \
        .base = offset, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
        .desc = { \
                .name = #label, \
-               .id = TWL6025_REG_##label, \
+               .id = TWL6032_REG_##label, \
                .n_voltages = 32, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
@@ -933,14 +933,14 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_SMPS(label, offset) \
+#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
 static const struct twlreg_info TWLSMPS_INFO_##label = { \
        .base = offset, \
        .min_mV = 600, \
        .max_mV = 2100, \
        .desc = { \
                .name = #label, \
-               .id = TWL6025_REG_##label, \
+               .id = TWL6032_REG_##label, \
                .n_voltages = 63, \
                .ops = &twlsmps_ops, \
                .type = REGULATOR_VOLTAGE, \
@@ -981,15 +981,15 @@ TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300);
 TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300);
 TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300);
 /* 6025 are renamed compared to 6030 versions */
-TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
-TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
+TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
 TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
 TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
 TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
@@ -1001,9 +1001,9 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
 TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
 TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
 TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
-TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34);
-TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10);
-TWL6025_ADJUSTABLE_SMPS(VIO, 0x16);
+TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34);
+TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10);
+TWL6032_ADJUSTABLE_SMPS(VIO, 0x16);
 
 static u8 twl_get_smps_offset(void)
 {
@@ -1031,7 +1031,7 @@ static u8 twl_get_smps_mult(void)
 
 #define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label)
 #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
-#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
+#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
 #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
 #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
 
@@ -1060,15 +1060,15 @@ static const struct of_device_id twl_of_match[] = {
        TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
        TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
        TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
-       TWL6025_OF_MATCH("ti,twl6025-ldo2", LDO2),
-       TWL6025_OF_MATCH("ti,twl6025-ldo4", LDO4),
-       TWL6025_OF_MATCH("ti,twl6025-ldo3", LDO3),
-       TWL6025_OF_MATCH("ti,twl6025-ldo5", LDO5),
-       TWL6025_OF_MATCH("ti,twl6025-ldo1", LDO1),
-       TWL6025_OF_MATCH("ti,twl6025-ldo7", LDO7),
-       TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6),
-       TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN),
-       TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB),
+       TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2),
+       TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4),
+       TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3),
+       TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5),
+       TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1),
+       TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7),
+       TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6),
+       TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN),
+       TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB),
        TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1),
        TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),
        TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
@@ -1080,9 +1080,9 @@ static const struct of_device_id twl_of_match[] = {
        TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
        TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
        TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
-       TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
-       TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
-       TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
+       TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3),
+       TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4),
+       TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
        {},
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
@@ -1163,19 +1163,19 @@ static int twlreg_probe(struct platform_device *pdev)
        }
 
        switch (id) {
-       case TWL6025_REG_SMPS3:
+       case TWL6032_REG_SMPS3:
                if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
                        info->flags |= SMPS_EXTENDED_EN;
                if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
                        info->flags |= SMPS_OFFSET_EN;
                break;
-       case TWL6025_REG_SMPS4:
+       case TWL6032_REG_SMPS4:
                if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
                        info->flags |= SMPS_EXTENDED_EN;
                if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
                        info->flags |= SMPS_OFFSET_EN;
                break;
-       case TWL6025_REG_VIO:
+       case TWL6032_REG_VIO:
                if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
                        info->flags |= SMPS_EXTENDED_EN;
                if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
index 5388336..f098ad8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/bcd.h>
+#include <linux/irqdomain.h>
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/max8998.h>
@@ -252,7 +253,7 @@ static const struct rtc_class_ops max8998_rtc_ops = {
 static int max8998_rtc_probe(struct platform_device *pdev)
 {
        struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent);
-       struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev);
+       struct max8998_platform_data *pdata = max8998->pdata;
        struct max8998_rtc_info *info;
        int ret;
 
@@ -264,7 +265,6 @@ static int max8998_rtc_probe(struct platform_device *pdev)
        info->dev = &pdev->dev;
        info->max8998 = max8998;
        info->rtc = max8998->rtc;
-       info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0;
 
        platform_set_drvdata(pdev, info);
 
@@ -277,6 +277,15 @@ static int max8998_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       if (!max8998->irq_domain)
+               goto no_irq;
+
+       info->irq = irq_create_mapping(max8998->irq_domain, MAX8998_IRQ_ALARM0);
+       if (!info->irq) {
+               dev_warn(&pdev->dev, "Failed to map alarm IRQ\n");
+               goto no_irq;
+       }
+
        ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
                                max8998_rtc_alarm_irq, 0, "rtc-alarm0", info);
 
@@ -284,6 +293,7 @@ static int max8998_rtc_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
                        info->irq, ret);
 
+no_irq:
        dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
        if (pdata && pdata->rtc_delay) {
                info->lp3974_bug_workaround = true;
diff --git a/drivers/ssbi/Kconfig b/drivers/ssbi/Kconfig
deleted file mode 100644 (file)
index 1ae4040..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# SSBI bus support
-#
-
-menu "Qualcomm MSM SSBI bus support"
-
-config SSBI
-       tristate "Qualcomm Single-wire Serial Bus Interface (SSBI)"
-       help
-         If you say yes to this option, support will be included for the
-         built-in SSBI interface on Qualcomm MSM family processors.
-
-         This is required for communicating with Qualcomm PMICs and
-         other devices that have the SSBI interface.
-
-endmenu
diff --git a/drivers/ssbi/Makefile b/drivers/ssbi/Makefile
deleted file mode 100644 (file)
index 38fb70c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_SSBI) += ssbi.o
index 9de7ada..1753bd3 100644 (file)
@@ -347,7 +347,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
        if (np) {
                twl->regulator = "usb";
        } else if (pdata) {
-               if (pdata->features & TWL6025_SUBCLASS)
+               if (pdata->features & TWL6032_SUBCLASS)
                        twl->regulator = "ldousb";
                else
                        twl->regulator = "vusb";
index e89fc31..7460d34 100644 (file)
@@ -687,6 +687,17 @@ config HP_WATCHDOG
          To compile this driver as a module, choose M here: the module will be
          called hpwdt.
 
+config KEMPLD_WDT
+       tristate "Kontron COM Watchdog Timer"
+       depends on MFD_KEMPLD
+       select WATCHDOG_CORE
+       help
+         Support for the PLD watchdog on some Kontron ETX and COMexpress
+         (ETXexpress) modules
+
+         This driver can also be built as a module. If so, the module will be
+         called kempld_wdt.
+
 config HPWDT_NMI_DECODING
        bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
        depends on HP_WATCHDOG
index a300b94..ec26899 100644 (file)
@@ -90,6 +90,7 @@ endif
 obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o
 obj-$(CONFIG_IT87_WDT) += it87_wdt.o
 obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
+obj-$(CONFIG_KEMPLD_WDT) += kempld_wdt.o
 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
 obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c
new file mode 100644 (file)
index 0000000..491419e
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Kontron PLD watchdog driver
+ *
+ * Copyright (c) 2010-2013 Kontron Europe GmbH
+ * Author: Michael Brunner <michael.brunner@kontron.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ * Note: From the PLD watchdog point of view timeout and pretimeout are
+ *       defined differently than in the kernel.
+ *       First the pretimeout stage runs out before the timeout stage gets
+ *       active.
+ *
+ * Kernel/API:                     P-----| pretimeout
+ *               |-----------------------T timeout
+ * Watchdog:     |-----------------P       pretimeout_stage
+ *                                 |-----T timeout_stage
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/kempld.h>
+
+#define KEMPLD_WDT_STAGE_TIMEOUT(x)    (0x1b + (x) * 4)
+#define KEMPLD_WDT_STAGE_CFG(x)                (0x18 + (x))
+#define STAGE_CFG_GET_PRESCALER(x)     (((x) & 0x30) >> 4)
+#define STAGE_CFG_SET_PRESCALER(x)     (((x) & 0x30) << 4)
+#define STAGE_CFG_PRESCALER_MASK       0x30
+#define STAGE_CFG_ACTION_MASK          0x7
+#define STAGE_CFG_ASSERT               (1 << 3)
+
+#define KEMPLD_WDT_MAX_STAGES          2
+#define KEMPLD_WDT_KICK                        0x16
+#define KEMPLD_WDT_CFG                 0x17
+#define KEMPLD_WDT_CFG_ENABLE          0x10
+#define KEMPLD_WDT_CFG_ENABLE_LOCK     0x8
+#define KEMPLD_WDT_CFG_GLOBAL_LOCK     0x80
+
+enum {
+       ACTION_NONE = 0,
+       ACTION_RESET,
+       ACTION_NMI,
+       ACTION_SMI,
+       ACTION_SCI,
+       ACTION_DELAY,
+};
+
+enum {
+       STAGE_TIMEOUT = 0,
+       STAGE_PRETIMEOUT,
+};
+
+enum {
+       PRESCALER_21 = 0,
+       PRESCALER_17,
+       PRESCALER_12,
+};
+
+const u32 kempld_prescaler[] = {
+       [PRESCALER_21] = (1 << 21) - 1,
+       [PRESCALER_17] = (1 << 17) - 1,
+       [PRESCALER_12] = (1 << 12) - 1,
+       0,
+};
+
+struct kempld_wdt_stage {
+       unsigned int    id;
+       u32             mask;
+};
+
+struct kempld_wdt_data {
+       struct kempld_device_data       *pld;
+       struct watchdog_device          wdd;
+       unsigned int                    pretimeout;
+       struct kempld_wdt_stage         stage[KEMPLD_WDT_MAX_STAGES];
+#ifdef CONFIG_PM
+       u8                              pm_status_store;
+#endif
+};
+
+#define DEFAULT_TIMEOUT                30 /* seconds */
+#define DEFAULT_PRETIMEOUT     0
+
+static unsigned int timeout = DEFAULT_TIMEOUT;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+       "Watchdog timeout in seconds. (>=0, default="
+       __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+
+static unsigned int pretimeout = DEFAULT_PRETIMEOUT;
+module_param(pretimeout, uint, 0);
+MODULE_PARM_DESC(pretimeout,
+       "Watchdog pretimeout in seconds. (>=0, default="
+       __MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+       "Watchdog cannot be stopped once started (default="
+       __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int kempld_wdt_set_stage_action(struct kempld_wdt_data *wdt_data,
+                                       struct kempld_wdt_stage *stage,
+                                       u8 action)
+{
+       struct kempld_device_data *pld = wdt_data->pld;
+       u8 stage_cfg;
+
+       if (!stage || !stage->mask)
+               return -EINVAL;
+
+       kempld_get_mutex(pld);
+       stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
+       stage_cfg &= ~STAGE_CFG_ACTION_MASK;
+       stage_cfg |= (action & STAGE_CFG_ACTION_MASK);
+
+       if (action == ACTION_RESET)
+               stage_cfg |= STAGE_CFG_ASSERT;
+       else
+               stage_cfg &= ~STAGE_CFG_ASSERT;
+
+       kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
+                                       struct kempld_wdt_stage *stage,
+                                       unsigned int timeout)
+{
+       struct kempld_device_data *pld = wdt_data->pld;
+       u32 prescaler = kempld_prescaler[PRESCALER_21];
+       u64 stage_timeout64;
+       u32 stage_timeout;
+       u32 remainder;
+       u8 stage_cfg;
+
+       if (!stage)
+               return -EINVAL;
+
+       stage_timeout64 = (u64)timeout * pld->pld_clock;
+       remainder = do_div(stage_timeout64, prescaler);
+       if (remainder)
+               stage_timeout64++;
+
+       if (stage_timeout64 > stage->mask)
+               return -EINVAL;
+
+       stage_timeout = stage_timeout64 & stage->mask;
+
+       kempld_get_mutex(pld);
+       stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
+       stage_cfg &= ~STAGE_CFG_PRESCALER_MASK;
+       stage_cfg |= STAGE_CFG_SET_PRESCALER(prescaler);
+       kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
+       kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id),
+                       stage_timeout);
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+/*
+ * kempld_get_mutex must be called prior to calling this function.
+ */
+static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data,
+                                               struct kempld_wdt_stage *stage)
+{
+       struct kempld_device_data *pld = wdt_data->pld;
+       unsigned int timeout;
+       u64 stage_timeout;
+       u32 prescaler;
+       u32 remainder;
+       u8 stage_cfg;
+
+       if (!stage->mask)
+               return 0;
+
+       stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
+       stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id));
+       prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)];
+
+       stage_timeout = (stage_timeout & stage->mask) * prescaler;
+       remainder = do_div(stage_timeout, pld->pld_clock);
+       if (remainder)
+               stage_timeout++;
+
+       timeout = stage_timeout;
+       WARN_ON_ONCE(timeout != stage_timeout);
+
+       return timeout;
+}
+
+static int kempld_wdt_set_timeout(struct watchdog_device *wdd,
+                                       unsigned int timeout)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_wdt_stage *pretimeout_stage;
+       struct kempld_wdt_stage *timeout_stage;
+       int ret;
+
+       timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
+       pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
+
+       if (pretimeout_stage->mask && wdt_data->pretimeout > 0)
+               timeout = wdt_data->pretimeout;
+
+       ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage,
+                                               ACTION_RESET);
+       if (ret)
+               return ret;
+       ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage,
+                                               timeout);
+       if (ret)
+               return ret;
+
+       wdd->timeout = timeout;
+       return 0;
+}
+
+static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd,
+                                       unsigned int pretimeout)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_wdt_stage *pretimeout_stage;
+       u8 action = ACTION_NONE;
+       int ret;
+
+       pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
+
+       if (!pretimeout_stage->mask)
+               return -ENXIO;
+
+       if (pretimeout > wdd->timeout)
+               return -EINVAL;
+
+       if (pretimeout > 0)
+               action = ACTION_NMI;
+
+       ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage,
+                                               action);
+       if (ret)
+               return ret;
+       ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage,
+                                               wdd->timeout - pretimeout);
+       if (ret)
+               return ret;
+
+       wdt_data->pretimeout = pretimeout;
+       return 0;
+}
+
+static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data)
+{
+       struct kempld_device_data *pld = wdt_data->pld;
+       struct kempld_wdt_stage *pretimeout_stage;
+       struct kempld_wdt_stage *timeout_stage;
+       unsigned int pretimeout, timeout;
+
+       pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
+       timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
+
+       kempld_get_mutex(pld);
+       pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage);
+       timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage);
+       kempld_release_mutex(pld);
+
+       if (pretimeout)
+               wdt_data->pretimeout = timeout;
+       else
+               wdt_data->pretimeout = 0;
+
+       wdt_data->wdd.timeout = pretimeout + timeout;
+}
+
+static int kempld_wdt_start(struct watchdog_device *wdd)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_device_data *pld = wdt_data->pld;
+       u8 status;
+       int ret;
+
+       ret = kempld_wdt_set_timeout(wdd, wdd->timeout);
+       if (ret)
+               return ret;
+
+       kempld_get_mutex(pld);
+       status = kempld_read8(pld, KEMPLD_WDT_CFG);
+       status |= KEMPLD_WDT_CFG_ENABLE;
+       kempld_write8(pld, KEMPLD_WDT_CFG, status);
+       status = kempld_read8(pld, KEMPLD_WDT_CFG);
+       kempld_release_mutex(pld);
+
+       /* Check if the watchdog was enabled */
+       if (!(status & KEMPLD_WDT_CFG_ENABLE))
+               return -EACCES;
+
+       return 0;
+}
+
+static int kempld_wdt_stop(struct watchdog_device *wdd)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_device_data *pld = wdt_data->pld;
+       u8 status;
+
+       kempld_get_mutex(pld);
+       status = kempld_read8(pld, KEMPLD_WDT_CFG);
+       status &= ~KEMPLD_WDT_CFG_ENABLE;
+       kempld_write8(pld, KEMPLD_WDT_CFG, status);
+       status = kempld_read8(pld, KEMPLD_WDT_CFG);
+       kempld_release_mutex(pld);
+
+       /* Check if the watchdog was disabled */
+       if (status & KEMPLD_WDT_CFG_ENABLE)
+               return -EACCES;
+
+       return 0;
+}
+
+static int kempld_wdt_keepalive(struct watchdog_device *wdd)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_device_data *pld = wdt_data->pld;
+
+       kempld_get_mutex(pld);
+       kempld_write8(pld, KEMPLD_WDT_KICK, 'K');
+       kempld_release_mutex(pld);
+
+       return 0;
+}
+
+static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       void __user *argp = (void __user *)arg;
+       int ret = -ENOIOCTLCMD;
+       int __user *p = argp;
+       int new_value;
+
+       switch (cmd) {
+       case WDIOC_SETPRETIMEOUT:
+               if (get_user(new_value, p))
+                       return -EFAULT;
+               ret = kempld_wdt_set_pretimeout(wdd, new_value);
+               if (ret)
+                       return ret;
+               ret = kempld_wdt_keepalive(wdd);
+               break;
+       case WDIOC_GETPRETIMEOUT:
+               ret = put_user(wdt_data->pretimeout, (int *)arg);
+               break;
+       }
+
+       return ret;
+}
+
+static int kempld_wdt_probe_stages(struct watchdog_device *wdd)
+{
+       struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
+       struct kempld_device_data *pld = wdt_data->pld;
+       struct kempld_wdt_stage *pretimeout_stage;
+       struct kempld_wdt_stage *timeout_stage;
+       u8 index, data, data_orig;
+       u32 mask;
+       int i, j;
+
+       pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
+       timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
+
+       pretimeout_stage->mask = 0;
+       timeout_stage->mask = 0;
+
+       for (i = 0; i < 3; i++) {
+               index = KEMPLD_WDT_STAGE_TIMEOUT(i);
+               mask = 0;
+
+               kempld_get_mutex(pld);
+               /* Probe each byte individually. */
+               for (j = 0; j < 4; j++) {
+                       data_orig = kempld_read8(pld, index + j);
+                       kempld_write8(pld, index + j, 0x00);
+                       data = kempld_read8(pld, index + j);
+                       /* A failed write means this byte is reserved */
+                       if (data != 0x00)
+                               break;
+                       kempld_write8(pld, index + j, data_orig);
+                       mask |= 0xff << (j * 8);
+               }
+               kempld_release_mutex(pld);
+
+               /* Assign available stages to timeout and pretimeout */
+               if (!timeout_stage->mask) {
+                       timeout_stage->mask = mask;
+                       timeout_stage->id = i;
+               } else {
+                       if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) {
+                               pretimeout_stage->mask = timeout_stage->mask;
+                               timeout_stage->mask = mask;
+                               pretimeout_stage->id = timeout_stage->id;
+                               timeout_stage->id = i;
+                       }
+                       break;
+               }
+       }
+
+       if (!timeout_stage->mask)
+               return -ENODEV;
+
+       return 0;
+}
+
+static struct watchdog_info kempld_wdt_info = {
+       .identity       = "KEMPLD Watchdog",
+       .options        = WDIOF_SETTIMEOUT |
+                       WDIOF_KEEPALIVEPING |
+                       WDIOF_MAGICCLOSE |
+                       WDIOF_PRETIMEOUT
+};
+
+static struct watchdog_ops kempld_wdt_ops = {
+       .owner          = THIS_MODULE,
+       .start          = kempld_wdt_start,
+       .stop           = kempld_wdt_stop,
+       .ping           = kempld_wdt_keepalive,
+       .set_timeout    = kempld_wdt_set_timeout,
+       .ioctl          = kempld_wdt_ioctl,
+};
+
+static int kempld_wdt_probe(struct platform_device *pdev)
+{
+       struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent);
+       struct kempld_wdt_data *wdt_data;
+       struct device *dev = &pdev->dev;
+       struct watchdog_device *wdd;
+       u8 status;
+       int ret = 0;
+
+       wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL);
+       if (!wdt_data)
+               return -ENOMEM;
+
+       wdt_data->pld = pld;
+       wdd = &wdt_data->wdd;
+       wdd->parent = dev;
+
+       kempld_get_mutex(pld);
+       status = kempld_read8(pld, KEMPLD_WDT_CFG);
+       kempld_release_mutex(pld);
+
+       /* Enable nowayout if watchdog is already locked */
+       if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK |
+                       KEMPLD_WDT_CFG_GLOBAL_LOCK)) {
+               if (!nowayout)
+                       dev_warn(dev,
+                               "Forcing nowayout - watchdog lock enabled!\n");
+               nowayout = true;
+       }
+
+       wdd->info = &kempld_wdt_info;
+       wdd->ops = &kempld_wdt_ops;
+
+       watchdog_set_drvdata(wdd, wdt_data);
+       watchdog_set_nowayout(wdd, nowayout);
+
+       ret = kempld_wdt_probe_stages(wdd);
+       if (ret)
+               return ret;
+
+       kempld_wdt_set_timeout(wdd, timeout);
+       kempld_wdt_set_pretimeout(wdd, pretimeout);
+
+       /* Check if watchdog is already enabled */
+       if (status & KEMPLD_WDT_CFG_ENABLE) {
+               /* Get current watchdog settings */
+               kempld_wdt_update_timeouts(wdt_data);
+               dev_info(dev, "Watchdog was already enabled\n");
+       }
+
+       platform_set_drvdata(pdev, wdt_data);
+       ret = watchdog_register_device(wdd);
+       if (ret)
+               return ret;
+
+       dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout);
+
+       return 0;
+}
+
+static void kempld_wdt_shutdown(struct platform_device *pdev)
+{
+       struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
+
+       kempld_wdt_stop(&wdt_data->wdd);
+}
+
+static int kempld_wdt_remove(struct platform_device *pdev)
+{
+       struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
+       struct watchdog_device *wdd = &wdt_data->wdd;
+       int ret = 0;
+
+       if (!nowayout)
+               ret = kempld_wdt_stop(wdd);
+       watchdog_unregister_device(wdd);
+
+       return ret;
+}
+
+#ifdef CONFIG_PM
+/* Disable watchdog if it is active during suspend */
+static int kempld_wdt_suspend(struct platform_device *pdev,
+                               pm_message_t message)
+{
+       struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
+       struct kempld_device_data *pld = wdt_data->pld;
+       struct watchdog_device *wdd = &wdt_data->wdd;
+
+       kempld_get_mutex(pld);
+       wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG);
+       kempld_release_mutex(pld);
+
+       kempld_wdt_update_timeouts(wdt_data);
+
+       if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
+               return kempld_wdt_stop(wdd);
+
+       return 0;
+}
+
+/* Enable watchdog and configure it if necessary */
+static int kempld_wdt_resume(struct platform_device *pdev)
+{
+       struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
+       struct watchdog_device *wdd = &wdt_data->wdd;
+
+       /*
+        * If watchdog was stopped before suspend be sure it gets disabled
+        * again, for the case BIOS has enabled it during resume
+        */
+       if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
+               return kempld_wdt_start(wdd);
+       else
+               return kempld_wdt_stop(wdd);
+}
+#else
+#define kempld_wdt_suspend     NULL
+#define kempld_wdt_resume      NULL
+#endif
+
+static struct platform_driver kempld_wdt_driver = {
+       .driver         = {
+               .name   = "kempld-wdt",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = kempld_wdt_probe,
+       .remove         = kempld_wdt_remove,
+       .shutdown       = kempld_wdt_shutdown,
+       .suspend        = kempld_wdt_suspend,
+       .resume         = kempld_wdt_resume,
+};
+
+module_platform_driver(kempld_wdt_driver);
+
+MODULE_DESCRIPTION("KEM PLD Watchdog Driver");
+MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 488debb..81cbbdb 100644 (file)
@@ -658,7 +658,6 @@ struct twl4030_power_data {
        bool use_poweroff;      /* Board is wired for TWL poweroff */
 };
 
-extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
 extern int twl4030_remove_script(u8 flags);
 extern void twl4030_power_off(void);
 
@@ -726,7 +725,7 @@ struct twl4030_platform_data {
        struct regulator_init_data              *clk32kg;
        struct regulator_init_data              *v1v8;
        struct regulator_init_data              *v2v1;
-       /* TWL6025 LDO regulators */
+       /* TWL6032 LDO regulators */
        struct regulator_init_data              *ldo1;
        struct regulator_init_data              *ldo2;
        struct regulator_init_data              *ldo3;
@@ -736,7 +735,7 @@ struct twl4030_platform_data {
        struct regulator_init_data              *ldo7;
        struct regulator_init_data              *ldoln;
        struct regulator_init_data              *ldousb;
-       /* TWL6025 DCDC regulators */
+       /* TWL6032 DCDC regulators */
        struct regulator_init_data              *smps3;
        struct regulator_init_data              *smps4;
        struct regulator_init_data              *vio6025;
@@ -753,7 +752,7 @@ struct twl_regulator_driver_data {
 #define TPS_SUBSET             BIT(1)  /* tps659[23]0 have fewer LDOs */
 #define TWL5031                        BIT(2)  /* twl5031 has different registers */
 #define TWL6030_CLASS          BIT(3)  /* TWL6030 class */
-#define TWL6025_SUBCLASS       BIT(4)  /* TWL6025 has changed registers */
+#define TWL6032_SUBCLASS       BIT(4)  /* TWL6032 has changed registers */
 #define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible
                                          * but not officially supported.
                                          * This flag is necessary to
@@ -840,20 +839,20 @@ static inline int twl4030charger_usb_en(int enable) { return 0; }
 #define TWL6030_REG_CLK32KG    48
 
 /* LDOs on 6025 have different names */
-#define TWL6025_REG_LDO2       49
-#define TWL6025_REG_LDO4       50
-#define TWL6025_REG_LDO3       51
-#define TWL6025_REG_LDO5       52
-#define TWL6025_REG_LDO1       53
-#define TWL6025_REG_LDO7       54
-#define TWL6025_REG_LDO6       55
-#define TWL6025_REG_LDOLN      56
-#define TWL6025_REG_LDOUSB     57
+#define TWL6032_REG_LDO2       49
+#define TWL6032_REG_LDO4       50
+#define TWL6032_REG_LDO3       51
+#define TWL6032_REG_LDO5       52
+#define TWL6032_REG_LDO1       53
+#define TWL6032_REG_LDO7       54
+#define TWL6032_REG_LDO6       55
+#define TWL6032_REG_LDOLN      56
+#define TWL6032_REG_LDOUSB     57
 
 /* 6025 DCDC supplies */
-#define TWL6025_REG_SMPS3      58
-#define TWL6025_REG_SMPS4      59
-#define TWL6025_REG_VIO                60
+#define TWL6032_REG_SMPS3      58
+#define TWL6032_REG_SMPS4      59
+#define TWL6032_REG_VIO                60
 
 
 #endif /* End of __TWL4030_H */
diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
deleted file mode 100644 (file)
index 49269a2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __LINUX_TI_AM335X_TSC_H
-#define __LINUX_TI_AM335X_TSC_H
-
-/**
- * struct tsc_data     Touchscreen wire configuration
- * @wires:             Wires refer to application modes
- *                     i.e. 4/5/8 wire touchscreen support
- *                     on the platform.
- * @x_plate_resistance:        X plate resistance.
- * @steps_to_configure:        The sequencer supports a total of
- *                     16 programmable steps.
- *                     A step configured to read a single
- *                     co-ordinate value, can be applied
- *                     more number of times for better results.
- */
-
-struct tsc_data {
-       int wires;
-       int x_plate_resistance;
-       int steps_to_configure;
-};
-
-#endif
index e94537b..97cb283 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/regmap.h>
 #include <linux/atomic.h>
 
-#define PM80X_VERSION_MASK             (0xFF)  /* 80X chip ID mask */
 enum {
        CHIP_INVALID = 0,
        CHIP_PM800,
@@ -299,8 +298,7 @@ struct pm80x_chip {
        struct regmap *regmap;
        struct regmap_irq_chip *regmap_irq_chip;
        struct regmap_irq_chip_data *irq_data;
-       unsigned char version;
-       int id;
+       int type;
        int irq;
        int irq_mode;
        unsigned long wu_flag;
@@ -309,8 +307,14 @@ struct pm80x_chip {
 
 struct pm80x_platform_data {
        struct pm80x_rtc_pdata *rtc;
-       unsigned short power_page_addr; /* power page I2C address */
-       unsigned short gpadc_page_addr; /* gpadc page I2C address */
+       /*
+        * For the regulator not defined, set regulators[not_defined] to be
+        * NULL. num_regulators are the number of regulators supposed to be
+        * initialized. If all regulators are not defined, set num_regulators
+        * to be 0.
+        */
+       struct regulator_init_data *regulators[PM800_ID_RG_MAX];
+       unsigned int num_regulators;
        int irq_mode;           /* Clear interrupt by read/write(0/1) */
        int batt_det;           /* enable/disable */
        int (*plat_config)(struct pm80x_chip *chip,
@@ -363,7 +367,6 @@ static inline int pm80x_dev_resume(struct device *dev)
 }
 #endif
 
-extern int pm80x_init(struct i2c_client *client,
-                     const struct i2c_device_id *id);
+extern int pm80x_init(struct i2c_client *client);
 extern int pm80x_deinit(void);
 #endif /* __LINUX_MFD_88PM80X_H */
index 0390d59..f4acd89 100644 (file)
@@ -291,6 +291,8 @@ enum ab8500_version {
 #define AB8540_INT_FSYNC2R             213
 #define AB8540_INT_BITCLK2F            214
 #define AB8540_INT_BITCLK2R            215
+/* ab8540_irq_regoffset[27] -> IT[Source|Latch|Mask]33 */
+#define AB8540_INT_RTC_1S              216
 
 /*
  * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the
index f797bb9..5cf8b91 100644 (file)
@@ -23,6 +23,7 @@
 enum arizona_type {
        WM5102 = 1,
        WM5110 = 2,
+       WM8997 = 3,
 };
 
 #define ARIZONA_IRQ_GP1                    0
@@ -121,5 +122,6 @@ int arizona_set_irq_wake(struct arizona *arizona, int irq, int on);
 
 int wm5102_patch(struct arizona *arizona);
 int wm5110_patch(struct arizona *arizona);
+int wm8997_patch(struct arizona *arizona);
 
 #endif
index 7dd6524..13a1ee9 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/mfd/core.h>
 #include <linux/platform_data/edma.h>
 
+#include <mach/hardware.h>
+
 /*
  * Register values.
  */
@@ -111,8 +113,6 @@ struct davinci_vc {
 
        /* Memory resources */
        void __iomem *base;
-       resource_size_t pbase;
-       size_t base_size;
 
        /* MFD cells */
        struct mfd_cell cells[DAVINCI_VC_CELLS];
diff --git a/include/linux/mfd/kempld.h b/include/linux/mfd/kempld.h
new file mode 100644 (file)
index 0000000..b911ef3
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Kontron PLD driver definitions
+ *
+ * Copyright (c) 2010-2012 Kontron Europe GmbH
+ * Author: Michael Brunner <michael.brunner@kontron.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_MFD_KEMPLD_H_
+#define _LINUX_MFD_KEMPLD_H_
+
+/* kempld register definitions */
+#define KEMPLD_IOINDEX                 0xa80
+#define KEMPLD_IODATA                  0xa81
+#define KEMPLD_MUTEX_KEY               0x80
+#define KEMPLD_VERSION                 0x00
+#define KEMPLD_VERSION_LSB             0x00
+#define KEMPLD_VERSION_MSB             0x01
+#define KEMPLD_VERSION_GET_MINOR(x)    (x & 0x1f)
+#define KEMPLD_VERSION_GET_MAJOR(x)    ((x >> 5) & 0x1f)
+#define KEMPLD_VERSION_GET_NUMBER(x)   ((x >> 10) & 0xf)
+#define KEMPLD_VERSION_GET_TYPE(x)     ((x >> 14) & 0x3)
+#define KEMPLD_BUILDNR                 0x02
+#define KEMPLD_BUILDNR_LSB             0x02
+#define KEMPLD_BUILDNR_MSB             0x03
+#define KEMPLD_FEATURE                 0x04
+#define KEMPLD_FEATURE_LSB             0x04
+#define KEMPLD_FEATURE_MSB             0x05
+#define KEMPLD_FEATURE_BIT_I2C         (1 << 0)
+#define KEMPLD_FEATURE_BIT_WATCHDOG    (1 << 1)
+#define KEMPLD_FEATURE_BIT_GPIO                (1 << 2)
+#define KEMPLD_FEATURE_MASK_UART       (7 << 3)
+#define KEMPLD_FEATURE_BIT_NMI         (1 << 8)
+#define KEMPLD_FEATURE_BIT_SMI         (1 << 9)
+#define KEMPLD_FEATURE_BIT_SCI         (1 << 10)
+#define KEMPLD_SPEC                    0x06
+#define KEMPLD_SPEC_GET_MINOR(x)       (x & 0x0f)
+#define KEMPLD_SPEC_GET_MAJOR(x)       ((x >> 4) & 0x0f)
+#define KEMPLD_IRQ_GPIO                        0x35
+#define KEMPLD_IRQ_I2C                 0x36
+#define KEMPLD_CFG                     0x37
+#define KEMPLD_CFG_GPIO_I2C_MUX                (1 << 0)
+#define KEMPLD_CFG_BIOS_WP             (1 << 7)
+
+#define KEMPLD_CLK                     33333333
+
+#define        KEMPLD_TYPE_RELEASE             0x0
+#define        KEMPLD_TYPE_DEBUG               0x1
+#define        KEMPLD_TYPE_CUSTOM              0x2
+
+/**
+ * struct kempld_info - PLD device information structure
+ * @major:     PLD major revision
+ * @minor:     PLD minor revision
+ * @buildnr:   PLD build number
+ * @number:    PLD board specific index
+ * @type:      PLD type
+ * @spec_major:        PLD FW specification major revision
+ * @spec_minor:        PLD FW specification minor revision
+ */
+struct kempld_info {
+       unsigned int major;
+       unsigned int minor;
+       unsigned int buildnr;
+       unsigned int number;
+       unsigned int type;
+       unsigned int spec_major;
+       unsigned int spec_minor;
+};
+
+/**
+ * struct kempld_device_data - Internal representation of the PLD device
+ * @io_base:           Pointer to the IO memory
+ * @io_index:          Pointer to the IO index register
+ * @io_data:           Pointer to the IO data register
+ * @pld_clock:         PLD clock frequency
+ * @feature_mask:      PLD feature mask
+ * @dev:               Pointer to kernel device structure
+ * @info:              KEMPLD info structure
+ * @lock:              PLD mutex
+ */
+struct kempld_device_data {
+       void __iomem            *io_base;
+       void __iomem            *io_index;
+       void __iomem            *io_data;
+       u32                     pld_clock;
+       u32                     feature_mask;
+       struct device           *dev;
+       struct kempld_info      info;
+       struct mutex            lock;
+};
+
+/**
+ * struct kempld_platform_data - PLD hardware configuration structure
+ * @pld_clock:                 PLD clock frequency
+ * @gpio_base                  GPIO base pin number
+ * @ioresource:                        IO addresses of the PLD
+ * @get_mutex:                 PLD specific get_mutex callback
+ * @release_mutex:             PLD specific release_mutex callback
+ * @get_info:                  PLD specific get_info callback
+ * @register_cells:            PLD specific register_cells callback
+ */
+struct kempld_platform_data {
+       u32                             pld_clock;
+       int                             gpio_base;
+       struct resource                 *ioresource;
+       void (*get_hardware_mutex)      (struct kempld_device_data *);
+       void (*release_hardware_mutex)  (struct kempld_device_data *);
+       int (*get_info)                 (struct kempld_device_data *);
+       int (*register_cells)           (struct kempld_device_data *);
+};
+
+extern void kempld_get_mutex(struct kempld_device_data *pld);
+extern void kempld_release_mutex(struct kempld_device_data *pld);
+extern u8 kempld_read8(struct kempld_device_data *pld, u8 index);
+extern void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data);
+extern u16 kempld_read16(struct kempld_device_data *pld, u8 index);
+extern void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data);
+extern u32 kempld_read32(struct kempld_device_data *pld, u8 index);
+extern void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data);
+
+#endif /* _LINUX_MFD_KEMPLD_H_ */
index effa5d3..84844e0 100644 (file)
@@ -132,9 +132,12 @@ enum {
 
 #define MAX8998_ENRAMP                  (1 << 4)
 
+struct irq_domain;
+
 /**
  * struct max8998_dev - max8998 master device for sub-drivers
  * @dev: master device of the chip (can be used to access platform data)
+ * @pdata: platform data for the driver and subdrivers
  * @i2c: i2c client private data for regulator
  * @rtc: i2c client private data for rtc
  * @iolock: mutex for serializing io access
@@ -148,12 +151,14 @@ enum {
  */
 struct max8998_dev {
        struct device *dev;
+       struct max8998_platform_data *pdata;
        struct i2c_client *i2c;
        struct i2c_client *rtc;
        struct mutex iolock;
        struct mutex irqlock;
 
-       int irq_base;
+       unsigned int irq_base;
+       struct irq_domain *irq_domain;
        int irq;
        int ono;
        u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];
index 6823548..e3956a6 100644 (file)
@@ -58,10 +58,12 @@ enum {
  * max8998_regulator_data - regulator data
  * @id: regulator id
  * @initdata: regulator init data (contraints, supplies, ...)
+ * @reg_node: DT node of regulator (unused on non-DT platforms)
  */
 struct max8998_regulator_data {
        int                             id;
        struct regulator_init_data      *initdata;
+       struct device_node              *reg_node;
 };
 
 /**
@@ -73,12 +75,8 @@ struct max8998_regulator_data {
  * @buck_voltage_lock: Do NOT change the values of the following six
  *   registers set by buck?_voltage?. The voltage of BUCK1/2 cannot
  *   be other than the preset values.
- * @buck1_voltage1: BUCK1 DVS mode 1 voltage register
- * @buck1_voltage2: BUCK1 DVS mode 2 voltage register
- * @buck1_voltage3: BUCK1 DVS mode 3 voltage register
- * @buck1_voltage4: BUCK1 DVS mode 4 voltage register
- * @buck2_voltage1: BUCK2 DVS mode 1 voltage register
- * @buck2_voltage2: BUCK2 DVS mode 2 voltage register
+ * @buck1_voltage: BUCK1 DVS mode 1 voltage registers
+ * @buck2_voltage: BUCK2 DVS mode 2 voltage registers
  * @buck1_set1: BUCK1 gpio pin 1 to set output voltage
  * @buck1_set2: BUCK1 gpio pin 2 to set output voltage
  * @buck1_default_idx: Default for BUCK1 gpio pin 1, 2
@@ -100,15 +98,11 @@ struct max8998_regulator_data {
 struct max8998_platform_data {
        struct max8998_regulator_data   *regulators;
        int                             num_regulators;
-       int                             irq_base;
+       unsigned int                    irq_base;
        int                             ono;
        bool                            buck_voltage_lock;
-       int                             buck1_voltage1;
-       int                             buck1_voltage2;
-       int                             buck1_voltage3;
-       int                             buck1_voltage4;
-       int                             buck2_voltage1;
-       int                             buck2_voltage2;
+       int                             buck1_voltage[4];
+       int                             buck2_voltage[2];
        int                             buck1_set1;
        int                             buck1_set2;
        int                             buck1_default_idx;
index 9b81b2b..1a8dd7a 100644 (file)
                        ((a) == PALMAS_CHIP_ID))
 #define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID)
 
+/**
+ * Palmas PMIC feature types
+ *
+ * PALMAS_PMIC_FEATURE_SMPS10_BOOST - used when the PMIC provides SMPS10_BOOST
+ *     regulator.
+ *
+ * PALMAS_PMIC_HAS(b, f) - macro to check if a bandgap device is capable of a
+ *     specific feature (above) or not. Return non-zero, if yes.
+ */
+#define PALMAS_PMIC_FEATURE_SMPS10_BOOST       BIT(0)
+#define PALMAS_PMIC_HAS(b, f)                  \
+                       ((b)->features & PALMAS_PMIC_FEATURE_ ## f)
+
 struct palmas_pmic;
 struct palmas_gpadc;
 struct palmas_resource;
@@ -54,6 +67,7 @@ struct palmas {
        /* Stored chip id */
        int id;
 
+       unsigned int features;
        /* IRQ Data */
        int irq;
        u32 irq_mask;
index 86bc635..7a9f708 100644 (file)
 
 #define CARD_PWR_CTL                   0xFD50
 #define CARD_CLK_SWITCH                        0xFD51
+#define RTL8411B_PACKAGE_MODE          0xFD51
 #define CARD_SHARE_MODE                        0xFD52
 #define CARD_DRIVE_SEL                 0xFD53
 #define CARD_STOP                      0xFD54
index f0f4de3..378ae8a 100644 (file)
@@ -14,8 +14,6 @@
 #ifndef __LINUX_MFD_SEC_CORE_H
 #define __LINUX_MFD_SEC_CORE_H
 
-#define NUM_IRQ_REGS   4
-
 enum sec_device_type {
        S5M8751X,
        S5M8763X,
@@ -44,8 +42,6 @@ struct sec_pmic_dev {
        struct regmap *regmap;
        struct i2c_client *i2c;
        struct i2c_client *rtc;
-       struct mutex iolock;
-       struct mutex irqlock;
 
        int device_type;
        int irq_base;
@@ -53,8 +49,6 @@ struct sec_pmic_dev {
        struct regmap_irq_chip_data *irq_data;
 
        int ono;
-       u8 irq_masks_cur[NUM_IRQ_REGS];
-       u8 irq_masks_cache[NUM_IRQ_REGS];
        int type;
        bool wakeup;
 };
index c79ad5d..8d73fe2 100644 (file)
@@ -30,8 +30,8 @@
 #define REG_IDLECONFIG         0x058
 #define REG_CHARGECONFIG       0x05C
 #define REG_CHARGEDELAY                0x060
-#define REG_STEPCONFIG(n)      (0x64 + ((n - 1) * 8))
-#define REG_STEPDELAY(n)       (0x68 + ((n - 1) * 8))
+#define REG_STEPCONFIG(n)      (0x64 + ((n) * 8))
+#define REG_STEPDELAY(n)       (0x68 + ((n) * 8))
 #define REG_FIFO0CNT           0xE4
 #define REG_FIFO0THR           0xE8
 #define REG_FIFO1CNT           0xF0
@@ -46,8 +46,6 @@
 /* Step Enable */
 #define STEPENB_MASK           (0x1FFFF << 0)
 #define STEPENB(val)           ((val) << 0)
-#define STPENB_STEPENB         STEPENB(0x1FFFF)
-#define STPENB_STEPENB_TC      STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN          BIT(0)
@@ -73,8 +71,6 @@
 #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
 #define STEPCONFIG_INP_MASK    (0xF << 19)
 #define STEPCONFIG_INP(val)    ((val) << 19)
-#define STEPCONFIG_INP_AN2     STEPCONFIG_INP(2)
-#define STEPCONFIG_INP_AN3     STEPCONFIG_INP(3)
 #define STEPCONFIG_INP_AN4     STEPCONFIG_INP(4)
 #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
 #define STEPCONFIG_FIFO1       BIT(26)
@@ -96,7 +92,6 @@
 #define STEPCHARGE_INM_AN1     STEPCHARGE_INM(1)
 #define STEPCHARGE_INP_MASK    (0xF << 19)
 #define STEPCHARGE_INP(val)    ((val) << 19)
-#define STEPCHARGE_INP_AN1     STEPCHARGE_INP(1)
 #define STEPCHARGE_RFM_MASK    (3 << 23)
 #define STEPCHARGE_RFM(val)    ((val) << 23)
 #define STEPCHARGE_RFM_XNUR    STEPCHARGE_RFM(1)
 
 #define TSCADC_CELLS           2
 
-enum tscadc_cells {
-       TSC_CELL,
-       ADC_CELL,
-};
-
-struct mfd_tscadc_board {
-       struct tsc_data *tsc_init;
-       struct adc_data *adc_init;
-};
-
 struct ti_tscadc_dev {
        struct device *dev;
        struct regmap *regmap_tscadc;
        void __iomem *tscadc_base;
        int irq;
+       int used_cells; /* 1-2 */
+       int tsc_cell;   /* -1 if not used */
+       int adc_cell;   /* -1 if not used */
        struct mfd_cell cells[TSCADC_CELLS];
+       u32 reg_se_cache;
+       spinlock_t reg_lock;
 
        /* tsc device */
        struct titsc *tsc;
@@ -149,4 +139,15 @@ struct ti_tscadc_dev {
        struct adc_device *adc;
 };
 
+static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
+{
+       struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data;
+
+       return *tscadc_dev;
+}
+
+void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
+void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
+void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
+
 #endif
index ae5c249..40854ac 100644 (file)
@@ -29,6 +29,7 @@ enum wm8994_type {
 
 struct regulator_dev;
 struct regulator_bulk_data;
+struct irq_domain;
 
 #define WM8994_NUM_GPIO_REGS 11
 #define WM8994_NUM_LDO_REGS   2
@@ -73,6 +74,7 @@ struct wm8994 {
 
        int irq;
        struct regmap_irq_chip_data *irq_data;
+       struct irq_domain *edge_irq;
 
        /* Used over suspend/resume */
        bool suspended;
index b5046f6..90c6052 100644 (file)
@@ -228,6 +228,11 @@ struct wm8994_pdata {
         * lines is mastered.
         */
        int max_channels_clocked[WM8994_NUM_AIF];
+
+       /**
+        * GPIO for the IRQ pin if host only supports edge triggering
+        */
+       int irq_gpio;
 };
 
 #endif
diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h
deleted file mode 100644 (file)
index e41d583..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __LINUX_TI_AM335X_ADC_H
-#define __LINUX_TI_AM335X_ADC_H
-
-/**
- * struct adc_data     ADC Input information
- * @adc_channels:      Number of analog inputs
- *                     available for ADC.
- */
-
-struct adc_data {
-       unsigned int adc_channels;
-};
-
-#endif