Merge tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Apr 2014 17:24:18 +0000 (10:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Apr 2014 17:24:18 +0000 (10:24 -0700)
Pull MFD updates from Lee Jones:
 "Changes to existing drivers:
   - Use of managed resources - omap, twl4030, ti_am335x_tscadc
   - Advanced error handling - omap
   - Rework clk management - omap
   - Device Tree (re-)work - tc3589x, pm8921, da9055, sec
   - IRC management overhaul and !BROKEN - pm8921
   - Convert to regmap - ssbi, pm8921
   - Use simple power-management ops - ucb1x00
   - Include file clean-up - adp5520, cs5535, janz, lpc_ich,
      - lpc_sch, max14577, mcp-sa11x0, pcf50633-adc, rc5t583,
       rdc321x-southbridge, retu, smsc-ece1099, ti-ssp, ti_am335x_tscadc,
tps65912, vexpress-config, wm8350, ywm8350
   - Various bug fixes across the subsystem
      - NULL/invalid pointer dereference prevention
      - Resource leak mitigation,
      - Variable used initialised
      - Staticise various containers
      - Enforce return value checks

  New drivers/supported devices:
   - Add support for s2mps14 and s2mpa01 to sec
   - Add support for da9063 (v5) to da9063
   - Add support for atom-c2000 to gpio-ich
   - Add support for come-{mbt10,cbt6,chl6} to kempld
   - Add support for da9053 to da9052
   - Add support for itco-wdt (v3) and baytrail to lpc_ich
   - Add new drivers for tps65218, rtsx_usb, bcm590xx

  (Re-)moved drivers:
   - twl4030 ==> drivers/iio
   - ti-ssp  ==> /dev/null"

* tag 'mfd-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (103 commits)
  mfd: wm5110: Correct default for HEADPHONE_DETECT_1
  mfd: arizona: Correct small errors in the DT binding documentation
  mfd: arizona: Mark DSP clocking register as volatile
  mfd: devicetree: bindings: Add pm8xxx RTC description
  mfd: kempld-core: Fix potential hang-up during boot
  mfd: sec-core: Fix uninitialized 'regmap_rtc' on S2MPA01
  mfd: tps65910: Fix regmap_irq_chip_data leak on mfd_add_devices fail
  mfd: tps65910: Fix possible invalid pointer dereference on regmap_add_irq_chip fail
  mfd: sec-core: Fix I2C dummy device resource leak on probe failure
  mfd: sec-core: Add of_compatible strings for clock MFD cells
  mfd: Remove obsolete ti-ssp driver
  Documentation: mfd: s2mps11: Describe S5M8767 and S2MPS14 clocks
  mfd: bcm590xx: Fix type argument for module device table
  mfd: lpc_ich: Add support for Intel Bay Trail SoC
  mfd: lpc_ich: Add support for NM10 GPIO
  mfd: lpc_ich: Change Avoton to iTCO v3
  watchdog: iTCO_wdt: Add support for v3 silicon
  mfd: lpc_ich: Add support for iTCO v3
  mfd: lpc_ich: Remove lpc_ich_cfg struct use
  mfd: lpc_ich: Only configure watchdog or GPIO when present
  ...

93 files changed:
Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/arizona.txt
Documentation/devicetree/bindings/mfd/bcm590xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/da9055.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/omap-usb-host.txt
Documentation/devicetree/bindings/mfd/omap-usb-tll.txt
Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/s2mps11.txt
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/mach-omap2/cclock3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
drivers/clk/ti/clk-3xxx.c
drivers/gpio/gpio-ich.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/twl4030-madc.c [new file with mode: 0644]
drivers/mfd/88pm800.c
drivers/mfd/88pm860x-core.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/adp5520.c
drivers/mfd/as3722.c
drivers/mfd/bcm590xx.c [new file with mode: 0644]
drivers/mfd/cs5535-mfd.c
drivers/mfd/da9052-core.c
drivers/mfd/da9052-i2c.c
drivers/mfd/da9052-spi.c
drivers/mfd/da9055-i2c.c
drivers/mfd/da9063-core.c
drivers/mfd/janz-cmodio.c
drivers/mfd/kempld-core.c
drivers/mfd/lpc_ich.c
drivers/mfd/lpc_sch.c
drivers/mfd/max14577.c
drivers/mfd/max77686.c
drivers/mfd/max77693.c
drivers/mfd/max8925-i2c.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/mc13xxx-spi.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/omap-usb-host.c
drivers/mfd/omap-usb-tll.c
drivers/mfd/pcf50633-adc.c
drivers/mfd/pm8921-core.c
drivers/mfd/pm8xxx-irq.c [deleted file]
drivers/mfd/rc5t583-irq.c
drivers/mfd/rdc321x-southbridge.c
drivers/mfd/retu-mfd.c
drivers/mfd/rtsx_usb.c [new file with mode: 0644]
drivers/mfd/sec-core.c
drivers/mfd/smsc-ece1099.c
drivers/mfd/stmpe.c
drivers/mfd/stw481x.c
drivers/mfd/syscon.c
drivers/mfd/tc3589x.c
drivers/mfd/ti-ssp.c [deleted file]
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/timberdale.c
drivers/mfd/tps65218.c [new file with mode: 0644]
drivers/mfd/tps65910.c
drivers/mfd/tps65912-core.c
drivers/mfd/tps65912-irq.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-irq.c
drivers/mfd/twl4030-madc.c [deleted file]
drivers/mfd/twl6030-irq.c
drivers/mfd/twl6040.c
drivers/mfd/ucb1x00-core.c
drivers/mfd/vexpress-config.c
drivers/mfd/vexpress-sysreg.c
drivers/mfd/wm5102-tables.c
drivers/mfd/wm5110-tables.c
drivers/mfd/wm8350-core.c
drivers/mfd/wm8350-irq.c
drivers/mfd/wm8400-core.c
drivers/watchdog/iTCO_wdt.c
include/linux/i2c/twl.h
include/linux/i2c/twl4030-madc.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/bcm590xx.h [new file with mode: 0644]
include/linux/mfd/da9052/da9052.h
include/linux/mfd/da9063/core.h
include/linux/mfd/da9063/registers.h
include/linux/mfd/lpc_ich.h
include/linux/mfd/max14577-private.h
include/linux/mfd/max14577.h
include/linux/mfd/pm8xxx/irq.h [deleted file]
include/linux/mfd/pm8xxx/pm8921.h [deleted file]
include/linux/mfd/rtsx_usb.h [new file with mode: 0644]
include/linux/mfd/tps65218.h [new file with mode: 0644]
include/linux/ssbi.h

diff --git a/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt b/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt
new file mode 100644 (file)
index 0000000..6bdd214
--- /dev/null
@@ -0,0 +1,24 @@
+* TWL4030 Monitoring Analog to Digital Converter (MADC)
+
+The MADC subsystem in the TWL4030 consists of a 10-bit ADC
+combined with a 16-input analog multiplexer.
+
+Required properties:
+  - compatible: Should contain "ti,twl4030-madc".
+  - interrupts: IRQ line for the MADC submodule.
+  - #io-channel-cells: Should be set to <1>.
+
+Optional properties:
+  - ti,system-uses-second-madc-irq: boolean, set if the second madc irq register
+                                   should be used, which is intended to be used
+                                   by Co-Processors (e.g. a modem).
+
+Example:
+
+&twl {
+       madc {
+               compatible = "ti,twl4030-madc";
+               interrupts = <3>;
+               #io-channel-cells = <1>;
+       };
+};
index 0e295c9..36a0c3d 100644 (file)
@@ -5,9 +5,10 @@ of analogue I/O.
 
 Required properties:
 
-  - compatible : one of the following chip-specific strings:
-       "wlf,wm5102"
-       "wlf,wm5110"
+  - compatible : One of the following chip-specific strings:
+        "wlf,wm5102"
+        "wlf,wm5110"
+        "wlf,wm8997"
   - reg : I2C slave address when connected using I2C, chip select number when
     using SPI.
 
@@ -25,8 +26,9 @@ Required properties:
   - #gpio-cells : Must be 2. The first cell is the pin number and the
     second cell is used to specify optional parameters (currently unused).
 
-  - AVDD1-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply,
-    SPKVDDL-supply, SPKVDDR-supply : power supplies for the device, as covered
+  - AVDD-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply (wm5102, wm5110),
+    CPVDD-supply, SPKVDDL-supply (wm5102, wm5110), SPKVDDR-supply (wm5102,
+    wm5110), SPKVDD-supply (wm8997) : Power supplies for the device, as covered
     in Documentation/devicetree/bindings/regulator/regulator.txt
 
 Optional properties:
@@ -46,6 +48,7 @@ codec: wm5102@1a {
        compatible = "wlf,wm5102";
        reg = <0x1a>;
        interrupts = <347>;
+       interrupt-controller;
        #interrupt-cells = <2>;
         interrupt-parent = <&gic>;
 
@@ -53,10 +56,10 @@ codec: wm5102@1a {
        #gpio-cells = <2>;
 
        wlf,gpio-defaults = <
-               0x00000000, /* AIF1TXLRCLK */
-               0xffffffff,
-               0xffffffff,
-               0xffffffff,
-               0xffffffff,
+               0x00000000 /* AIF1TXLRCLK */
+               0xffffffff
+               0xffffffff
+               0xffffffff
+               0xffffffff
        >;
 };
diff --git a/Documentation/devicetree/bindings/mfd/bcm590xx.txt b/Documentation/devicetree/bindings/mfd/bcm590xx.txt
new file mode 100644 (file)
index 0000000..1fe30e2
--- /dev/null
@@ -0,0 +1,37 @@
+-------------------------------
+BCM590xx Power Management Units
+-------------------------------
+
+Required properties:
+- compatible: "brcm,bcm59056"
+- reg: I2C slave address
+- interrupts: interrupt for the PMU. Generic interrupt client node bindings
+  are described in interrupt-controller/interrupts.txt
+
+------------------
+Voltage Regulators
+------------------
+
+Optional child nodes:
+- regulators: container node for regulators following the generic
+  regulator binding in regulator/regulator.txt
+
+  The valid regulator node names for BCM59056 are:
+       rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
+       mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
+       csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr
+
+Example:
+       pmu: bcm59056@8 {
+               compatible = "brcm,bcm59056";
+               reg = <0x08>;
+               interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+               regulators {
+                       rfldo_reg: rfldo {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ...
+               };
+       };
diff --git a/Documentation/devicetree/bindings/mfd/da9055.txt b/Documentation/devicetree/bindings/mfd/da9055.txt
new file mode 100644 (file)
index 0000000..6dab34d
--- /dev/null
@@ -0,0 +1,72 @@
+* Dialog DA9055 Power Management Integrated Circuit (PMIC)
+
+DA9055 consists of a large and varied group of sub-devices (I2C Only):
+
+Device                  Supply Names    Description
+------                  ------------    -----------
+da9055-gpio            :               : GPIOs
+da9055-regulator       :               : Regulators
+da9055-onkey           :               : On key
+da9055-rtc             :               : RTC
+da9055-hwmon           :               : ADC
+da9055-watchdog                :               : Watchdog
+
+The CODEC device in DA9055 has a separate, configurable I2C address and so
+is instantiated separately from the PMIC.
+
+For details on accompanying CODEC I2C device, see the following:
+Documentation/devicetree/bindings/sound/da9055.txt
+
+======
+
+Required properties:
+- compatible : Should be "dlg,da9055-pmic"
+- reg: Specifies the I2C slave address (defaults to 0x5a but can be modified)
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the IRQs from da9055 are delivered to.
+- interrupts: IRQ line info for da9055 chip.
+- interrupt-controller: da9055 has internal IRQs (has own IRQ domain).
+- #interrupt-cells: Should be 1, is the local IRQ number for da9055.
+
+Sub-nodes:
+- regulators : Contain the regulator nodes. The DA9055 regulators are
+  bound using their names as listed below:
+
+    buck1     : regulator BUCK1
+    buck2     : regulator BUCK2
+    ldo1      : regulator LDO1
+    ldo2      : regulator LDO2
+    ldo3      : regulator LDO3
+    ldo4      : regulator LDO4
+    ldo5      : regulator LDO5
+    ldo6      : regulator LDO6
+
+  The bindings details of individual regulator device can be found in:
+  Documentation/devicetree/bindings/regulator/regulator.txt
+
+
+Example:
+
+       pmic: da9055-pmic@5a {
+               compatible = "dlg,da9055-pmic";
+               reg = <0x5a>;
+               interrupt-parent = <&intc>;
+               interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               regulators {
+                       buck1: BUCK1 {
+                               regulator-min-microvolt = <725000>;
+                               regulator-max-microvolt = <2075000>;
+                       };
+                       buck2: BUCK2 {
+                               regulator-min-microvolt = <925000>;
+                               regulator-max-microvolt = <2500000>;
+                       };
+                       ldo1: LDO1 {
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+               };
+       };
index b381fa6..4721b2d 100644 (file)
@@ -32,6 +32,29 @@ Optional properties:
 - single-ulpi-bypass: Must be present if the controller contains a single
   ULPI bypass control bit. e.g. OMAP3 silicon <= ES2.1
 
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+  clock-names.
+
+- clock-names: should include:
+  For OMAP3
+  * "usbhost_120m_fck" - 120MHz Functional clock.
+
+  For OMAP4+
+  * "refclk_60m_int" - 60MHz internal reference clock for UTMI clock mux
+  * "refclk_60m_ext_p1" - 60MHz external ref. clock for Port 1's UTMI clock mux.
+  * "refclk_60m_ext_p2" - 60MHz external ref. clock for Port 2's UTMI clock mux
+  * "utmi_p1_gfclk" - Port 1 UTMI clock mux.
+  * "utmi_p2_gfclk" - Port 2 UTMI clock mux.
+  * "usb_host_hs_utmi_p1_clk" - Port 1 UTMI clock gate.
+  * "usb_host_hs_utmi_p2_clk" - Port 2 UTMI clock gate.
+  * "usb_host_hs_utmi_p3_clk" - Port 3 UTMI clock gate.
+  * "usb_host_hs_hsic480m_p1_clk" - Port 1 480MHz HSIC clock gate.
+  * "usb_host_hs_hsic480m_p2_clk" - Port 2 480MHz HSIC clock gate.
+  * "usb_host_hs_hsic480m_p3_clk" - Port 3 480MHz HSIC clock gate.
+  * "usb_host_hs_hsic60m_p1_clk" - Port 1 60MHz HSIC clock gate.
+  * "usb_host_hs_hsic60m_p2_clk" - Port 2 60MHz HSIC clock gate.
+  * "usb_host_hs_hsic60m_p3_clk" - Port 3 60MHz HSIC clock gate.
+
 Required properties if child node exists:
 
 - #address-cells: Must be 1
index 62fe697..c58d704 100644 (file)
@@ -7,6 +7,16 @@ Required properties:
 - interrupts : should contain the TLL module's interrupt
 - ti,hwmod : must contain "usb_tll_hs"
 
+Optional properties:
+
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+  clock-names.
+
+- clock-names: should include:
+  * "usb_tll_hs_usb_ch0_clk" - USB TLL channel 0 clock
+  * "usb_tll_hs_usb_ch1_clk" - USB TLL channel 1 clock
+  * "usb_tll_hs_usb_ch2_clk" - USB TLL channel 2 clock
+
 Example:
 
        usbhstll: usbhstll@4a062000 {
diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt
new file mode 100644 (file)
index 0000000..03518dc
--- /dev/null
@@ -0,0 +1,96 @@
+Qualcomm PM8xxx PMIC multi-function devices
+
+The PM8xxx family of Power Management ICs are used to provide regulated
+voltages and other various functionality to Qualcomm SoCs.
+
+= PROPERTIES
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be one of:
+                   "qcom,pm8058"
+                   "qcom,pm8921"
+
+- #address-cells:
+       Usage: required
+       Value type: <u32>
+       Definition: must be 1
+
+- #size-cells:
+       Usage: required
+       Value type: <u32>
+       Definition: must be 0
+
+- interrupts:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: specifies the interrupt that indicates a subdevice
+                   has generated an interrupt (summary interrupt). The
+                   format of the specifier is defined by the binding document
+                   describing the node's interrupt parent.
+
+- #interrupt-cells:
+       Usage: required
+       Value type : <u32>
+       Definition: must be 2. Specifies the number of cells needed to encode
+                   an interrupt source. The 1st cell contains the interrupt
+                   number. The 2nd cell is the trigger type and level flags
+                   encoded as follows:
+
+                       1 = low-to-high edge triggered
+                       2 = high-to-low edge triggered
+                       4 = active high level-sensitive
+                       8 = active low level-sensitive
+
+- interrupt-controller:
+       Usage: required
+       Value type: <empty>
+       Definition: identifies this node as an interrupt controller
+
+= SUBCOMPONENTS
+
+The PMIC contains multiple independent functions, each described in a subnode.
+The below bindings specify the set of valid subnodes.
+
+== Real-Time Clock
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be one of:
+                   "qcom,pm8058-rtc"
+                   "qcom,pm8921-rtc"
+
+- reg:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: single entry specifying the base address of the RTC registers
+
+- interrupts:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: single entry specifying the RTC's alarm interrupt
+
+- allow-set-time:
+       Usage: optional
+       Value type: <empty>
+       Definition: indicates that the setting of RTC time is allowed by
+                   the host CPU
+
+= EXAMPLE
+
+       pmicintc: pmic@0 {
+               compatible = "qcom,pm8921";
+               interrupts = <104 8>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rtc@11d {
+                       compatible = "qcom,pm8921-rtc";
+                       reg = <0x11d>;
+                       interrupts = <0x27 0>;
+               };
+       };
index f69bec2..802e839 100644 (file)
@@ -16,20 +16,25 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
-- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
-  register these as clocks with common clock framework instantiate a sub-node
-  named "clocks". It uses the common clock binding documented in :
+- clocks: s2mps11 and s5m8767 provide three(AP/CP/BT) buffered 32.768 KHz
+  outputs, so to register these as clocks with common clock framework
+  instantiate a sub-node named "clocks". It uses the common clock binding
+  documented in :
   [Documentation/devicetree/bindings/clock/clock-bindings.txt]
+  The s2mps14 provides two (AP/BT) buffered 32.768 KHz outputs.
   - #clock-cells: should be 1.
 
   - The following is the list of clocks generated by the controller. Each clock
     is assigned an identifier and client nodes use this identifier to specify
     the clock which they consume.
-    Clock               ID
-    ----------------------
-    32KhzAP            0
-    32KhzCP            1
-    32KhzBT            2
+    Clock               ID           Devices
+    ----------------------------------------------------------
+    32KhzAP            0            S2MPS11, S2MPS14, S5M8767
+    32KhzCP            1            S2MPS11, S5M8767
+    32KhzBT            2            S2MPS11, S2MPS14, S5M8767
+
+  - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps14-clk",
+               "samsung,s5m8767-clk"
 
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
@@ -75,7 +80,8 @@ Example:
                compatible = "samsung,s2mps11-pmic";
                reg = <0x66>;
 
-               s2m_osc: clocks{
+               s2m_osc: clocks {
+                       compatible = "samsung,s2mps11-clk";
                        #clock-cells = 1;
                        clock-output-names = "xx", "yy", "zz";
                };
index fe61976..0769ec5 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
+                       clocks = <&init_60m_fclk>,
+                                <&xclk60mhsp1_ck>,
+                                <&xclk60mhsp2_ck>;
+                       clock-names = "refclk_60m_int",
+                                     "refclk_60m_ext_p1",
+                                     "refclk_60m_ext_p2";
 
                        usbhsohci: ohci@4a064800 {
                                compatible = "ti,ohci-omap3";
index 8292ad0..19155bb 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
+                       clocks = <&l3init_60m_fclk>,
+                                <&xclk60mhsp1_ck>,
+                                <&xclk60mhsp2_ck>;
+                       clock-names = "refclk_60m_int",
+                                     "refclk_60m_ext_p1",
+                                     "refclk_60m_ext_p2";
 
                        usbhsohci: ohci@4a064800 {
                                compatible = "ti,ohci-omap3";
index 11ed915..8f5121b 100644 (file)
@@ -3497,10 +3497,6 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "dss_tv_fck",   &dss_tv_fck),
        CLK(NULL,       "dss_96m_fck",  &dss_96m_fck),
        CLK(NULL,       "dss2_alwon_fck",       &dss2_alwon_fck),
-       CLK(NULL,       "utmi_p1_gfclk",        &dummy_ck),
-       CLK(NULL,       "utmi_p2_gfclk",        &dummy_ck),
-       CLK(NULL,       "xclk60mhsp1_ck",       &dummy_ck),
-       CLK(NULL,       "xclk60mhsp2_ck",       &dummy_ck),
        CLK(NULL,       "init_60m_fclk",        &dummy_ck),
        CLK(NULL,       "gpt1_fck",     &gpt1_fck),
        CLK(NULL,       "aes2_ick",     &aes2_ick),
index 9c7e23a..a123ff0 100644 (file)
@@ -1955,10 +1955,6 @@ static struct omap_hwmod_class omap3xxx_usb_host_hs_hwmod_class = {
        .sysc = &omap3xxx_usb_host_hs_sysc,
 };
 
-static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = {
-         { .role = "ehci_logic_fck", .clk = "usbhost_120m_fck", },
-};
-
 static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = {
        { .name = "ohci-irq", .irq = 76 + OMAP_INTC_START, },
        { .name = "ehci-irq", .irq = 77 + OMAP_INTC_START, },
@@ -1981,8 +1977,6 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
                        .idlest_stdby_bit = OMAP3430ES2_ST_USBHOST_STDBY_SHIFT,
                },
        },
-       .opt_clks       = omap3xxx_usb_host_hs_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(omap3xxx_usb_host_hs_opt_clks),
 
        /*
         * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
index d323023..0d1750a 100644 (file)
@@ -130,10 +130,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"),
        DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"),
        DT_CLK(NULL, "dss2_alwon_fck", "dss2_alwon_fck"),
-       DT_CLK(NULL, "utmi_p1_gfclk", "dummy_ck"),
-       DT_CLK(NULL, "utmi_p2_gfclk", "dummy_ck"),
-       DT_CLK(NULL, "xclk60mhsp1_ck", "dummy_ck"),
-       DT_CLK(NULL, "xclk60mhsp2_ck", "dummy_ck"),
        DT_CLK(NULL, "init_60m_fclk", "dummy_ck"),
        DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
        DT_CLK(NULL, "aes2_ick", "aes2_ick"),
index bfef20f..e73c675 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Intel ICH6-10, Series 5 and 6 GPIO driver
+ * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver
  *
  * Copyright (C) 2010 Extreme Engineering Solutions.
  *
@@ -55,6 +55,16 @@ static const u8 ichx_reglen[3] = {
        0x30, 0x10, 0x10,
 };
 
+static const u8 avoton_regs[4][3] = {
+       {0x00, 0x80, 0x00},
+       {0x04, 0x84, 0x00},
+       {0x08, 0x88, 0x00},
+};
+
+static const u8 avoton_reglen[3] = {
+       0x10, 0x10, 0x00,
+};
+
 #define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
 #define ICHX_READ(reg, base_res)       inl((reg) + (base_res)->start)
 
@@ -353,6 +363,17 @@ static struct ichx_desc intel5_desc = {
        .reglen = ichx_reglen,
 };
 
+/* Avoton */
+static struct ichx_desc avoton_desc = {
+       /* Avoton has only 59 GPIOs, but we assume the first set of register
+        * (Core) has 32 instead of 31 to keep gpio-ich compliance
+        */
+       .ngpio = 60,
+       .regs = avoton_regs,
+       .reglen = avoton_reglen,
+       .use_outlvl_cache = true,
+};
+
 static int ichx_gpio_request_regions(struct resource *res_base,
                                                const char *name, u8 use_gpio)
 {
@@ -427,6 +448,9 @@ static int ichx_gpio_probe(struct platform_device *pdev)
        case ICH_V10CONS_GPIO:
                ichx_priv.desc = &ich10_cons_desc;
                break;
+       case AVOTON_GPIO:
+               ichx_priv.desc = &avoton_desc;
+               break;
        default:
                return -ENODEV;
        }
index 4bf4c16..d86196c 100644 (file)
@@ -193,6 +193,16 @@ config TI_AM335X_ADC
          Say yes here to build support for Texas Instruments ADC
          driver which is also a MFD client.
 
+config TWL4030_MADC
+       tristate "TWL4030 MADC (Monitoring A/D Converter)"
+       depends on TWL4030_CORE
+       help
+       This driver provides support for Triton TWL4030-MADC. The
+       driver supports both RT and SW conversion methods.
+
+       This driver can also be built as a module. If so, the module will be
+       called twl4030-madc.
+
 config TWL6030_GPADC
        tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
        depends on TWL4030_CORE
index bb25254..ab346d8 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_NAU7802) += nau7802.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
+obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
new file mode 100644 (file)
index 0000000..7de1c4c
--- /dev/null
@@ -0,0 +1,895 @@
+/*
+ *
+ * TWL4030 MADC module driver-This driver monitors the real time
+ * conversion of analog signals like battery temperature,
+ * battery type, battery level etc.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * J Keerthy <j-keerthy@ti.com>
+ *
+ * Based on twl4030-madc.c
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@nokia.com>
+ *
+ * Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/i2c/twl.h>
+#include <linux/i2c/twl4030-madc.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/mutex.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/err.h>
+
+#include <linux/iio/iio.h>
+
+/**
+ * struct twl4030_madc_data - a container for madc info
+ * @dev:               Pointer to device structure for madc
+ * @lock:              Mutex protecting this data structure
+ * @requests:          Array of request struct corresponding to SW1, SW2 and RT
+ * @use_second_irq:    IRQ selection (main or co-processor)
+ * @imr:               Interrupt mask register of MADC
+ * @isr:               Interrupt status register of MADC
+ */
+struct twl4030_madc_data {
+       struct device *dev;
+       struct mutex lock;      /* mutex protecting this data structure */
+       struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
+       bool use_second_irq;
+       u8 imr;
+       u8 isr;
+};
+
+static int twl4030_madc_read(struct iio_dev *iio_dev,
+                            const struct iio_chan_spec *chan,
+                            int *val, int *val2, long mask)
+{
+       struct twl4030_madc_data *madc = iio_priv(iio_dev);
+       struct twl4030_madc_request req;
+       int ret;
+
+       req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1;
+
+       req.channels = BIT(chan->channel);
+       req.active = false;
+       req.func_cb = NULL;
+       req.type = TWL4030_MADC_WAIT;
+       req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
+       req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
+
+       ret = twl4030_madc_conversion(&req);
+       if (ret < 0)
+               return ret;
+
+       *val = req.rbuf[chan->channel];
+
+       return IIO_VAL_INT;
+}
+
+static const struct iio_info twl4030_madc_iio_info = {
+       .read_raw = &twl4030_madc_read,
+       .driver_module = THIS_MODULE,
+};
+
+#define TWL4030_ADC_CHANNEL(_channel, _type, _name) {  \
+       .type = _type,                                  \
+       .channel = _channel,                            \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
+                             BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
+                             BIT(IIO_CHAN_INFO_PROCESSED), \
+       .datasheet_name = _name,                        \
+       .indexed = 1,                                   \
+}
+
+static const struct iio_chan_spec twl4030_madc_iio_channels[] = {
+       TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"),
+       TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"),
+       TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"),
+       TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"),
+       TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"),
+       TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"),
+       TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"),
+       TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"),
+       TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"),
+       TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"),
+       TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"),
+       TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"),
+       TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"),
+       TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"),
+       TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"),
+       TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"),
+};
+
+static struct twl4030_madc_data *twl4030_madc;
+
+struct twl4030_prescale_divider_ratios {
+       s16 numerator;
+       s16 denominator;
+};
+
+static const struct twl4030_prescale_divider_ratios
+twl4030_divider_ratios[16] = {
+       {1, 1},         /* CHANNEL 0 No Prescaler */
+       {1, 1},         /* CHANNEL 1 No Prescaler */
+       {6, 10},        /* CHANNEL 2 */
+       {6, 10},        /* CHANNEL 3 */
+       {6, 10},        /* CHANNEL 4 */
+       {6, 10},        /* CHANNEL 5 */
+       {6, 10},        /* CHANNEL 6 */
+       {6, 10},        /* CHANNEL 7 */
+       {3, 14},        /* CHANNEL 8 */
+       {1, 3},         /* CHANNEL 9 */
+       {1, 1},         /* CHANNEL 10 No Prescaler */
+       {15, 100},      /* CHANNEL 11 */
+       {1, 4},         /* CHANNEL 12 */
+       {1, 1},         /* CHANNEL 13 Reserved channels */
+       {1, 1},         /* CHANNEL 14 Reseved channels */
+       {5, 11},        /* CHANNEL 15 */
+};
+
+
+/* Conversion table from -3 to 55 degrees Celcius */
+static int twl4030_therm_tbl[] = {
+       30800,  29500,  28300,  27100,
+       26000,  24900,  23900,  22900,  22000,  21100,  20300,  19400,  18700,
+       17900,  17200,  16500,  15900,  15300,  14700,  14100,  13600,  13100,
+       12600,  12100,  11600,  11200,  10800,  10400,  10000,  9630,   9280,
+       8950,   8620,   8310,   8020,   7730,   7460,   7200,   6950,   6710,
+       6470,   6250,   6040,   5830,   5640,   5450,   5260,   5090,   4920,
+       4760,   4600,   4450,   4310,   4170,   4040,   3910,   3790,   3670,
+       3550
+};
+
+/*
+ * Structure containing the registers
+ * of different conversion methods supported by MADC.
+ * Hardware or RT real time conversion request initiated by external host
+ * processor for RT Signal conversions.
+ * External host processors can also request for non RT conversions
+ * SW1 and SW2 software conversions also called asynchronous or GPC request.
+ */
+static
+const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
+       [TWL4030_MADC_RT] = {
+                            .sel = TWL4030_MADC_RTSELECT_LSB,
+                            .avg = TWL4030_MADC_RTAVERAGE_LSB,
+                            .rbase = TWL4030_MADC_RTCH0_LSB,
+                            },
+       [TWL4030_MADC_SW1] = {
+                             .sel = TWL4030_MADC_SW1SELECT_LSB,
+                             .avg = TWL4030_MADC_SW1AVERAGE_LSB,
+                             .rbase = TWL4030_MADC_GPCH0_LSB,
+                             .ctrl = TWL4030_MADC_CTRL_SW1,
+                             },
+       [TWL4030_MADC_SW2] = {
+                             .sel = TWL4030_MADC_SW2SELECT_LSB,
+                             .avg = TWL4030_MADC_SW2AVERAGE_LSB,
+                             .rbase = TWL4030_MADC_GPCH0_LSB,
+                             .ctrl = TWL4030_MADC_CTRL_SW2,
+                             },
+};
+
+/**
+ * twl4030_madc_channel_raw_read() - Function to read a particular channel value
+ * @madc:      pointer to struct twl4030_madc_data
+ * @reg:       lsb of ADC Channel
+ *
+ * Return: 0 on success, an error code otherwise.
+ */
+static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
+{
+       u16 val;
+       int ret;
+       /*
+        * For each ADC channel, we have MSB and LSB register pair. MSB address
+        * is always LSB address+1. reg parameter is the address of LSB register
+        */
+       ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg);
+       if (ret) {
+               dev_err(madc->dev, "unable to read register 0x%X\n", reg);
+               return ret;
+       }
+
+       return (int)(val >> 6);
+}
+
+/*
+ * Return battery temperature in degrees Celsius
+ * Or < 0 on failure.
+ */
+static int twl4030battery_temperature(int raw_volt)
+{
+       u8 val;
+       int temp, curr, volt, res, ret;
+
+       volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
+       /* Getting and calculating the supply current in micro amperes */
+       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
+               REG_BCICTL2);
+       if (ret < 0)
+               return ret;
+
+       curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
+       /* Getting and calculating the thermistor resistance in ohms */
+       res = volt * 1000 / curr;
+       /* calculating temperature */
+       for (temp = 58; temp >= 0; temp--) {
+               int actual = twl4030_therm_tbl[temp];
+               if ((actual - res) >= 0)
+                       break;
+       }
+
+       return temp + 1;
+}
+
+static int twl4030battery_current(int raw_volt)
+{
+       int ret;
+       u8 val;
+
+       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
+               TWL4030_BCI_BCICTL1);
+       if (ret)
+               return ret;
+       if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
+               return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
+       else /* slope of 0.88 mV/mA */
+               return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
+}
+
+/*
+ * Function to read channel values
+ * @madc - pointer to twl4030_madc_data struct
+ * @reg_base - Base address of the first channel
+ * @Channels - 16 bit bitmap. If the bit is set, channel's value is read
+ * @buf - The channel values are stored here. if read fails error
+ * @raw - Return raw values without conversion
+ * value is stored
+ * Returns the number of successfully read channels.
+ */
+static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
+                                     u8 reg_base, unsigned
+                                     long channels, int *buf,
+                                     bool raw)
+{
+       int count = 0;
+       int i;
+       u8 reg;
+
+       for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
+               reg = reg_base + (2 * i);
+               buf[i] = twl4030_madc_channel_raw_read(madc, reg);
+               if (buf[i] < 0) {
+                       dev_err(madc->dev, "Unable to read register 0x%X\n",
+                               reg);
+                       return buf[i];
+               }
+               if (raw) {
+                       count++;
+                       continue;
+               }
+               switch (i) {
+               case 10:
+                       buf[i] = twl4030battery_current(buf[i]);
+                       if (buf[i] < 0) {
+                               dev_err(madc->dev, "err reading current\n");
+                               return buf[i];
+                       } else {
+                               count++;
+                               buf[i] = buf[i] - 750;
+                       }
+                       break;
+               case 1:
+                       buf[i] = twl4030battery_temperature(buf[i]);
+                       if (buf[i] < 0) {
+                               dev_err(madc->dev, "err reading temperature\n");
+                               return buf[i];
+                       } else {
+                               buf[i] -= 3;
+                               count++;
+                       }
+                       break;
+               default:
+                       count++;
+                       /* Analog Input (V) = conv_result * step_size / R
+                        * conv_result = decimal value of 10-bit conversion
+                        *               result
+                        * step size = 1.5 / (2 ^ 10 -1)
+                        * R = Prescaler ratio for input channels.
+                        * Result given in mV hence multiplied by 1000.
+                        */
+                       buf[i] = (buf[i] * 3 * 1000 *
+                                twl4030_divider_ratios[i].denominator)
+                               / (2 * 1023 *
+                               twl4030_divider_ratios[i].numerator);
+               }
+       }
+
+       return count;
+}
+
+/*
+ * Enables irq.
+ * @madc - pointer to twl4030_madc_data struct
+ * @id - irq number to be enabled
+ * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
+ * corresponding to RT, SW1, SW2 conversion requests.
+ * If the i2c read fails it returns an error else returns 0.
+ */
+static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
+{
+       u8 val;
+       int ret;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
+       if (ret) {
+               dev_err(madc->dev, "unable to read imr register 0x%X\n",
+                       madc->imr);
+               return ret;
+       }
+
+       val &= ~(1 << id);
+       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
+       if (ret) {
+               dev_err(madc->dev,
+                       "unable to write imr register 0x%X\n", madc->imr);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Disables irq.
+ * @madc - pointer to twl4030_madc_data struct
+ * @id - irq number to be disabled
+ * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
+ * corresponding to RT, SW1, SW2 conversion requests.
+ * Returns error if i2c read/write fails.
+ */
+static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
+{
+       u8 val;
+       int ret;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
+       if (ret) {
+               dev_err(madc->dev, "unable to read imr register 0x%X\n",
+                       madc->imr);
+               return ret;
+       }
+       val |= (1 << id);
+       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
+       if (ret) {
+               dev_err(madc->dev,
+                       "unable to write imr register 0x%X\n", madc->imr);
+               return ret;
+       }
+
+       return 0;
+}
+
+static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
+{
+       struct twl4030_madc_data *madc = _madc;
+       const struct twl4030_madc_conversion_method *method;
+       u8 isr_val, imr_val;
+       int i, len, ret;
+       struct twl4030_madc_request *r;
+
+       mutex_lock(&madc->lock);
+       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
+       if (ret) {
+               dev_err(madc->dev, "unable to read isr register 0x%X\n",
+                       madc->isr);
+               goto err_i2c;
+       }
+       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
+       if (ret) {
+               dev_err(madc->dev, "unable to read imr register 0x%X\n",
+                       madc->imr);
+               goto err_i2c;
+       }
+       isr_val &= ~imr_val;
+       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+               if (!(isr_val & (1 << i)))
+                       continue;
+               ret = twl4030_madc_disable_irq(madc, i);
+               if (ret < 0)
+                       dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
+               madc->requests[i].result_pending = 1;
+       }
+       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+               r = &madc->requests[i];
+               /* No pending results for this method, move to next one */
+               if (!r->result_pending)
+                       continue;
+               method = &twl4030_conversion_methods[r->method];
+               /* Read results */
+               len = twl4030_madc_read_channels(madc, method->rbase,
+                                                r->channels, r->rbuf, r->raw);
+               /* Return results to caller */
+               if (r->func_cb != NULL) {
+                       r->func_cb(len, r->channels, r->rbuf);
+                       r->func_cb = NULL;
+               }
+               /* Free request */
+               r->result_pending = 0;
+               r->active = 0;
+       }
+       mutex_unlock(&madc->lock);
+
+       return IRQ_HANDLED;
+
+err_i2c:
+       /*
+        * In case of error check whichever request is active
+        * and service the same.
+        */
+       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+               r = &madc->requests[i];
+               if (r->active == 0)
+                       continue;
+               method = &twl4030_conversion_methods[r->method];
+               /* Read results */
+               len = twl4030_madc_read_channels(madc, method->rbase,
+                                                r->channels, r->rbuf, r->raw);
+               /* Return results to caller */
+               if (r->func_cb != NULL) {
+                       r->func_cb(len, r->channels, r->rbuf);
+                       r->func_cb = NULL;
+               }
+               /* Free request */
+               r->result_pending = 0;
+               r->active = 0;
+       }
+       mutex_unlock(&madc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
+                               struct twl4030_madc_request *req)
+{
+       struct twl4030_madc_request *p;
+       int ret;
+
+       p = &madc->requests[req->method];
+       memcpy(p, req, sizeof(*req));
+       ret = twl4030_madc_enable_irq(madc, req->method);
+       if (ret < 0) {
+               dev_err(madc->dev, "enable irq failed!!\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Function which enables the madc conversion
+ * by writing to the control register.
+ * @madc - pointer to twl4030_madc_data struct
+ * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
+ * corresponding to RT SW1 or SW2 conversion methods.
+ * Returns 0 if succeeds else a negative error value
+ */
+static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
+                                        int conv_method)
+{
+       const struct twl4030_madc_conversion_method *method;
+       int ret = 0;
+
+       if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2)
+               return -ENOTSUPP;
+
+       method = &twl4030_conversion_methods[conv_method];
+       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, TWL4030_MADC_SW_START,
+                              method->ctrl);
+       if (ret) {
+               dev_err(madc->dev, "unable to write ctrl register 0x%X\n",
+                       method->ctrl);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Function that waits for conversion to be ready
+ * @madc - pointer to twl4030_madc_data struct
+ * @timeout_ms - timeout value in milliseconds
+ * @status_reg - ctrl register
+ * returns 0 if succeeds else a negative error value
+ */
+static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
+                                             unsigned int timeout_ms,
+                                             u8 status_reg)
+{
+       unsigned long timeout;
+       int ret;
+
+       timeout = jiffies + msecs_to_jiffies(timeout_ms);
+       do {
+               u8 reg;
+
+               ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
+               if (ret) {
+                       dev_err(madc->dev,
+                               "unable to read status register 0x%X\n",
+                               status_reg);
+                       return ret;
+               }
+               if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
+                       return 0;
+               usleep_range(500, 2000);
+       } while (!time_after(jiffies, timeout));
+       dev_err(madc->dev, "conversion timeout!\n");
+
+       return -EAGAIN;
+}
+
+/*
+ * An exported function which can be called from other kernel drivers.
+ * @req twl4030_madc_request structure
+ * req->rbuf will be filled with read values of channels based on the
+ * channel index. If a particular channel reading fails there will
+ * be a negative error value in the corresponding array element.
+ * returns 0 if succeeds else error value
+ */
+int twl4030_madc_conversion(struct twl4030_madc_request *req)
+{
+       const struct twl4030_madc_conversion_method *method;
+       int ret;
+
+       if (!req || !twl4030_madc)
+               return -EINVAL;
+
+       mutex_lock(&twl4030_madc->lock);
+       if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
+               ret = -EINVAL;
+               goto out;
+       }
+       /* Do we have a conversion request ongoing */
+       if (twl4030_madc->requests[req->method].active) {
+               ret = -EBUSY;
+               goto out;
+       }
+       method = &twl4030_conversion_methods[req->method];
+       /* Select channels to be converted */
+       ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel);
+       if (ret) {
+               dev_err(twl4030_madc->dev,
+                       "unable to write sel register 0x%X\n", method->sel);
+               goto out;
+       }
+       /* Select averaging for all channels if do_avg is set */
+       if (req->do_avg) {
+               ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels,
+                                      method->avg);
+               if (ret) {
+                       dev_err(twl4030_madc->dev,
+                               "unable to write avg register 0x%X\n",
+                               method->avg);
+                       goto out;
+               }
+       }
+       if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
+               ret = twl4030_madc_set_irq(twl4030_madc, req);
+               if (ret < 0)
+                       goto out;
+               ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
+               if (ret < 0)
+                       goto out;
+               twl4030_madc->requests[req->method].active = 1;
+               ret = 0;
+               goto out;
+       }
+       /* With RT method we should not be here anymore */
+       if (req->method == TWL4030_MADC_RT) {
+               ret = -EINVAL;
+               goto out;
+       }
+       ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
+       if (ret < 0)
+               goto out;
+       twl4030_madc->requests[req->method].active = 1;
+       /* Wait until conversion is ready (ctrl register returns EOC) */
+       ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
+       if (ret) {
+               twl4030_madc->requests[req->method].active = 0;
+               goto out;
+       }
+       ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
+                                        req->channels, req->rbuf, req->raw);
+       twl4030_madc->requests[req->method].active = 0;
+
+out:
+       mutex_unlock(&twl4030_madc->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
+
+int twl4030_get_madc_conversion(int channel_no)
+{
+       struct twl4030_madc_request req;
+       int temp = 0;
+       int ret;
+
+       req.channels = (1 << channel_no);
+       req.method = TWL4030_MADC_SW2;
+       req.active = 0;
+       req.func_cb = NULL;
+       ret = twl4030_madc_conversion(&req);
+       if (ret < 0)
+               return ret;
+       if (req.rbuf[channel_no] > 0)
+               temp = req.rbuf[channel_no];
+
+       return temp;
+}
+EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
+
+/**
+ * twl4030_madc_set_current_generator() - setup bias current
+ *
+ * @madc:      pointer to twl4030_madc_data struct
+ * @chan:      can be one of the two values:
+ *             TWL4030_BCI_ITHEN
+ *             Enables bias current for main battery type reading
+ *             TWL4030_BCI_TYPEN
+ *             Enables bias current for main battery temperature sensing
+ * @on:                enable or disable chan.
+ *
+ * Function to enable or disable bias current for
+ * main battery type reading or temperature sensing
+ */
+static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
+                                             int chan, int on)
+{
+       int ret;
+       int regmask;
+       u8 regval;
+
+       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
+                             &regval, TWL4030_BCI_BCICTL1);
+       if (ret) {
+               dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
+                       TWL4030_BCI_BCICTL1);
+               return ret;
+       }
+
+       regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
+       if (on)
+               regval |= regmask;
+       else
+               regval &= ~regmask;
+
+       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                              regval, TWL4030_BCI_BCICTL1);
+       if (ret) {
+               dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
+                       TWL4030_BCI_BCICTL1);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Function that sets MADC software power on bit to enable MADC
+ * @madc - pointer to twl4030_madc_data struct
+ * @on - Enable or disable MADC software power on bit.
+ * returns error if i2c read/write fails else 0
+ */
+static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
+{
+       u8 regval;
+       int ret;
+
+       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
+                             &regval, TWL4030_MADC_CTRL1);
+       if (ret) {
+               dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
+                       TWL4030_MADC_CTRL1);
+               return ret;
+       }
+       if (on)
+               regval |= TWL4030_MADC_MADCON;
+       else
+               regval &= ~TWL4030_MADC_MADCON;
+       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
+       if (ret) {
+               dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
+                       TWL4030_MADC_CTRL1);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialize MADC and request for threaded irq
+ */
+static int twl4030_madc_probe(struct platform_device *pdev)
+{
+       struct twl4030_madc_data *madc;
+       struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
+       int irq, ret;
+       u8 regval;
+       struct iio_dev *iio_dev = NULL;
+
+       if (!pdata && !np) {
+               dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
+               return -EINVAL;
+       }
+
+       iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc));
+       if (!iio_dev) {
+               dev_err(&pdev->dev, "failed allocating iio device\n");
+               return -ENOMEM;
+       }
+
+       madc = iio_priv(iio_dev);
+       madc->dev = &pdev->dev;
+
+       iio_dev->name = dev_name(&pdev->dev);
+       iio_dev->dev.parent = &pdev->dev;
+       iio_dev->dev.of_node = pdev->dev.of_node;
+       iio_dev->info = &twl4030_madc_iio_info;
+       iio_dev->modes = INDIO_DIRECT_MODE;
+       iio_dev->channels = twl4030_madc_iio_channels;
+       iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels);
+
+       /*
+        * Phoenix provides 2 interrupt lines. The first one is connected to
+        * the OMAP. The other one can be connected to the other processor such
+        * as modem. Hence two separate ISR and IMR registers.
+        */
+       if (pdata)
+               madc->use_second_irq = (pdata->irq_line != 1);
+       else
+               madc->use_second_irq = of_property_read_bool(np,
+                                      "ti,system-uses-second-madc-irq");
+
+       madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
+                                          TWL4030_MADC_IMR1;
+       madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 :
+                                          TWL4030_MADC_ISR1;
+
+       ret = twl4030_madc_set_power(madc, 1);
+       if (ret < 0)
+               return ret;
+       ret = twl4030_madc_set_current_generator(madc, 0, 1);
+       if (ret < 0)
+               goto err_current_generator;
+
+       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
+                             &regval, TWL4030_BCI_BCICTL1);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
+                       TWL4030_BCI_BCICTL1);
+               goto err_i2c;
+       }
+       regval |= TWL4030_BCI_MESBAT;
+       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                              regval, TWL4030_BCI_BCICTL1);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
+                       TWL4030_BCI_BCICTL1);
+               goto err_i2c;
+       }
+
+       /* Check that MADC clock is on */
+       ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
+                               TWL4030_REG_GPBR1);
+               goto err_i2c;
+       }
+
+       /* If MADC clk is not on, turn it on */
+       if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
+               dev_info(&pdev->dev, "clk disabled, enabling\n");
+               regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
+               ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
+                                      TWL4030_REG_GPBR1);
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
+                                       TWL4030_REG_GPBR1);
+                       goto err_i2c;
+               }
+       }
+
+       platform_set_drvdata(pdev, iio_dev);
+       mutex_init(&madc->lock);
+
+       irq = platform_get_irq(pdev, 0);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                  twl4030_madc_threaded_irq_handler,
+                                  IRQF_TRIGGER_RISING, "twl4030_madc", madc);
+       if (ret) {
+               dev_err(&pdev->dev, "could not request irq\n");
+               goto err_i2c;
+       }
+       twl4030_madc = madc;
+
+       ret = iio_device_register(iio_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "could not register iio device\n");
+               goto err_i2c;
+       }
+
+       return 0;
+
+err_i2c:
+       twl4030_madc_set_current_generator(madc, 0, 0);
+err_current_generator:
+       twl4030_madc_set_power(madc, 0);
+       return ret;
+}
+
+static int twl4030_madc_remove(struct platform_device *pdev)
+{
+       struct iio_dev *iio_dev = platform_get_drvdata(pdev);
+       struct twl4030_madc_data *madc = iio_priv(iio_dev);
+
+       iio_device_unregister(iio_dev);
+
+       twl4030_madc_set_current_generator(madc, 0, 0);
+       twl4030_madc_set_power(madc, 0);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id twl_madc_of_match[] = {
+       { .compatible = "ti,twl4030-madc", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl_madc_of_match);
+#endif
+
+static struct platform_driver twl4030_madc_driver = {
+       .probe = twl4030_madc_probe,
+       .remove = twl4030_madc_remove,
+       .driver = {
+                  .name = "twl4030_madc",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(twl_madc_of_match),
+       },
+};
+
+module_platform_driver(twl4030_madc_driver);
+
+MODULE_DESCRIPTION("TWL4030 ADC driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("J Keerthy");
+MODULE_ALIAS("platform:twl4030_madc");
index 7dca1e6..841717a 100644 (file)
@@ -571,7 +571,7 @@ static int pm800_probe(struct i2c_client *client,
        ret = pm800_pages_init(chip);
        if (ret) {
                dev_err(&client->dev, "pm800_pages_init failed!\n");
-               goto err_page_init;
+               goto err_device_init;
        }
 
        ret = device_800_init(chip, pdata);
@@ -587,7 +587,6 @@ static int pm800_probe(struct i2c_client *client,
 
 err_device_init:
        pm800_pages_exit(chip);
-err_page_init:
 err_subchip_alloc:
        pm80x_deinit();
 out_init:
index c9b1f64..bcfc9e8 100644 (file)
@@ -1179,12 +1179,18 @@ static int pm860x_probe(struct i2c_client *client,
                chip->companion_addr = pdata->companion_addr;
                chip->companion = i2c_new_dummy(chip->client->adapter,
                                                chip->companion_addr);
+               if (!chip->companion) {
+                       dev_err(&client->dev,
+                               "Failed to allocate I2C companion device\n");
+                       return -ENODEV;
+               }
                chip->regmap_companion = regmap_init_i2c(chip->companion,
                                                        &pm860x_regmap_config);
                if (IS_ERR(chip->regmap_companion)) {
                        ret = PTR_ERR(chip->regmap_companion);
                        dev_err(&chip->companion->dev,
                                "Failed to allocate register map: %d\n", ret);
+                       i2c_unregister_device(chip->companion);
                        return ret;
                }
                i2c_set_clientdata(chip->companion, chip);
index 49bb445..3383412 100644 (file)
@@ -59,6 +59,14 @@ config MFD_AAT2870_CORE
          additional drivers must be enabled in order to use the
          functionality of the device.
 
+config MFD_BCM590XX
+       tristate "Broadcom BCM590xx PMUs"
+       select MFD_CORE
+       select REGMAP_I2C
+       depends on I2C
+       help
+         Support for the BCM590xx PMUs from Broadcom
+
 config MFD_CROS_EC
        tristate "ChromeOS Embedded Controller"
        select MFD_CORE
@@ -100,7 +108,7 @@ config PMIC_DA903X
        bool "Dialog Semiconductor DA9030/DA9034 PMIC Support"
        depends on I2C=y
        help
-         Say yes here to support for Dialog Semiconductor DA9030 (a.k.a
+         Say yes here to add support for Dialog Semiconductor DA9030 (a.k.a
          ARAVA) and DA9034 (a.k.a MICCO), these are Power Management IC
          usually found on PXA processors-based platforms. This includes
          the I2C driver and the core APIs _only_, you have to select
@@ -270,13 +278,18 @@ config MFD_KEMPLD
          device may provide functions like watchdog, GPIO, UART and I2C bus.
 
          The following modules are supported:
+               * COMe-bHL6
                * COMe-bIP#
                * COMe-bPC2 (ETXexpress-PC)
                * COMe-bSC# (ETXexpress-SC T#)
+               * COMe-cBT6
                * COMe-cCT6
                * COMe-cDC2 (microETXexpress-DC)
+               * COMe-cHL6
                * COMe-cPC2 (microETXexpress-PC)
+               * COMe-mBT10
                * COMe-mCT10
+               * COMe-mTT10 (nanoETXexpress-TT)
                * ETX-OH
 
          This driver can also be built as a module. If so, the module
@@ -322,9 +335,10 @@ config MFD_MAX14577
        depends on I2C=y
        select MFD_CORE
        select REGMAP_I2C
+       select REGMAP_IRQ
        select IRQ_DOMAIN
        help
-         Say yes here to support for Maxim Semiconductor MAX14577.
+         Say yes here to add support for Maxim Semiconductor MAX14577.
          This is a Micro-USB IC with Charger controls on chip.
          This driver provides common support for accessing the device;
          additional drivers must be enabled in order to use the functionality
@@ -337,7 +351,7 @@ config MFD_MAX77686
        select REGMAP_I2C
        select IRQ_DOMAIN
        help
-         Say yes here to support for Maxim Semiconductor MAX77686.
+         Say yes here to add support for Maxim Semiconductor MAX77686.
          This is a Power Management IC with RTC on chip.
          This driver provides common support for accessing the device;
          additional drivers must be enabled in order to use the functionality
@@ -349,7 +363,7 @@ config MFD_MAX77693
        select MFD_CORE
        select REGMAP_I2C
        help
-         Say yes here to support for Maxim Semiconductor MAX77693.
+         Say yes here to add support for Maxim Semiconductor MAX77693.
          This is a companion Power Management IC with Flash, Haptic, Charger,
          and MUIC(Micro USB Interface Controller) controls on chip.
          This driver provides common support for accessing the device;
@@ -363,7 +377,7 @@ config MFD_MAX8907
        select REGMAP_I2C
        select REGMAP_IRQ
        help
-         Say yes here to support for Maxim Semiconductor MAX8907. This is
+         Say yes here to add support for Maxim Semiconductor MAX8907. This is
          a Power Management IC. This driver provides common support for
          accessing the device; additional drivers must be enabled in order
          to use the functionality of the device.
@@ -373,7 +387,7 @@ config MFD_MAX8925
        depends on I2C=y
        select MFD_CORE
        help
-         Say yes here to support for Maxim Semiconductor MAX8925. This is
+         Say yes here to add support for Maxim Semiconductor MAX8925. This is
          a Power Management IC. This driver provides common support for
          accessing the device, additional drivers must be enabled in order
          to use the functionality of the device.
@@ -384,7 +398,7 @@ config MFD_MAX8997
        select MFD_CORE
        select IRQ_DOMAIN
        help
-         Say yes here to support for Maxim Semiconductor MAX8997/8966.
+         Say yes here to add support for Maxim Semiconductor MAX8997/8966.
          This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
          MUIC controls on chip.
          This driver provides common support for accessing the device;
@@ -397,7 +411,7 @@ config MFD_MAX8998
        select MFD_CORE
        select IRQ_DOMAIN
        help
-         Say yes here to support for Maxim Semiconductor MAX8998 and
+         Say yes here to add support for Maxim Semiconductor MAX8998 and
          National Semiconductor LP3974. This is a Power Management IC.
          This driver provides common support for accessing the device,
          additional drivers must be enabled in order to use the functionality
@@ -473,10 +487,11 @@ config MFD_PM8XXX
 
 config MFD_PM8921_CORE
        tristate "Qualcomm PM8921 PMIC chip"
-       depends on (ARCH_MSM || HEXAGON)
-       depends on BROKEN
+       depends on (ARM || HEXAGON)
+       select IRQ_DOMAIN
        select MFD_CORE
        select MFD_PM8XXX
+       select REGMAP
        help
          If you say yes to this option, support will be included for the
          built-in PM8921 PMIC chip.
@@ -487,16 +502,6 @@ config MFD_PM8921_CORE
          Say M here if you want to include support for PM8921 chip as a module.
          This will build a module called "pm8921-core".
 
-config MFD_PM8XXX_IRQ
-       bool "Qualcomm PM8xxx IRQ features"
-       depends on MFD_PM8XXX
-       default y if MFD_PM8XXX
-       help
-         This is the IRQ driver for Qualcomm PM 8xxx PMIC chips.
-
-         This is required to use certain other PM 8xxx features, such as GPIO
-         and MPP.
-
 config MFD_RDC321X
        tristate "RDC R-321x southbridge"
        select MFD_CORE
@@ -516,6 +521,16 @@ config MFD_RTSX_PCI
          types of memory cards, such as Memory Stick, Memory Stick Pro,
          Secure Digital and MultiMediaCard.
 
+config MFD_RTSX_USB
+       tristate "Realtek USB card reader"
+       depends on USB
+       select MFD_CORE
+       help
+         Select this option to get support for Realtek USB 2.0 card readers
+         including RTS5129, RTS5139, RTS5179 and RTS5170.
+         Realtek card reader supports access to many types of memory cards,
+         such as Memory Stick Pro, Secure Digital and MultiMediaCard.
+
 config MFD_RC5T583
        bool "Ricoh RC5T583 Power Management system device"
        depends on I2C=y
@@ -774,17 +789,6 @@ config MFD_PALMAS
          If you say yes here you get support for the Palmas
          series of PMIC chips from Texas Instruments.
 
-config MFD_TI_SSP
-       tristate "TI Sequencer Serial Port support"
-       depends on ARCH_DAVINCI_TNETV107X
-       select MFD_CORE
-       ---help---
-         Say Y here if you want support for the Sequencer Serial Port
-         in a Texas Instruments TNETV107X SoC.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ti-ssp.
-
 config TPS6105X
        tristate "TI TPS61050/61052 Boost Converters"
        depends on I2C
@@ -853,6 +857,22 @@ config MFD_TPS65217
          This driver can also be built as a module.  If so, the module
          will be called tps65217.
 
+config MFD_TPS65218
+       tristate "TI TPS65218 Power Management chips"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         If you say yes here you get support for the TPS65218 series of
+         Power Management chips.
+         These include voltage regulators, gpio and other features
+         that are often used in portable devices. Only regulator
+         component is currently supported.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65218.
+
 config MFD_TPS6586X
        bool "TI TPS6586x Power Management chips"
        depends on I2C=y
@@ -935,16 +955,6 @@ config TWL4030_CORE
          high speed USB OTG transceiver, an audio codec (on most
          versions) and many other features.
 
-config TWL4030_MADC
-       tristate "TI TWL4030 MADC"
-       depends on TWL4030_CORE
-       help
-       This driver provides support for triton TWL4030-MADC. The
-       driver supports both RT and SW conversion methods.
-
-       This driver can be built as a module. If so it will be
-       named twl4030-madc
-
 config TWL4030_POWER
        bool "TI TWL4030 power resources"
        depends on TWL4030_CORE && ARM
@@ -1193,9 +1203,6 @@ config MFD_STW481X
          in various ST Microelectronics and ST-Ericsson embedded
          Nomadik series.
 
-endmenu
-endif
-
 menu "Multimedia Capabilities Port drivers"
        depends on ARCH_SA1100
 
@@ -1226,3 +1233,6 @@ config VEXPRESS_CONFIG
        help
          Platform configuration infrastructure for the ARM Ltd.
          Versatile Express.
+
+endmenu
+endif
index 5aea5ef..2851275 100644 (file)
@@ -8,12 +8,14 @@ obj-$(CONFIG_MFD_88PM800)     += 88pm800.o 88pm80x.o
 obj-$(CONFIG_MFD_88PM805)      += 88pm805.o 88pm80x.o
 obj-$(CONFIG_MFD_SM501)                += sm501.o
 obj-$(CONFIG_MFD_ASIC3)                += asic3.o tmio_core.o
+obj-$(CONFIG_MFD_BCM590XX)     += bcm590xx.o
 obj-$(CONFIG_MFD_CROS_EC)      += cros_ec.o
 obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 
 rtsx_pci-objs                  := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
 obj-$(CONFIG_MFD_RTSX_PCI)     += rtsx_pci.o
+obj-$(CONFIG_MFD_RTSX_USB)     += rtsx_usb.o
 
 obj-$(CONFIG_HTC_EGPIO)                += htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)       += htc-pasic3.o
@@ -21,7 +23,6 @@ obj-$(CONFIG_HTC_I2CPLD)      += htc-i2cpld.o
 
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)   += davinci_voicecodec.o
 obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
-obj-$(CONFIG_MFD_TI_SSP)       += ti-ssp.o
 obj-$(CONFIG_MFD_TI_AM335X_TSCADC)     += ti_am335x_tscadc.o
 
 obj-$(CONFIG_MFD_STA2X11)      += sta2x11-mfd.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_TPS6105X)                += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
 obj-$(CONFIG_MFD_TPS65217)     += tps65217.o
+obj-$(CONFIG_MFD_TPS65218)     += tps65218.o
 obj-$(CONFIG_MFD_TPS65910)     += tps65910.o
 tps65912-objs                   := tps65912-core.o tps65912-irq.o
 obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
@@ -71,7 +73,6 @@ obj-$(CONFIG_MFD_TPS80031)    += tps80031.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
-obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_MFD_TWL4030_AUDIO)        += twl4030-audio.o
 obj-$(CONFIG_TWL6040_CORE)     += twl6040.o
@@ -150,7 +151,6 @@ obj-$(CONFIG_MFD_SI476X_CORE)       += si476x-core.o
 obj-$(CONFIG_MFD_CS5535)       += cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o ssbi.o
-obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
index 6250155..f495b8b 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index c71ff0a..39fa554 100644 (file)
@@ -277,6 +277,7 @@ static const struct regmap_range as3722_readable_ranges[] = {
        regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC_CONFIGURATION_REG),
        regmap_reg_range(AS3722_ASIC_ID1_REG, AS3722_ASIC_ID2_REG),
        regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG),
+       regmap_reg_range(AS3722_FUSE7_REG, AS3722_FUSE7_REG),
 };
 
 static const struct regmap_access_table as3722_readable_table = {
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
new file mode 100644 (file)
index 0000000..e9a33c7
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Broadcom BCM590xx PMU
+ *
+ * Copyright 2014 Linaro Limited
+ * Author: Matt Porter <mporter@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/mfd/bcm590xx.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static const struct mfd_cell bcm590xx_devs[] = {
+       {
+               .name = "bcm590xx-vregs",
+       },
+};
+
+static const struct regmap_config bcm590xx_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = BCM590XX_MAX_REGISTER,
+       .cache_type     = REGCACHE_RBTREE,
+};
+
+static int bcm590xx_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
+{
+       struct bcm590xx *bcm590xx;
+       int ret;
+
+       bcm590xx = devm_kzalloc(&i2c->dev, sizeof(*bcm590xx), GFP_KERNEL);
+       if (!bcm590xx)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, bcm590xx);
+       bcm590xx->dev = &i2c->dev;
+       bcm590xx->i2c_client = i2c;
+
+       bcm590xx->regmap = devm_regmap_init_i2c(i2c, &bcm590xx_regmap_config);
+       if (IS_ERR(bcm590xx->regmap)) {
+               ret = PTR_ERR(bcm590xx->regmap);
+               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mfd_add_devices(&i2c->dev, -1, bcm590xx_devs,
+                             ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
+       if (ret < 0)
+               dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret);
+
+       return ret;
+}
+
+static const struct of_device_id bcm590xx_of_match[] = {
+       { .compatible = "brcm,bcm59056" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, bcm590xx_of_match);
+
+static const struct i2c_device_id bcm590xx_i2c_id[] = {
+       { "bcm59056" },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, bcm590xx_i2c_id);
+
+static struct i2c_driver bcm590xx_i2c_driver = {
+       .driver = {
+                  .name = "bcm590xx",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(bcm590xx_of_match),
+       },
+       .probe = bcm590xx_i2c_probe,
+       .id_table = bcm590xx_i2c_id,
+};
+module_i2c_driver(bcm590xx_i2c_driver);
+
+MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
+MODULE_DESCRIPTION("BCM590xx multi-function driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bcm590xx");
index 17c1301..be91cb5 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/mfd/core.h>
 #include <linux/module.h>
 #include <linux/pci.h>
index 25838f1..e8af816 100644 (file)
@@ -279,6 +279,9 @@ static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
        case DA9052_EVENT_B_REG:
        case DA9052_EVENT_C_REG:
        case DA9052_EVENT_D_REG:
+       case DA9052_CONTROL_B_REG:
+       case DA9052_CONTROL_D_REG:
+       case DA9052_SUPPLY_REG:
        case DA9052_FAULTLOG_REG:
        case DA9052_CHG_TIME_REG:
        case DA9052_ADC_RES_L_REG:
index c319c4e..6da8ec8 100644 (file)
@@ -75,6 +75,7 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
                                           DA9052_PARK_REGISTER,
                                           &val);
                break;
+       case DA9053_BC:
        default:
                /*
                 * For other chips parking of I2C register
@@ -114,6 +115,7 @@ static const struct i2c_device_id da9052_i2c_id[] = {
        {"da9053-aa", DA9053_AA},
        {"da9053-ba", DA9053_BA},
        {"da9053-bb", DA9053_BB},
+       {"da9053-bc", DA9053_BC},
        {}
 };
 
@@ -121,8 +123,9 @@ static const struct i2c_device_id da9052_i2c_id[] = {
 static const struct of_device_id dialog_dt_ids[] = {
        { .compatible = "dlg,da9052", .data = &da9052_i2c_id[0] },
        { .compatible = "dlg,da9053-aa", .data = &da9052_i2c_id[1] },
-       { .compatible = "dlg,da9053-ab", .data = &da9052_i2c_id[2] },
+       { .compatible = "dlg,da9053-ba", .data = &da9052_i2c_id[2] },
        { .compatible = "dlg,da9053-bb", .data = &da9052_i2c_id[3] },
+       { .compatible = "dlg,da9053-bc", .data = &da9052_i2c_id[4] },
        { /* sentinel */ }
 };
 #endif
index 0680bcb..17666b4 100644 (file)
@@ -71,6 +71,7 @@ static struct spi_device_id da9052_spi_id[] = {
        {"da9053-aa", DA9053_AA},
        {"da9053-ba", DA9053_BA},
        {"da9053-bb", DA9053_BB},
+       {"da9053-bc", DA9053_BC},
        {}
 };
 
index 8103e43..d4d4c16 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/da9055/core.h>
 
@@ -66,6 +68,11 @@ static struct i2c_device_id da9055_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 
+static const struct of_device_id da9055_of_match[] = {
+       { .compatible = "dlg,da9055-pmic", },
+       { }
+};
+
 static struct i2c_driver da9055_i2c_driver = {
        .probe = da9055_i2c_probe,
        .remove = da9055_i2c_remove,
@@ -73,6 +80,7 @@ static struct i2c_driver da9055_i2c_driver = {
        .driver = {
                .name = "da9055-pmic",
                .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(da9055_of_match),
        },
 };
 
index 26937cd..e70ae31 100644 (file)
@@ -110,7 +110,7 @@ static const struct mfd_cell da9063_devs[] = {
 int da9063_device_init(struct da9063 *da9063, unsigned int irq)
 {
        struct da9063_pdata *pdata = da9063->dev->platform_data;
-       int model, revision;
+       int model, variant_id, variant_code;
        int ret;
 
        if (pdata) {
@@ -141,23 +141,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
                return -ENODEV;
        }
 
-       ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &revision);
+       ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &variant_id);
        if (ret < 0) {
-               dev_err(da9063->dev, "Cannot read chip revision id.\n");
+               dev_err(da9063->dev, "Cannot read chip variant id.\n");
                return -EIO;
        }
-       revision >>= DA9063_CHIP_VARIANT_SHIFT;
-       if (revision != 3) {
-               dev_err(da9063->dev, "Unknown chip revision: %d\n", revision);
+
+       variant_code = variant_id >> DA9063_CHIP_VARIANT_SHIFT;
+
+       dev_info(da9063->dev,
+                "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
+                model, variant_id);
+
+       if (variant_code != PMIC_DA9063_BB) {
+               dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
+                               variant_code);
                return -ENODEV;
        }
 
        da9063->model = model;
-       da9063->revision = revision;
-
-       dev_info(da9063->dev,
-                "Device detected (model-ID: 0x%02X  rev-ID: 0x%02X)\n",
-                model, revision);
+       da9063->variant_code = variant_code;
 
        ret = da9063_irq_init(da9063);
        if (ret) {
index 81b7d88..433f823 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
index d3e2327..0769260 100644 (file)
@@ -322,9 +322,12 @@ static int kempld_detect_device(struct kempld_device_data *pld)
                return -ENODEV;
        }
 
-       /* Release hardware mutex if aquired */
-       if (!(index_reg & KEMPLD_MUTEX_KEY))
+       /* Release hardware mutex if acquired */
+       if (!(index_reg & KEMPLD_MUTEX_KEY)) {
                iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+               /* PXT and COMe-cPC2 boards may require a second release */
+               iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
+       }
 
        mutex_unlock(&pld->lock);
 
@@ -437,6 +440,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
                },
                .driver_data = (void *)&kempld_platform_data_generic,
                .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CHL6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cHL6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
        }, {
                .ident = "CHR2",
                .matches = {
@@ -509,6 +520,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
                },
                .driver_data = (void *)&kempld_platform_data_generic,
                .callback = kempld_create_platform_device,
+       }, {
+               .ident = "CVV6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cBT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
        }, {
                .ident = "FRI2",
                .matches = {
@@ -532,6 +551,14 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
                },
                .driver_data = (void *)&kempld_platform_data_generic,
                .callback = kempld_create_platform_device,
+       }, {
+               .ident = "MVV1",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-mBT"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
        }, {
                .ident = "NTC1",
                .matches = {
index be93fa2..3f10ea3 100644 (file)
@@ -58,7 +58,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #define ACPIBASE_GPE_END       0x2f
 #define ACPIBASE_SMI_OFF       0x30
 #define ACPIBASE_SMI_END       0x33
+#define ACPIBASE_PMC_OFF       0x08
+#define ACPIBASE_PMC_END       0x0c
 #define ACPIBASE_TCO_OFF       0x60
 #define ACPIBASE_TCO_END       0x7f
-#define ACPICTRL               0x44
+#define ACPICTRL_PMCBASE       0x44
 
 #define ACPIBASE_GCS_OFF       0x3410
 #define ACPIBASE_GCS_END       0x3414
 #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i)
 #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)])
 
-struct lpc_ich_cfg {
-       int base;
-       int ctrl;
-       int save;
-};
-
 struct lpc_ich_priv {
        int chipset;
-       struct lpc_ich_cfg acpi;
-       struct lpc_ich_cfg gpio;
+
+       int abase;              /* ACPI base */
+       int actrl_pbase;        /* ACPI control or PMC base */
+       int gbase;              /* GPIO base */
+       int gctrl;              /* GPIO control */
+
+       int abase_save;         /* Cached ACPI base value */
+       int actrl_pbase_save;           /* Cached ACPI control or PMC base value */
+       int gctrl_save;         /* Cached GPIO control value */
 };
 
 static struct resource wdt_ich_res[] = {
@@ -111,7 +113,7 @@ static struct resource wdt_ich_res[] = {
        {
                .flags = IORESOURCE_IO,
        },
-       /* GCS */
+       /* GCS or PMC */
        {
                .flags = IORESOURCE_MEM,
        },
@@ -211,6 +213,7 @@ enum lpc_chipsets {
        LPC_LPT_LP,     /* Lynx Point-LP */
        LPC_WBG,        /* Wellsburg */
        LPC_AVN,        /* Avoton SoC */
+       LPC_BAYTRAIL,   /* Bay Trail SoC */
        LPC_COLETO,     /* Coleto Creek */
        LPC_WPT_LP,     /* Wildcat Point-LP */
 };
@@ -303,6 +306,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
        [LPC_NM10] = {
                .name = "NM10",
                .iTCO_version = 2,
+               .gpio_version = ICH_V7_GPIO,
        },
        [LPC_ICH8] = {
                .name = "ICH8 or ICH8R",
@@ -499,7 +503,12 @@ static struct lpc_ich_info lpc_chipset_info[] = {
        },
        [LPC_AVN] = {
                .name = "Avoton SoC",
-               .iTCO_version = 1,
+               .iTCO_version = 3,
+               .gpio_version = AVOTON_GPIO,
+       },
+       [LPC_BAYTRAIL] = {
+               .name = "Bay Trail SoC",
+               .iTCO_version = 3,
        },
        [LPC_COLETO] = {
                .name = "Coleto Creek",
@@ -726,6 +735,7 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
        { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
        { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
        { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
        { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP},
@@ -742,14 +752,20 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev)
 {
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
 
-       if (priv->acpi.save >= 0) {
-               pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save);
-               priv->acpi.save = -1;
+       if (priv->abase_save >= 0) {
+               pci_write_config_byte(dev, priv->abase, priv->abase_save);
+               priv->abase_save = -1;
+       }
+
+       if (priv->actrl_pbase_save >= 0) {
+               pci_write_config_byte(dev, priv->actrl_pbase,
+                       priv->actrl_pbase_save);
+               priv->actrl_pbase_save = -1;
        }
 
-       if (priv->gpio.save >= 0) {
-               pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save);
-               priv->gpio.save = -1;
+       if (priv->gctrl_save >= 0) {
+               pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save);
+               priv->gctrl_save = -1;
        }
 }
 
@@ -758,9 +774,26 @@ static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
        u8 reg_save;
 
-       pci_read_config_byte(dev, priv->acpi.ctrl, &reg_save);
-       pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10);
-       priv->acpi.save = reg_save;
+       switch (lpc_chipset_info[priv->chipset].iTCO_version) {
+       case 3:
+               /*
+                * Some chipsets (eg Avoton) enable the ACPI space in the
+                * ACPI BASE register.
+                */
+               pci_read_config_byte(dev, priv->abase, &reg_save);
+               pci_write_config_byte(dev, priv->abase, reg_save | 0x2);
+               priv->abase_save = reg_save;
+               break;
+       default:
+               /*
+                * Most chipsets enable the ACPI space in the ACPI control
+                * register.
+                */
+               pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
+               pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80);
+               priv->actrl_pbase_save = reg_save;
+               break;
+       }
 }
 
 static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
@@ -768,9 +801,20 @@ static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
        u8 reg_save;
 
-       pci_read_config_byte(dev, priv->gpio.ctrl, &reg_save);
-       pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10);
-       priv->gpio.save = reg_save;
+       pci_read_config_byte(dev, priv->gctrl, &reg_save);
+       pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10);
+       priv->gctrl_save = reg_save;
+}
+
+static void lpc_ich_enable_pmc_space(struct pci_dev *dev)
+{
+       struct lpc_ich_priv *priv = pci_get_drvdata(dev);
+       u8 reg_save;
+
+       pci_read_config_byte(dev, priv->actrl_pbase, &reg_save);
+       pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2);
+
+       priv->actrl_pbase_save = reg_save;
 }
 
 static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell)
@@ -815,7 +859,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
        struct resource *res;
 
        /* Setup power management base register */
-       pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
+       pci_read_config_dword(dev, priv->abase, &base_addr_cfg);
        base_addr = base_addr_cfg & 0x0000ff80;
        if (!base_addr) {
                dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
@@ -841,7 +885,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
 
 gpe0_done:
        /* Setup GPIO base register */
-       pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg);
+       pci_read_config_dword(dev, priv->gbase, &base_addr_cfg);
        base_addr = base_addr_cfg & 0x0000ff80;
        if (!base_addr) {
                dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n");
@@ -891,7 +935,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
        struct resource *res;
 
        /* Setup power management base register */
-       pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
+       pci_read_config_dword(dev, priv->abase, &base_addr_cfg);
        base_addr = base_addr_cfg & 0x0000ff80;
        if (!base_addr) {
                dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
@@ -910,14 +954,20 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
        lpc_ich_enable_acpi_space(dev);
 
        /*
+        * iTCO v2:
         * Get the Memory-Mapped GCS register. To get access to it
         * we have to read RCBA from PCI Config space 0xf0 and use
         * it as base. GCS = RCBA + ICH6_GCS(0x3410).
+        *
+        * iTCO v3:
+        * Get the Power Management Configuration register.  To get access
+        * to it we have to read the PMC BASE from config space and address
+        * the register at offset 0x8.
         */
        if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
                /* Don't register iomem for TCO ver 1 */
                lpc_ich_cells[LPC_WDT].num_resources--;
-       } else {
+       } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) {
                pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
                base_addr = base_addr_cfg & 0xffffc000;
                if (!(base_addr_cfg & 1)) {
@@ -926,9 +976,17 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
                        ret = -ENODEV;
                        goto wdt_done;
                }
-               res = wdt_mem_res(ICH_RES_MEM_GCS);
+               res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
                res->start = base_addr + ACPIBASE_GCS_OFF;
                res->end = base_addr + ACPIBASE_GCS_END;
+       } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) {
+               lpc_ich_enable_pmc_space(dev);
+               pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg);
+               base_addr = base_addr_cfg & 0xfffffe00;
+
+               res = wdt_mem_res(ICH_RES_MEM_GCS_PMC);
+               res->start = base_addr + ACPIBASE_PMC_OFF;
+               res->end = base_addr + ACPIBASE_PMC_END;
        }
 
        lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]);
@@ -952,28 +1010,35 @@ static int lpc_ich_probe(struct pci_dev *dev,
                return -ENOMEM;
 
        priv->chipset = id->driver_data;
-       priv->acpi.save = -1;
-       priv->acpi.base = ACPIBASE;
-       priv->acpi.ctrl = ACPICTRL;
 
-       priv->gpio.save = -1;
+       priv->actrl_pbase_save = -1;
+       priv->abase_save = -1;
+
+       priv->abase = ACPIBASE;
+       priv->actrl_pbase = ACPICTRL_PMCBASE;
+
+       priv->gctrl_save = -1;
        if (priv->chipset <= LPC_ICH5) {
-               priv->gpio.base = GPIOBASE_ICH0;
-               priv->gpio.ctrl = GPIOCTRL_ICH0;
+               priv->gbase = GPIOBASE_ICH0;
+               priv->gctrl = GPIOCTRL_ICH0;
        } else {
-               priv->gpio.base = GPIOBASE_ICH6;
-               priv->gpio.ctrl = GPIOCTRL_ICH6;
+               priv->gbase = GPIOBASE_ICH6;
+               priv->gctrl = GPIOCTRL_ICH6;
        }
 
        pci_set_drvdata(dev, priv);
 
-       ret = lpc_ich_init_wdt(dev);
-       if (!ret)
-               cell_added = true;
+       if (lpc_chipset_info[priv->chipset].iTCO_version) {
+               ret = lpc_ich_init_wdt(dev);
+               if (!ret)
+                       cell_added = true;
+       }
 
-       ret = lpc_ich_init_gpio(dev);
-       if (!ret)
-               cell_added = true;
+       if (lpc_chipset_info[priv->chipset].gpio_version) {
+               ret = lpc_ich_init_gpio(dev);
+               if (!ret)
+                       cell_added = true;
+       }
 
        /*
         * We only care if at least one or none of the cells registered
index 3bb05c0..4ee7550 100644 (file)
@@ -23,7 +23,6 @@
  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
index 71aa14a..5f13cef 100644 (file)
@@ -18,6 +18,7 @@
  * This driver is based on max8997.c
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max14577-private.h>
 
 static struct mfd_cell max14577_devs[] = {
-       { .name = "max14577-muic", },
+       {
+               .name = "max14577-muic",
+               .of_compatible = "maxim,max14577-muic",
+       },
        {
                .name = "max14577-regulator",
                .of_compatible = "maxim,max14577-regulator",
index f53d582..e5fce76 100644 (file)
@@ -121,6 +121,10 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
                dev_info(max77686->dev, "device found\n");
 
        max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+       if (!max77686->rtc) {
+               dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n");
+               return -ENODEV;
+       }
        i2c_set_clientdata(max77686->rtc, max77686);
 
        max77686_irq_init(max77686);
index e085998..c5535f0 100644 (file)
@@ -148,9 +148,18 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                dev_info(max77693->dev, "device ID: 0x%x\n", reg_data);
 
        max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+       if (!max77693->muic) {
+               dev_err(max77693->dev, "Failed to allocate I2C device for MUIC\n");
+               return -ENODEV;
+       }
        i2c_set_clientdata(max77693->muic, max77693);
 
        max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+       if (!max77693->haptic) {
+               dev_err(max77693->dev, "Failed to allocate I2C device for Haptic\n");
+               ret = -ENODEV;
+               goto err_i2c_haptic;
+       }
        i2c_set_clientdata(max77693->haptic, max77693);
 
        /*
@@ -184,8 +193,9 @@ err_mfd:
        max77693_irq_exit(max77693);
 err_irq:
 err_regmap_muic:
-       i2c_unregister_device(max77693->muic);
        i2c_unregister_device(max77693->haptic);
+err_i2c_haptic:
+       i2c_unregister_device(max77693->muic);
        return ret;
 }
 
index 176aa26..a83eed5 100644 (file)
@@ -181,9 +181,18 @@ static int max8925_probe(struct i2c_client *client,
        mutex_init(&chip->io_lock);
 
        chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
+       if (!chip->rtc) {
+               dev_err(chip->dev, "Failed to allocate I2C device for RTC\n");
+               return -ENODEV;
+       }
        i2c_set_clientdata(chip->rtc, chip);
 
        chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
+       if (!chip->adc) {
+               dev_err(chip->dev, "Failed to allocate I2C device for ADC\n");
+               i2c_unregister_device(chip->rtc);
+               return -ENODEV;
+       }
        i2c_set_clientdata(chip->adc, chip);
 
        device_init_wakeup(&client->dev, 1);
index 5adede0..8cf7a01 100644 (file)
@@ -208,10 +208,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
        mutex_init(&max8997->iolock);
 
        max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+       if (!max8997->rtc) {
+               dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n");
+               return -ENODEV;
+       }
        i2c_set_clientdata(max8997->rtc, max8997);
+
        max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+       if (!max8997->haptic) {
+               dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n");
+               ret = -ENODEV;
+               goto err_i2c_haptic;
+       }
        i2c_set_clientdata(max8997->haptic, max8997);
+
        max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+       if (!max8997->muic) {
+               dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n");
+               ret = -ENODEV;
+               goto err_i2c_muic;
+       }
        i2c_set_clientdata(max8997->muic, max8997);
 
        pm_runtime_set_active(max8997->dev);
@@ -239,7 +255,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 err_mfd:
        mfd_remove_devices(max8997->dev);
        i2c_unregister_device(max8997->muic);
+err_i2c_muic:
        i2c_unregister_device(max8997->haptic);
+err_i2c_haptic:
        i2c_unregister_device(max8997->rtc);
        return ret;
 }
index 5d5e186..592db06 100644 (file)
@@ -215,6 +215,10 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
        mutex_init(&max8998->iolock);
 
        max8998->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
+       if (!max8998->rtc) {
+               dev_err(&i2c->dev, "Failed to allocate I2C device for RTC\n");
+               return -ENODEV;
+       }
        i2c_set_clientdata(max8998->rtc, max8998);
 
        max8998_irq_init(max8998);
index 38ab678..702925e 100644 (file)
@@ -140,6 +140,11 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
 
        mc13xxx->irq = spi->irq;
 
+       spi->max_speed_hz = spi->max_speed_hz ? : 26000000;
+       ret = spi_setup(spi);
+       if (ret)
+               return ret;
+
        mc13xxx->regmap = devm_regmap_init(&spi->dev, &regmap_mc13xxx_bus,
                                           &spi->dev,
                                           &mc13xxx_regmap_spi_config);
index 41c31b3..29d7698 100644 (file)
@@ -12,7 +12,6 @@
  *  MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
  */
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
index 90b630c..651e249 100644 (file)
@@ -665,55 +665,78 @@ static int usbhs_omap_probe(struct platform_device *pdev)
                goto err_mem;
        }
 
-       need_logic_fck = false;
+       /* Set all clocks as invalid to begin with */
+       omap->ehci_logic_fck = ERR_PTR(-ENODEV);
+       omap->init_60m_fclk = ERR_PTR(-ENODEV);
+       omap->utmi_p1_gfclk = ERR_PTR(-ENODEV);
+       omap->utmi_p2_gfclk = ERR_PTR(-ENODEV);
+       omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV);
+       omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV);
+
        for (i = 0; i < omap->nports; i++) {
-               if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
-                       is_ehci_hsic_mode(i))
-                               need_logic_fck |= true;
+               omap->utmi_clk[i] = ERR_PTR(-ENODEV);
+               omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
+               omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
        }
 
-       omap->ehci_logic_fck = ERR_PTR(-EINVAL);
-       if (need_logic_fck) {
-               omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck");
-               if (IS_ERR(omap->ehci_logic_fck)) {
-                       ret = PTR_ERR(omap->ehci_logic_fck);
-                       dev_dbg(dev, "ehci_logic_fck failed:%d\n", ret);
+       /* for OMAP3 i.e. USBHS REV1 */
+       if (omap->usbhs_rev == OMAP_USBHS_REV1) {
+               need_logic_fck = false;
+               for (i = 0; i < omap->nports; i++) {
+                       if (is_ehci_phy_mode(pdata->port_mode[i]) ||
+                           is_ehci_tll_mode(pdata->port_mode[i]) ||
+                           is_ehci_hsic_mode(pdata->port_mode[i]))
+
+                               need_logic_fck |= true;
                }
+
+               if (need_logic_fck) {
+                       omap->ehci_logic_fck = devm_clk_get(dev,
+                                                           "usbhost_120m_fck");
+                       if (IS_ERR(omap->ehci_logic_fck)) {
+                               ret = PTR_ERR(omap->ehci_logic_fck);
+                               dev_err(dev, "usbhost_120m_fck failed:%d\n",
+                                       ret);
+                               goto err_mem;
+                       }
+               }
+               goto initialize;
        }
 
-       omap->utmi_p1_gfclk = clk_get(dev, "utmi_p1_gfclk");
+       /* for OMAP4+ i.e. USBHS REV2+ */
+       omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk");
        if (IS_ERR(omap->utmi_p1_gfclk)) {
                ret = PTR_ERR(omap->utmi_p1_gfclk);
                dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
-               goto err_p1_gfclk;
+               goto err_mem;
        }
 
-       omap->utmi_p2_gfclk = clk_get(dev, "utmi_p2_gfclk");
+       omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk");
        if (IS_ERR(omap->utmi_p2_gfclk)) {
                ret = PTR_ERR(omap->utmi_p2_gfclk);
                dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
-               goto err_p2_gfclk;
+               goto err_mem;
        }
 
-       omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
+       omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1");
        if (IS_ERR(omap->xclk60mhsp1_ck)) {
                ret = PTR_ERR(omap->xclk60mhsp1_ck);
-               dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
-               goto err_xclk60mhsp1;
+               dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret);
+               goto err_mem;
        }
 
-       omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
+       omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2");
        if (IS_ERR(omap->xclk60mhsp2_ck)) {
                ret = PTR_ERR(omap->xclk60mhsp2_ck);
-               dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
-               goto err_xclk60mhsp2;
+               dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret);
+               goto err_mem;
        }
 
-       omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
+       omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int");
        if (IS_ERR(omap->init_60m_fclk)) {
                ret = PTR_ERR(omap->init_60m_fclk);
-               dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
-               goto err_init60m;
+               dev_err(dev, "refclk_60m_int failed error:%d\n", ret);
+               goto err_mem;
        }
 
        for (i = 0; i < omap->nports; i++) {
@@ -727,55 +750,72 @@ static int usbhs_omap_probe(struct platform_device *pdev)
                 * platforms have all clocks and we can function without
                 * them
                 */
-               omap->utmi_clk[i] = clk_get(dev, clkname);
-               if (IS_ERR(omap->utmi_clk[i]))
-                       dev_dbg(dev, "Failed to get clock : %s : %ld\n",
-                               clkname, PTR_ERR(omap->utmi_clk[i]));
+               omap->utmi_clk[i] = devm_clk_get(dev, clkname);
+               if (IS_ERR(omap->utmi_clk[i])) {
+                       ret = PTR_ERR(omap->utmi_clk[i]);
+                       dev_err(dev, "Failed to get clock : %s : %d\n",
+                               clkname, ret);
+                       goto err_mem;
+               }
 
                snprintf(clkname, sizeof(clkname),
                                "usb_host_hs_hsic480m_p%d_clk", i + 1);
-               omap->hsic480m_clk[i] = clk_get(dev, clkname);
-               if (IS_ERR(omap->hsic480m_clk[i]))
-                       dev_dbg(dev, "Failed to get clock : %s : %ld\n",
-                               clkname, PTR_ERR(omap->hsic480m_clk[i]));
+               omap->hsic480m_clk[i] = devm_clk_get(dev, clkname);
+               if (IS_ERR(omap->hsic480m_clk[i])) {
+                       ret = PTR_ERR(omap->hsic480m_clk[i]);
+                       dev_err(dev, "Failed to get clock : %s : %d\n",
+                               clkname, ret);
+                       goto err_mem;
+               }
 
                snprintf(clkname, sizeof(clkname),
                                "usb_host_hs_hsic60m_p%d_clk", i + 1);
-               omap->hsic60m_clk[i] = clk_get(dev, clkname);
-               if (IS_ERR(omap->hsic60m_clk[i]))
-                       dev_dbg(dev, "Failed to get clock : %s : %ld\n",
-                               clkname, PTR_ERR(omap->hsic60m_clk[i]));
+               omap->hsic60m_clk[i] = devm_clk_get(dev, clkname);
+               if (IS_ERR(omap->hsic60m_clk[i])) {
+                       ret = PTR_ERR(omap->hsic60m_clk[i]);
+                       dev_err(dev, "Failed to get clock : %s : %d\n",
+                               clkname, ret);
+                       goto err_mem;
+               }
        }
 
        if (is_ehci_phy_mode(pdata->port_mode[0])) {
-               /* for OMAP3, clk_set_parent fails */
                ret = clk_set_parent(omap->utmi_p1_gfclk,
                                        omap->xclk60mhsp1_ck);
-               if (ret != 0)
-                       dev_dbg(dev, "xclk60mhsp1_ck set parent failed: %d\n",
-                                       ret);
+               if (ret != 0) {
+                       dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n",
+                               ret);
+                       goto err_mem;
+               }
        } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
                ret = clk_set_parent(omap->utmi_p1_gfclk,
                                        omap->init_60m_fclk);
-               if (ret != 0)
-                       dev_dbg(dev, "P0 init_60m_fclk set parent failed: %d\n",
-                                       ret);
+               if (ret != 0) {
+                       dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n",
+                               ret);
+                       goto err_mem;
+               }
        }
 
        if (is_ehci_phy_mode(pdata->port_mode[1])) {
                ret = clk_set_parent(omap->utmi_p2_gfclk,
                                        omap->xclk60mhsp2_ck);
-               if (ret != 0)
-                       dev_dbg(dev, "xclk60mhsp2_ck set parent failed: %d\n",
-                                       ret);
+               if (ret != 0) {
+                       dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n",
+                               ret);
+                       goto err_mem;
+               }
        } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
                ret = clk_set_parent(omap->utmi_p2_gfclk,
                                                omap->init_60m_fclk);
-               if (ret != 0)
-                       dev_dbg(dev, "P1 init_60m_fclk set parent failed: %d\n",
-                                       ret);
+               if (ret != 0) {
+                       dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n",
+                               ret);
+                       goto err_mem;
+               }
        }
 
+initialize:
        omap_usbhs_init(dev);
 
        if (dev->of_node) {
@@ -784,7 +824,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
 
                if (ret) {
                        dev_err(dev, "Failed to create DT children: %d\n", ret);
-                       goto err_alloc;
+                       goto err_mem;
                }
 
        } else {
@@ -792,40 +832,12 @@ static int usbhs_omap_probe(struct platform_device *pdev)
                if (ret) {
                        dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
                                                ret);
-                       goto err_alloc;
+                       goto err_mem;
                }
        }
 
        return 0;
 
-err_alloc:
-       for (i = 0; i < omap->nports; i++) {
-               if (!IS_ERR(omap->utmi_clk[i]))
-                       clk_put(omap->utmi_clk[i]);
-               if (!IS_ERR(omap->hsic60m_clk[i]))
-                       clk_put(omap->hsic60m_clk[i]);
-               if (!IS_ERR(omap->hsic480m_clk[i]))
-                       clk_put(omap->hsic480m_clk[i]);
-       }
-
-       clk_put(omap->init_60m_fclk);
-
-err_init60m:
-       clk_put(omap->xclk60mhsp2_ck);
-
-err_xclk60mhsp2:
-       clk_put(omap->xclk60mhsp1_ck);
-
-err_xclk60mhsp1:
-       clk_put(omap->utmi_p2_gfclk);
-
-err_p2_gfclk:
-       clk_put(omap->utmi_p1_gfclk);
-
-err_p1_gfclk:
-       if (!IS_ERR(omap->ehci_logic_fck))
-               clk_put(omap->ehci_logic_fck);
-
 err_mem:
        pm_runtime_disable(dev);
 
@@ -847,27 +859,6 @@ static int usbhs_omap_remove_child(struct device *dev, void *data)
  */
 static int usbhs_omap_remove(struct platform_device *pdev)
 {
-       struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < omap->nports; i++) {
-               if (!IS_ERR(omap->utmi_clk[i]))
-                       clk_put(omap->utmi_clk[i]);
-               if (!IS_ERR(omap->hsic60m_clk[i]))
-                       clk_put(omap->hsic60m_clk[i]);
-               if (!IS_ERR(omap->hsic480m_clk[i]))
-                       clk_put(omap->hsic480m_clk[i]);
-       }
-
-       clk_put(omap->init_60m_fclk);
-       clk_put(omap->utmi_p1_gfclk);
-       clk_put(omap->utmi_p2_gfclk);
-       clk_put(omap->xclk60mhsp2_ck);
-       clk_put(omap->xclk60mhsp1_ck);
-
-       if (!IS_ERR(omap->ehci_logic_fck))
-               clk_put(omap->ehci_logic_fck);
-
        pm_runtime_disable(&pdev->dev);
 
        /* remove children */
index 5ee50f7..532eaca 100644 (file)
@@ -252,7 +252,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
                break;
        }
 
-       tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]),
+       tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch,
                                                GFP_KERNEL);
        if (!tll->ch_clk) {
                ret = -ENOMEM;
index b8941a5..c1984b0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/completion.h>
index 484fe66..b97a971 100644 (file)
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/ssbi.h>
+#include <linux/regmap.h>
+#include <linux/of_platform.h>
 #include <linux/mfd/core.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/core.h>
 
+#define        SSBI_REG_ADDR_IRQ_BASE          0x1BB
+
+#define        SSBI_REG_ADDR_IRQ_ROOT          (SSBI_REG_ADDR_IRQ_BASE + 0)
+#define        SSBI_REG_ADDR_IRQ_M_STATUS1     (SSBI_REG_ADDR_IRQ_BASE + 1)
+#define        SSBI_REG_ADDR_IRQ_M_STATUS2     (SSBI_REG_ADDR_IRQ_BASE + 2)
+#define        SSBI_REG_ADDR_IRQ_M_STATUS3     (SSBI_REG_ADDR_IRQ_BASE + 3)
+#define        SSBI_REG_ADDR_IRQ_M_STATUS4     (SSBI_REG_ADDR_IRQ_BASE + 4)
+#define        SSBI_REG_ADDR_IRQ_BLK_SEL       (SSBI_REG_ADDR_IRQ_BASE + 5)
+#define        SSBI_REG_ADDR_IRQ_IT_STATUS     (SSBI_REG_ADDR_IRQ_BASE + 6)
+#define        SSBI_REG_ADDR_IRQ_CONFIG        (SSBI_REG_ADDR_IRQ_BASE + 7)
+#define        SSBI_REG_ADDR_IRQ_RT_STATUS     (SSBI_REG_ADDR_IRQ_BASE + 8)
+
+#define        PM_IRQF_LVL_SEL                 0x01    /* level select */
+#define        PM_IRQF_MASK_FE                 0x02    /* mask falling edge */
+#define        PM_IRQF_MASK_RE                 0x04    /* mask rising edge */
+#define        PM_IRQF_CLR                     0x08    /* clear interrupt */
+#define        PM_IRQF_BITS_MASK               0x70
+#define        PM_IRQF_BITS_SHIFT              4
+#define        PM_IRQF_WRITE                   0x80
+
+#define        PM_IRQF_MASK_ALL                (PM_IRQF_MASK_FE | \
+                                       PM_IRQF_MASK_RE)
+
 #define REG_HWREV              0x002  /* PMIC4 revision */
 #define REG_HWREV_2            0x0E8  /* PMIC4 revision 2 */
 
+#define PM8921_NR_IRQS         256
+
+struct pm_irq_chip {
+       struct device           *dev;
+       struct regmap           *regmap;
+       spinlock_t              pm_irq_lock;
+       struct irq_domain       *irqdomain;
+       unsigned int            num_irqs;
+       unsigned int            num_blocks;
+       unsigned int            num_masters;
+       u8                      config[0];
+};
+
 struct pm8921 {
        struct device                   *dev;
        struct pm_irq_chip              *irq_chip;
 };
 
+static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
+                                unsigned int *ip)
+{
+       int     rc;
+
+       spin_lock(&chip->pm_irq_lock);
+       rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+       if (rc) {
+               pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+               goto bail;
+       }
+
+       rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+       if (rc)
+               pr_err("Failed Reading Status rc=%d\n", rc);
+bail:
+       spin_unlock(&chip->pm_irq_lock);
+       return rc;
+}
+
+static int
+pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
+{
+       int     rc;
+
+       spin_lock(&chip->pm_irq_lock);
+       rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+       if (rc) {
+               pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+               goto bail;
+       }
+
+       cp |= PM_IRQF_WRITE;
+       rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+       if (rc)
+               pr_err("Failed Configuring IRQ rc=%d\n", rc);
+bail:
+       spin_unlock(&chip->pm_irq_lock);
+       return rc;
+}
+
+static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
+{
+       int pmirq, irq, i, ret = 0;
+       unsigned int bits;
+
+       ret = pm8xxx_read_block_irq(chip, block, &bits);
+       if (ret) {
+               pr_err("Failed reading %d block ret=%d", block, ret);
+               return ret;
+       }
+       if (!bits) {
+               pr_err("block bit set in master but no irqs: %d", block);
+               return 0;
+       }
+
+       /* Check IRQ bits */
+       for (i = 0; i < 8; i++) {
+               if (bits & (1 << i)) {
+                       pmirq = block * 8 + i;
+                       irq = irq_find_mapping(chip->irqdomain, pmirq);
+                       generic_handle_irq(irq);
+               }
+       }
+       return 0;
+}
+
+static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
+{
+       unsigned int blockbits;
+       int block_number, i, ret = 0;
+
+       ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
+                         &blockbits);
+       if (ret) {
+               pr_err("Failed to read master %d ret=%d\n", master, ret);
+               return ret;
+       }
+       if (!blockbits) {
+               pr_err("master bit set in root but no blocks: %d", master);
+               return 0;
+       }
+
+       for (i = 0; i < 8; i++)
+               if (blockbits & (1 << i)) {
+                       block_number = master * 8 + i;  /* block # */
+                       ret |= pm8xxx_irq_block_handler(chip, block_number);
+               }
+       return ret;
+}
+
+static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+       struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+       unsigned int root;
+       int     i, ret, masters = 0;
+
+       chained_irq_enter(irq_chip, desc);
+
+       ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
+       if (ret) {
+               pr_err("Can't read root status ret=%d\n", ret);
+               return;
+       }
+
+       /* on pm8xxx series masters start from bit 1 of the root */
+       masters = root >> 1;
+
+       /* Read allowed masters for blocks. */
+       for (i = 0; i < chip->num_masters; i++)
+               if (masters & (1 << i))
+                       pm8xxx_irq_master_handler(chip, i);
+
+       chained_irq_exit(irq_chip, desc);
+}
+
+static void pm8xxx_irq_mask_ack(struct irq_data *d)
+{
+       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int pmirq = irqd_to_hwirq(d);
+       int     irq_bit;
+       u8      block, config;
+
+       block = pmirq / 8;
+       irq_bit = pmirq % 8;
+
+       config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
+       pm8xxx_config_irq(chip, block, config);
+}
+
+static void pm8xxx_irq_unmask(struct irq_data *d)
+{
+       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int pmirq = irqd_to_hwirq(d);
+       int     irq_bit;
+       u8      block, config;
+
+       block = pmirq / 8;
+       irq_bit = pmirq % 8;
+
+       config = chip->config[pmirq];
+       pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int pmirq = irqd_to_hwirq(d);
+       int irq_bit;
+       u8 block, config;
+
+       block = pmirq / 8;
+       irq_bit  = pmirq % 8;
+
+       chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
+                                                       | PM_IRQF_MASK_ALL;
+       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+               if (flow_type & IRQF_TRIGGER_RISING)
+                       chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+               if (flow_type & IRQF_TRIGGER_FALLING)
+                       chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+       } else {
+               chip->config[pmirq] |= PM_IRQF_LVL_SEL;
+
+               if (flow_type & IRQF_TRIGGER_HIGH)
+                       chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+               else
+                       chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+       }
+
+       config = chip->config[pmirq] | PM_IRQF_CLR;
+       return pm8xxx_config_irq(chip, block, config);
+}
+
+static struct irq_chip pm8xxx_irq_chip = {
+       .name           = "pm8xxx",
+       .irq_mask_ack   = pm8xxx_irq_mask_ack,
+       .irq_unmask     = pm8xxx_irq_unmask,
+       .irq_set_type   = pm8xxx_irq_set_type,
+       .flags          = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+/**
+ * pm8xxx_get_irq_stat - get the status of the irq line
+ * @chip: pointer to identify a pmic irq controller
+ * @irq: the irq number
+ *
+ * The pm8xxx gpio and mpp rely on the interrupt block to read
+ * the values on their pins. This function is to facilitate reading
+ * the status of a gpio or an mpp line. The caller has to convert the
+ * gpio number to irq number.
+ *
+ * RETURNS:
+ * an int indicating the value read on that line
+ */
+static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
+{
+       int pmirq, rc;
+       unsigned int  block, bits, bit;
+       unsigned long flags;
+       struct irq_data *irq_data = irq_get_irq_data(irq);
+
+       pmirq = irq_data->hwirq;
+
+       block = pmirq / 8;
+       bit = pmirq % 8;
+
+       spin_lock_irqsave(&chip->pm_irq_lock, flags);
+
+       rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+       if (rc) {
+               pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
+                       irq, pmirq, block, rc);
+               goto bail_out;
+       }
+
+       rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+       if (rc) {
+               pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
+                       irq, pmirq, block, rc);
+               goto bail_out;
+       }
+
+       rc = (bits & (1 << bit)) ? 1 : 0;
+
+bail_out:
+       spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
+
+       return rc;
+}
+
+static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
+                                  irq_hw_number_t hwirq)
+{
+       struct pm_irq_chip *chip = d->host_data;
+
+       irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
+       irq_set_chip_data(irq, chip);
+#ifdef CONFIG_ARM
+       set_irq_flags(irq, IRQF_VALID);
+#else
+       irq_set_noprobe(irq);
+#endif
+       return 0;
+}
+
+static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
+       .xlate = irq_domain_xlate_twocell,
+       .map = pm8xxx_irq_domain_map,
+};
+
 static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
 {
        const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
@@ -81,42 +374,35 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
        .pmic_read_irq_stat     = pm8921_read_irq_stat,
 };
 
-static int pm8921_add_subdevices(const struct pm8921_platform_data
-                                          *pdata,
-                                          struct pm8921 *pmic,
-                                          u32 rev)
-{
-       int ret = 0, irq_base = 0;
-       struct pm_irq_chip *irq_chip;
-
-       if (pdata->irq_pdata) {
-               pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
-               pdata->irq_pdata->irq_cdata.rev = rev;
-               irq_base = pdata->irq_pdata->irq_base;
-               irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+static const struct regmap_config ssbi_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .max_register = 0x3ff,
+       .fast_io = true,
+       .reg_read = ssbi_reg_read,
+       .reg_write = ssbi_reg_write
+};
 
-               if (IS_ERR(irq_chip)) {
-                       pr_err("Failed to init interrupts ret=%ld\n",
-                                       PTR_ERR(irq_chip));
-                       return PTR_ERR(irq_chip);
-               }
-               pmic->irq_chip = irq_chip;
-       }
-       return ret;
-}
+static const struct of_device_id pm8921_id_table[] = {
+       { .compatible = "qcom,pm8058", },
+       { .compatible = "qcom,pm8921", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pm8921_id_table);
 
 static int pm8921_probe(struct platform_device *pdev)
 {
-       const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct pm8921 *pmic;
-       int rc;
-       u8 val;
+       struct regmap *regmap;
+       int irq, rc;
+       unsigned int val;
        u32 rev;
+       struct pm_irq_chip *chip;
+       unsigned int nirqs = PM8921_NR_IRQS;
 
-       if (!pdata) {
-               pr_err("missing platform data\n");
-               return -EINVAL;
-       }
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
 
        pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
        if (!pmic) {
@@ -124,8 +410,13 @@ static int pm8921_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
+                                 &ssbi_regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        /* Read PMIC chip revision */
-       rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
+       rc = regmap_read(regmap, REG_HWREV, &val);
        if (rc) {
                pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
                return rc;
@@ -134,7 +425,7 @@ static int pm8921_probe(struct platform_device *pdev)
        rev = val;
 
        /* Read PMIC chip revision 2 */
-       rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
+       rc = regmap_read(regmap, REG_HWREV_2, &val);
        if (rc) {
                pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
                        REG_HWREV_2, rc);
@@ -147,37 +438,56 @@ static int pm8921_probe(struct platform_device *pdev)
        pm8921_drvdata.pm_chip_data = pmic;
        platform_set_drvdata(pdev, &pm8921_drvdata);
 
-       rc = pm8921_add_subdevices(pdata, pmic, rev);
+       chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
+                                       sizeof(chip->config[0]) * nirqs,
+                                       GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       pmic->irq_chip = chip;
+       chip->dev = &pdev->dev;
+       chip->regmap = regmap;
+       chip->num_irqs = nirqs;
+       chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
+       chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
+       spin_lock_init(&chip->pm_irq_lock);
+
+       chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
+                                               &pm8xxx_irq_domain_ops,
+                                               chip);
+       if (!chip->irqdomain)
+               return -ENODEV;
+
+       irq_set_handler_data(irq, chip);
+       irq_set_chained_handler(irq, pm8xxx_irq_handler);
+       irq_set_irq_wake(irq, 1);
+
+       rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
        if (rc) {
-               pr_err("Cannot add subdevices rc=%d\n", rc);
-               goto err;
+               irq_set_chained_handler(irq, NULL);
+               irq_set_handler_data(irq, NULL);
+               irq_domain_remove(chip->irqdomain);
        }
 
-       /* gpio might not work if no irq device is found */
-       WARN_ON(pmic->irq_chip == NULL);
+       return rc;
+}
 
+static int pm8921_remove_child(struct device *dev, void *unused)
+{
+       platform_device_unregister(to_platform_device(dev));
        return 0;
-
-err:
-       mfd_remove_devices(pmic->dev);
-       return rc;
 }
 
 static int pm8921_remove(struct platform_device *pdev)
 {
-       struct pm8xxx_drvdata *drvdata;
-       struct pm8921 *pmic = NULL;
-
-       drvdata = platform_get_drvdata(pdev);
-       if (drvdata)
-               pmic = drvdata->pm_chip_data;
-       if (pmic) {
-               mfd_remove_devices(pmic->dev);
-               if (pmic->irq_chip) {
-                       pm8xxx_irq_exit(pmic->irq_chip);
-                       pmic->irq_chip = NULL;
-               }
-       }
+       int irq = platform_get_irq(pdev, 0);
+       struct pm8921 *pmic = pm8921_drvdata.pm_chip_data;
+       struct pm_irq_chip *chip = pmic->irq_chip;
+
+       device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
+       irq_set_chained_handler(irq, NULL);
+       irq_set_handler_data(irq, NULL);
+       irq_domain_remove(chip->irqdomain);
 
        return 0;
 }
@@ -188,6 +498,7 @@ static struct platform_driver pm8921_driver = {
        .driver         = {
                .name   = "pm8921-core",
                .owner  = THIS_MODULE,
+               .of_match_table = pm8921_id_table,
        },
 };
 
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
deleted file mode 100644 (file)
index 1360e20..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt)    "%s: " fmt, __func__
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/irq.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* PMIC8xxx IRQ */
-
-#define        SSBI_REG_ADDR_IRQ_BASE          0x1BB
-
-#define        SSBI_REG_ADDR_IRQ_ROOT          (SSBI_REG_ADDR_IRQ_BASE + 0)
-#define        SSBI_REG_ADDR_IRQ_M_STATUS1     (SSBI_REG_ADDR_IRQ_BASE + 1)
-#define        SSBI_REG_ADDR_IRQ_M_STATUS2     (SSBI_REG_ADDR_IRQ_BASE + 2)
-#define        SSBI_REG_ADDR_IRQ_M_STATUS3     (SSBI_REG_ADDR_IRQ_BASE + 3)
-#define        SSBI_REG_ADDR_IRQ_M_STATUS4     (SSBI_REG_ADDR_IRQ_BASE + 4)
-#define        SSBI_REG_ADDR_IRQ_BLK_SEL       (SSBI_REG_ADDR_IRQ_BASE + 5)
-#define        SSBI_REG_ADDR_IRQ_IT_STATUS     (SSBI_REG_ADDR_IRQ_BASE + 6)
-#define        SSBI_REG_ADDR_IRQ_CONFIG        (SSBI_REG_ADDR_IRQ_BASE + 7)
-#define        SSBI_REG_ADDR_IRQ_RT_STATUS     (SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define        PM_IRQF_LVL_SEL                 0x01    /* level select */
-#define        PM_IRQF_MASK_FE                 0x02    /* mask falling edge */
-#define        PM_IRQF_MASK_RE                 0x04    /* mask rising edge */
-#define        PM_IRQF_CLR                     0x08    /* clear interrupt */
-#define        PM_IRQF_BITS_MASK               0x70
-#define        PM_IRQF_BITS_SHIFT              4
-#define        PM_IRQF_WRITE                   0x80
-
-#define        PM_IRQF_MASK_ALL                (PM_IRQF_MASK_FE | \
-                                       PM_IRQF_MASK_RE)
-
-struct pm_irq_chip {
-       struct device           *dev;
-       spinlock_t              pm_irq_lock;
-       unsigned int            devirq;
-       unsigned int            irq_base;
-       unsigned int            num_irqs;
-       unsigned int            num_blocks;
-       unsigned int            num_masters;
-       u8                      config[0];
-};
-
-static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
-{
-       return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
-}
-
-static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
-{
-       return pm8xxx_readb(chip->dev,
-                       SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
-}
-
-static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
-{
-       int     rc;
-
-       spin_lock(&chip->pm_irq_lock);
-       rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-       if (rc) {
-               pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-               goto bail;
-       }
-
-       rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
-       if (rc)
-               pr_err("Failed Reading Status rc=%d\n", rc);
-bail:
-       spin_unlock(&chip->pm_irq_lock);
-       return rc;
-}
-
-static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
-{
-       int     rc;
-
-       spin_lock(&chip->pm_irq_lock);
-       rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-       if (rc) {
-               pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-               goto bail;
-       }
-
-       cp |= PM_IRQF_WRITE;
-       rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
-       if (rc)
-               pr_err("Failed Configuring IRQ rc=%d\n", rc);
-bail:
-       spin_unlock(&chip->pm_irq_lock);
-       return rc;
-}
-
-static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
-{
-       int pmirq, irq, i, ret = 0;
-       u8 bits;
-
-       ret = pm8xxx_read_block_irq(chip, block, &bits);
-       if (ret) {
-               pr_err("Failed reading %d block ret=%d", block, ret);
-               return ret;
-       }
-       if (!bits) {
-               pr_err("block bit set in master but no irqs: %d", block);
-               return 0;
-       }
-
-       /* Check IRQ bits */
-       for (i = 0; i < 8; i++) {
-               if (bits & (1 << i)) {
-                       pmirq = block * 8 + i;
-                       irq = pmirq + chip->irq_base;
-                       generic_handle_irq(irq);
-               }
-       }
-       return 0;
-}
-
-static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
-{
-       u8 blockbits;
-       int block_number, i, ret = 0;
-
-       ret = pm8xxx_read_master_irq(chip, master, &blockbits);
-       if (ret) {
-               pr_err("Failed to read master %d ret=%d\n", master, ret);
-               return ret;
-       }
-       if (!blockbits) {
-               pr_err("master bit set in root but no blocks: %d", master);
-               return 0;
-       }
-
-       for (i = 0; i < 8; i++)
-               if (blockbits & (1 << i)) {
-                       block_number = master * 8 + i;  /* block # */
-                       ret |= pm8xxx_irq_block_handler(chip, block_number);
-               }
-       return ret;
-}
-
-static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
-       struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-       u8      root;
-       int     i, ret, masters = 0;
-
-       ret = pm8xxx_read_root_irq(chip, &root);
-       if (ret) {
-               pr_err("Can't read root status ret=%d\n", ret);
-               return;
-       }
-
-       /* on pm8xxx series masters start from bit 1 of the root */
-       masters = root >> 1;
-
-       /* Read allowed masters for blocks. */
-       for (i = 0; i < chip->num_masters; i++)
-               if (masters & (1 << i))
-                       pm8xxx_irq_master_handler(chip, i);
-
-       irq_chip->irq_ack(&desc->irq_data);
-}
-
-static void pm8xxx_irq_mask_ack(struct irq_data *d)
-{
-       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-       unsigned int pmirq = d->irq - chip->irq_base;
-       int     master, irq_bit;
-       u8      block, config;
-
-       block = pmirq / 8;
-       master = block / 8;
-       irq_bit = pmirq % 8;
-
-       config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
-       pm8xxx_config_irq(chip, block, config);
-}
-
-static void pm8xxx_irq_unmask(struct irq_data *d)
-{
-       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-       unsigned int pmirq = d->irq - chip->irq_base;
-       int     master, irq_bit;
-       u8      block, config;
-
-       block = pmirq / 8;
-       master = block / 8;
-       irq_bit = pmirq % 8;
-
-       config = chip->config[pmirq];
-       pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-       unsigned int pmirq = d->irq - chip->irq_base;
-       int master, irq_bit;
-       u8 block, config;
-
-       block = pmirq / 8;
-       master = block / 8;
-       irq_bit  = pmirq % 8;
-
-       chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
-                                                       | PM_IRQF_MASK_ALL;
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-               if (flow_type & IRQF_TRIGGER_RISING)
-                       chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-               if (flow_type & IRQF_TRIGGER_FALLING)
-                       chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-       } else {
-               chip->config[pmirq] |= PM_IRQF_LVL_SEL;
-
-               if (flow_type & IRQF_TRIGGER_HIGH)
-                       chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-               else
-                       chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-       }
-
-       config = chip->config[pmirq] | PM_IRQF_CLR;
-       return pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       return 0;
-}
-
-static struct irq_chip pm8xxx_irq_chip = {
-       .name           = "pm8xxx",
-       .irq_mask_ack   = pm8xxx_irq_mask_ack,
-       .irq_unmask     = pm8xxx_irq_unmask,
-       .irq_set_type   = pm8xxx_irq_set_type,
-       .irq_set_wake   = pm8xxx_irq_set_wake,
-       .flags          = IRQCHIP_MASK_ON_SUSPEND,
-};
-
-/**
- * pm8xxx_get_irq_stat - get the status of the irq line
- * @chip: pointer to identify a pmic irq controller
- * @irq: the irq number
- *
- * The pm8xxx gpio and mpp rely on the interrupt block to read
- * the values on their pins. This function is to facilitate reading
- * the status of a gpio or an mpp line. The caller has to convert the
- * gpio number to irq number.
- *
- * RETURNS:
- * an int indicating the value read on that line
- */
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
-       int pmirq, rc;
-       u8  block, bits, bit;
-       unsigned long flags;
-
-       if (chip == NULL || irq < chip->irq_base ||
-                       irq >= chip->irq_base + chip->num_irqs)
-               return -EINVAL;
-
-       pmirq = irq - chip->irq_base;
-
-       block = pmirq / 8;
-       bit = pmirq % 8;
-
-       spin_lock_irqsave(&chip->pm_irq_lock, flags);
-
-       rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
-       if (rc) {
-               pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
-                       irq, pmirq, block, rc);
-               goto bail_out;
-       }
-
-       rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
-       if (rc) {
-               pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
-                       irq, pmirq, block, rc);
-               goto bail_out;
-       }
-
-       rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
-       spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
-
-struct pm_irq_chip *  pm8xxx_irq_init(struct device *dev,
-                               const struct pm8xxx_irq_platform_data *pdata)
-{
-       struct pm_irq_chip  *chip;
-       int devirq, rc;
-       unsigned int pmirq;
-
-       if (!pdata) {
-               pr_err("No platform data\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       devirq = pdata->devirq;
-       if (devirq < 0) {
-               pr_err("missing devirq\n");
-               rc = devirq;
-               return ERR_PTR(-EINVAL);
-       }
-
-       chip = kzalloc(sizeof(struct pm_irq_chip)
-                       + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
-       if (!chip) {
-               pr_err("Cannot alloc pm_irq_chip struct\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       chip->dev = dev;
-       chip->devirq = devirq;
-       chip->irq_base = pdata->irq_base;
-       chip->num_irqs = pdata->irq_cdata.nirqs;
-       chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
-       chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
-       spin_lock_init(&chip->pm_irq_lock);
-
-       for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
-               irq_set_chip_and_handler(chip->irq_base + pmirq,
-                               &pm8xxx_irq_chip,
-                               handle_level_irq);
-               irq_set_chip_data(chip->irq_base + pmirq, chip);
-#ifdef CONFIG_ARM
-               set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
-#else
-               irq_set_noprobe(chip->irq_base + pmirq);
-#endif
-       }
-
-       irq_set_irq_type(devirq, pdata->irq_trigger_flag);
-       irq_set_handler_data(devirq, chip);
-       irq_set_chained_handler(devirq, pm8xxx_irq_handler);
-       set_irq_wake(devirq, 1);
-
-       return chip;
-}
-
-int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-       irq_set_chained_handler(chip->devirq, NULL);
-       kfree(chip);
-       return 0;
-}
index b41db59..bb85020 100644 (file)
@@ -22,7 +22,6 @@
  */
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/mfd/rc5t583.h>
 
index d346146..c795697 100644 (file)
@@ -19,7 +19,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
index c8f345f..663f8a3 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
new file mode 100644 (file)
index 0000000..b53b9d4
--- /dev/null
@@ -0,0 +1,760 @@
+/* Driver for Realtek USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rtsx_usb.h>
+
+static int polling_pipe = 1;
+module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
+
+static struct mfd_cell rtsx_usb_cells[] = {
+       [RTSX_USB_SD_CARD] = {
+               .name = "rtsx_usb_sdmmc",
+               .pdata_size = 0,
+       },
+       [RTSX_USB_MS_CARD] = {
+               .name = "rtsx_usb_ms",
+               .pdata_size = 0,
+       },
+};
+
+static void rtsx_usb_sg_timed_out(unsigned long data)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)data;
+
+       dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
+       usb_sg_cancel(&ucr->current_sg);
+
+       /* we know the cancellation is caused by time-out */
+       ucr->current_sg.status = -ETIMEDOUT;
+}
+
+static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
+               unsigned int pipe, struct scatterlist *sg, int num_sg,
+               unsigned int length, unsigned int *act_len, int timeout)
+{
+       int ret;
+
+       dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n",
+                       __func__, length, num_sg);
+       ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0,
+                       sg, num_sg, length, GFP_NOIO);
+       if (ret)
+               return ret;
+
+       ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
+       add_timer(&ucr->sg_timer);
+       usb_sg_wait(&ucr->current_sg);
+       del_timer(&ucr->sg_timer);
+
+       if (act_len)
+               *act_len = ucr->current_sg.bytes;
+
+       return ucr->current_sg.status;
+}
+
+int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+                             void *buf, unsigned int len, int num_sg,
+                             unsigned int *act_len, int timeout)
+{
+       if (timeout < 600)
+               timeout = 600;
+
+       if (num_sg)
+               return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
+                               (struct scatterlist *)buf, num_sg, len, act_len,
+                               timeout);
+       else
+               return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
+                               timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
+
+static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 seq_type)
+{
+       rtsx_usb_cmd_hdr_tag(ucr);
+
+       ucr->cmd_buf[PACKET_TYPE] = seq_type;
+       ucr->cmd_buf[5] = (u8)(len >> 8);
+       ucr->cmd_buf[6] = (u8)len;
+       ucr->cmd_buf[8] = (u8)(addr >> 8);
+       ucr->cmd_buf[9] = (u8)addr;
+
+       if (seq_type == SEQ_WRITE)
+               ucr->cmd_buf[STAGE_FLAG] = 0;
+       else
+               ucr->cmd_buf[STAGE_FLAG] = STAGE_R;
+}
+
+static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 *data)
+{
+       u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4);
+
+       if (!data)
+               return -EINVAL;
+
+       if (cmd_len > IOBUF_SIZE)
+               return -EINVAL;
+
+       rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE);
+       memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len);
+
+       return rtsx_usb_transfer_data(ucr,
+                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                       ucr->cmd_buf, cmd_len, 0, NULL, 100);
+}
+
+static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 *data)
+{
+       int i, ret;
+       u16 rsp_len = round_down(len, 4);
+       u16 res_len = len - rsp_len;
+
+       if (!data)
+               return -EINVAL;
+
+       /* 4-byte aligned part */
+       if (rsp_len) {
+               rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ);
+               ret = rtsx_usb_transfer_data(ucr,
+                               usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                               ucr->cmd_buf, 12, 0, NULL, 100);
+               if (ret)
+                       return ret;
+
+               ret = rtsx_usb_transfer_data(ucr,
+                               usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+                               data, rsp_len, 0, NULL, 100);
+               if (ret)
+                       return ret;
+       }
+
+       /* unaligned part */
+       for (i = 0; i < res_len; i++) {
+               ret = rtsx_usb_read_register(ucr, addr + rsp_len + i,
+                               data + rsp_len + i);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+       return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf);
+
+int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+       return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf);
+
+int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
+               u8 mask, u8 data)
+{
+       u16 value, index;
+
+       addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT;
+       value = swab16(addr);
+       index = mask | data << 8;
+
+       return usb_control_msg(ucr->pusb_dev,
+                       usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
+
+int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+       u16 value;
+
+       if (!data)
+               return -EINVAL;
+       *data = 0;
+
+       addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
+       value = swab16(addr);
+
+       return usb_control_msg(ucr->pusb_dev,
+                       usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, 0, data, 1, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
+
+void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr,
+               u8 mask, u8 data)
+{
+       int i;
+
+       if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) {
+               i = CMD_OFFSET + ucr->cmd_idx * 4;
+
+               ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
+                       (u8)((reg_addr >> 8) & 0x3F);
+               ucr->cmd_buf[i++] = (u8)reg_addr;
+               ucr->cmd_buf[i++] = mask;
+               ucr->cmd_buf[i++] = data;
+
+               ucr->cmd_idx++;
+       }
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
+
+int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
+{
+       int ret;
+
+       ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
+       ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
+       ucr->cmd_buf[STAGE_FLAG] = flag;
+
+       ret = rtsx_usb_transfer_data(ucr,
+                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                       ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
+                       0, NULL, timeout);
+       if (ret) {
+               rtsx_usb_clear_fsm_err(ucr);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
+
+int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
+{
+       if (rsp_len <= 0)
+               return -EINVAL;
+
+       rsp_len = ALIGN(rsp_len, 4);
+
+       return rtsx_usb_transfer_data(ucr,
+                       usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+                       ucr->rsp_buf, rsp_len, 0, NULL, timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
+
+static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
+{
+       int ret;
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
+       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+       if (ret)
+               return ret;
+
+       ret = rtsx_usb_get_rsp(ucr, 2, 100);
+       if (ret)
+               return ret;
+
+       *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
+                 ((ucr->rsp_buf[1] & 0x03) << 4);
+
+       return 0;
+}
+
+int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
+{
+       int ret;
+
+       if (!status)
+               return -EINVAL;
+
+       if (polling_pipe == 0)
+               ret = usb_control_msg(ucr->pusb_dev,
+                               usb_rcvctrlpipe(ucr->pusb_dev, 0),
+                               RTSX_USB_REQ_POLL,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, 0, status, 2, 100);
+       else
+               ret = rtsx_usb_get_status_with_bulk(ucr, status);
+
+       /* usb_control_msg may return positive when success */
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
+
+static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val)
+{
+       dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n",
+                       val, addr);
+
+       rtsx_usb_init_cmd(ucr);
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL,
+                       0xFF, (addr >> 4) & 0x0F);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+
+       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data)
+{
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data);
+       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_register);
+
+int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+       int ret;
+
+       if (data != NULL)
+               *data = 0;
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0);
+       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+       if (ret)
+               return ret;
+
+       ret = rtsx_usb_get_rsp(ucr, 1, 100);
+       if (ret)
+               return ret;
+
+       if (data != NULL)
+               *data = ucr->rsp_buf[0];
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_register);
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+       return (depth > 1) ? (depth - 1) : depth;
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+       if (div > CLK_DIV_1) {
+               if (ssc_depth > div - 1)
+                       ssc_depth -= (div - 1);
+               else
+                       ssc_depth = SSC_DEPTH_2M;
+       }
+
+       return ssc_depth;
+}
+
+int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+       int ret;
+       u8 n, clk_divider, mcu_cnt, div;
+
+       if (!card_clock) {
+               ucr->cur_clk = 0;
+               return 0;
+       }
+
+       if (initial_mode) {
+               /* We use 250k(around) here, in initial stage */
+               clk_divider = SD_CLK_DIVIDE_128;
+               card_clock = 30000000;
+       } else {
+               clk_divider = SD_CLK_DIVIDE_0;
+       }
+
+       ret = rtsx_usb_write_register(ucr, SD_CFG1,
+                       SD_CLK_DIVIDE_MASK, clk_divider);
+       if (ret < 0)
+               return ret;
+
+       card_clock /= 1000000;
+       dev_dbg(&ucr->pusb_intf->dev,
+                       "Switch card clock to %dMHz\n", card_clock);
+
+       if (!initial_mode && double_clk)
+               card_clock *= 2;
+       dev_dbg(&ucr->pusb_intf->dev,
+                       "Internal SSC clock: %dMHz (cur_clk = %d)\n",
+                       card_clock, ucr->cur_clk);
+
+       if (card_clock == ucr->cur_clk)
+               return 0;
+
+       /* Converting clock value into internal settings: n and div */
+       n = card_clock - 2;
+       if ((card_clock <= 2) || (n > MAX_DIV_N))
+               return -EINVAL;
+
+       mcu_cnt = 60/card_clock + 3;
+       if (mcu_cnt > 15)
+               mcu_cnt = 15;
+
+       /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
+
+       div = CLK_DIV_1;
+       while (n < MIN_DIV_N && div < CLK_DIV_4) {
+               n = (n + 2) * 2 - 2;
+               div++;
+       }
+       dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div);
+
+       if (double_clk)
+               ssc_depth = double_ssc_depth(ssc_depth);
+
+       ssc_depth = revise_ssc_depth(ssc_depth, div);
+       dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth);
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV,
+                       0x3F, (div << 4) | mcu_cnt);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2,
+                       SSC_DEPTH_MASK, ssc_depth);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+       if (vpclk) {
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, 0);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, PHASE_NOT_RESET);
+       }
+
+       ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000);
+       if (ret < 0)
+               return ret;
+
+       ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff,
+                       SSC_RSTB | SSC_8X_EN | SSC_SEL_4M);
+       if (ret < 0)
+               return ret;
+
+       /* Wait SSC clock stable */
+       usleep_range(100, 1000);
+
+       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0);
+       if (ret < 0)
+               return ret;
+
+       ucr->cur_clk = card_clock;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock);
+
+int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card)
+{
+       int ret;
+       u16 val;
+       u16 cd_mask[] = {
+               [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD),
+               [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD)
+       };
+
+       ret = rtsx_usb_get_card_status(ucr, &val);
+       /*
+        * If get status fails, return 0 (ok) for the exclusive check
+        * and let the flow fail at somewhere else.
+        */
+       if (ret)
+               return 0;
+
+       if (val & cd_mask[card])
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check);
+
+static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
+{
+       int ret;
+       u8 val;
+
+       rtsx_usb_init_cmd(ucr);
+
+       if (CHECK_PKG(ucr, LQFP48)) {
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+                               LDO3318_PWR_MASK, LDO_SUSPEND);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+                               FORCE_LDO_POWERB, FORCE_LDO_POWERB);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1,
+                               0x30, 0x10);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5,
+                               0x03, 0x01);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6,
+                               0x0C, 0x04);
+       }
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                       CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       SD30_DRIVE_MASK, DRIVER_TYPE_D);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                       CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0);
+
+       if (ucr->is_rts5179)
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                               CARD_PULL_CTL5, 0x03, 0x01);
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL,
+                      EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND,
+                       XD_INT | MS_INT | SD_INT,
+                       XD_INT | MS_INT | SD_INT);
+
+       ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+       if (ret)
+               return ret;
+
+       /* config non-crystal mode */
+       rtsx_usb_read_register(ucr, CFG_MODE, &val);
+       if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) {
+               ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
+{
+       int ret;
+       u8 val;
+
+       rtsx_usb_clear_fsm_err(ucr);
+
+       /* power on SSC */
+       ret = rtsx_usb_write_register(ucr,
+                       FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
+       if (ret)
+               return ret;
+
+       usleep_range(100, 1000);
+       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
+       if (ret)
+               return ret;
+
+       /* determine IC version */
+       ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
+       if (ret)
+               return ret;
+
+       ucr->ic_version = val & HW_VER_MASK;
+
+       /* determine package */
+       ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
+       if (ret)
+               return ret;
+
+       if (val & CARD_SHARE_LQFP_SEL) {
+               ucr->package = LQFP48;
+               dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
+       } else {
+               ucr->package = QFN24;
+               dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
+       }
+
+       /* determine IC variations */
+       rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
+       if (val & RTS5179) {
+               ucr->is_rts5179 = true;
+               dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
+       } else {
+               ucr->is_rts5179 = false;
+       }
+
+       return rtsx_usb_reset_chip(ucr);
+}
+
+static int rtsx_usb_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct rtsx_ucr *ucr;
+       int ret;
+
+       dev_dbg(&intf->dev,
+               ": Realtek USB Card Reader found at bus %03d address %03d\n",
+                usb_dev->bus->busnum, usb_dev->devnum);
+
+       ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL);
+       if (!ucr)
+               return -ENOMEM;
+
+       ucr->pusb_dev = usb_dev;
+
+       ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
+                       GFP_KERNEL, &ucr->iobuf_dma);
+       if (!ucr->iobuf)
+               return -ENOMEM;
+
+       usb_set_intfdata(intf, ucr);
+
+       ucr->vendor_id = id->idVendor;
+       ucr->product_id = id->idProduct;
+       ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
+
+       mutex_init(&ucr->dev_mutex);
+
+       ucr->pusb_intf = intf;
+
+       /* initialize */
+       ret = rtsx_usb_init_chip(ucr);
+       if (ret)
+               goto out_init_fail;
+
+       ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
+                       ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
+       if (ret)
+               goto out_init_fail;
+
+       /* initialize USB SG transfer timer */
+       init_timer(&ucr->sg_timer);
+       setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
+#ifdef CONFIG_PM
+       intf->needs_remote_wakeup = 1;
+       usb_enable_autosuspend(usb_dev);
+#endif
+
+       return 0;
+
+out_init_fail:
+       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+                       ucr->iobuf_dma);
+       return ret;
+}
+
+static void rtsx_usb_disconnect(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       dev_dbg(&intf->dev, "%s called\n", __func__);
+
+       mfd_remove_devices(&intf->dev);
+
+       usb_set_intfdata(ucr->pusb_intf, NULL);
+       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+                       ucr->iobuf_dma);
+}
+
+#ifdef CONFIG_PM
+static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct rtsx_ucr *ucr =
+               (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       dev_dbg(&intf->dev, "%s called with pm message 0x%04u\n",
+                       __func__, message.event);
+
+       mutex_lock(&ucr->dev_mutex);
+       rtsx_usb_turn_off_led(ucr);
+       mutex_unlock(&ucr->dev_mutex);
+       return 0;
+}
+
+static int rtsx_usb_resume(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int rtsx_usb_reset_resume(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr =
+               (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       rtsx_usb_reset_chip(ucr);
+       return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_usb_suspend NULL
+#define rtsx_usb_resume NULL
+#define rtsx_usb_reset_resume NULL
+
+#endif /* CONFIG_PM */
+
+
+static int rtsx_usb_pre_reset(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       mutex_lock(&ucr->dev_mutex);
+       return 0;
+}
+
+static int rtsx_usb_post_reset(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       mutex_unlock(&ucr->dev_mutex);
+       return 0;
+}
+
+static struct usb_device_id rtsx_usb_usb_ids[] = {
+       { USB_DEVICE(0x0BDA, 0x0129) },
+       { USB_DEVICE(0x0BDA, 0x0139) },
+       { USB_DEVICE(0x0BDA, 0x0140) },
+       { }
+};
+
+static struct usb_driver rtsx_usb_driver = {
+       .name                   = "rtsx_usb",
+       .probe                  = rtsx_usb_probe,
+       .disconnect             = rtsx_usb_disconnect,
+       .suspend                = rtsx_usb_suspend,
+       .resume                 = rtsx_usb_resume,
+       .reset_resume           = rtsx_usb_reset_resume,
+       .pre_reset              = rtsx_usb_pre_reset,
+       .post_reset             = rtsx_usb_post_reset,
+       .id_table               = rtsx_usb_usb_ids,
+       .supports_autosuspend   = 1,
+       .soft_unbind            = 1,
+};
+
+module_usb_driver(rtsx_usb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
+MODULE_DESCRIPTION("Realtek USB Card Reader Driver");
index 281a827..1cf2752 100644 (file)
@@ -60,6 +60,7 @@ static const struct mfd_cell s5m8767_devs[] = {
                .name = "s5m-rtc",
        }, {
                .name = "s5m8767-clk",
+               .of_compatible = "samsung,s5m8767-clk",
        }
 };
 
@@ -68,6 +69,7 @@ static const struct mfd_cell s2mps11_devs[] = {
                .name = "s2mps11-pmic",
        }, {
                .name = "s2mps11-clk",
+               .of_compatible = "samsung,s2mps11-clk",
        }
 };
 
@@ -78,6 +80,7 @@ static const struct mfd_cell s2mps14_devs[] = {
                .name = "s2mps14-rtc",
        }, {
                .name = "s2mps14-clk",
+               .of_compatible = "samsung,s2mps14-clk",
        }
 };
 
@@ -295,6 +298,13 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        switch (sec_pmic->device_type) {
        case S2MPA01:
                regmap = &s2mpa01_regmap_config;
+               /*
+                * The rtc-s5m driver does not support S2MPA01 and there
+                * is no mfd_cell for S2MPA01 RTC device.
+                * However we must pass something to devm_regmap_init_i2c()
+                * so use S5M-like regmap config even though it wouldn't work.
+                */
+               regmap_rtc = &s5m_rtc_regmap_config;
                break;
        case S2MPS11X:
                regmap = &s2mps11_regmap_config;
@@ -344,7 +354,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                ret = PTR_ERR(sec_pmic->regmap_rtc);
                dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
                        ret);
-               return ret;
+               goto err_regmap_rtc;
        }
 
        if (pdata && pdata->cfg_pmic_irq)
@@ -385,14 +395,15 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        }
 
        if (ret)
-               goto err;
+               goto err_mfd;
 
        device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
 
        return ret;
 
-err:
+err_mfd:
        sec_irq_exit(sec_pmic);
+err_regmap_rtc:
        i2c_unregister_device(sec_pmic->rtc);
        return ret;
 }
index 24ae3d8..90112d4 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
index 42ccd05..4a91f67 100644 (file)
@@ -706,7 +706,7 @@ static int stmpe1801_reset(struct stmpe *stmpe)
                if (!(ret & STMPE1801_MSK_SYS_CTRL_RESET))
                        return 0;
                usleep_range(100, 200);
-       };
+       }
        return -EIO;
 }
 
index 1243d5c..7ceb3df 100644 (file)
@@ -167,7 +167,7 @@ static struct mfd_cell stw481x_cells[] = {
        },
 };
 
-const struct regmap_config stw481x_regmap_config = {
+static const struct regmap_config stw481x_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 };
@@ -186,6 +186,12 @@ static int stw481x_probe(struct i2c_client *client,
        i2c_set_clientdata(client, stw481x);
        stw481x->client = client;
        stw481x->map = devm_regmap_init_i2c(client, &stw481x_regmap_config);
+       if (IS_ERR(stw481x->map)) {
+               ret = PTR_ERR(stw481x->map);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
 
        ret = stw481x_startup(stw481x);
        if (ret) {
index 71841f9..dbea55d 100644 (file)
@@ -69,13 +69,6 @@ EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
 
 static int syscon_match_pdevname(struct device *dev, void *data)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       const struct platform_device_id *id = platform_get_device_id(pdev);
-
-       if (id)
-               if (!strcmp(id->name, (const char *)data))
-                       return 1;
-
        return !strcmp(dev_name(dev), (const char *)data);
 }
 
@@ -152,7 +145,7 @@ static int syscon_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, syscon);
 
-       dev_info(dev, "regmap %pR registered\n", res);
+       dev_dbg(dev, "regmap %pR registered\n", res);
 
        return 0;
 }
index 2cf636c..bd83acc 100644 (file)
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/err.h>
 
 /**
  * enum tc3589x_version - indicates the TC3589x version
@@ -160,7 +162,7 @@ static const struct mfd_cell tc3589x_dev_gpio[] = {
                .name           = "tc3589x-gpio",
                .num_resources  = ARRAY_SIZE(gpio_resources),
                .resources      = &gpio_resources[0],
-               .of_compatible  = "tc3589x-gpio",
+               .of_compatible  = "toshiba,tc3589x-gpio",
        },
 };
 
@@ -169,7 +171,7 @@ static const struct mfd_cell tc3589x_dev_keypad[] = {
                .name           = "tc3589x-keypad",
                .num_resources  = ARRAY_SIZE(keypad_resources),
                .resources      = &keypad_resources[0],
-               .of_compatible  = "tc3589x-keypad",
+               .of_compatible  = "toshiba,tc3589x-keypad",
        },
 };
 
@@ -318,45 +320,74 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
        return ret;
 }
 
-static int tc3589x_of_probe(struct device_node *np,
-                       struct tc3589x_platform_data *pdata)
+#ifdef CONFIG_OF
+static const struct of_device_id tc3589x_match[] = {
+       /* Legacy compatible string */
+       { .compatible = "tc3589x", .data = (void *) TC3589X_UNKNOWN },
+       { .compatible = "toshiba,tc35890", .data = (void *) TC3589X_TC35890 },
+       { .compatible = "toshiba,tc35892", .data = (void *) TC3589X_TC35892 },
+       { .compatible = "toshiba,tc35893", .data = (void *) TC3589X_TC35893 },
+       { .compatible = "toshiba,tc35894", .data = (void *) TC3589X_TC35894 },
+       { .compatible = "toshiba,tc35895", .data = (void *) TC3589X_TC35895 },
+       { .compatible = "toshiba,tc35896", .data = (void *) TC3589X_TC35896 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, tc3589x_match);
+
+static struct tc3589x_platform_data *
+tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
 {
+       struct device_node *np = dev->of_node;
+       struct tc3589x_platform_data *pdata;
        struct device_node *child;
+       const struct of_device_id *of_id;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       of_id = of_match_device(tc3589x_match, dev);
+       if (!of_id)
+               return ERR_PTR(-ENODEV);
+       *version = (enum tc3589x_version) of_id->data;
 
        for_each_child_of_node(np, child) {
-               if (!strcmp(child->name, "tc3589x_gpio")) {
+               if (of_device_is_compatible(child, "toshiba,tc3589x-gpio"))
                        pdata->block |= TC3589x_BLOCK_GPIO;
-               }
-               if (!strcmp(child->name, "tc3589x_keypad")) {
+               if (of_device_is_compatible(child, "toshiba,tc3589x-keypad"))
                        pdata->block |= TC3589x_BLOCK_KEYPAD;
-               }
        }
 
-       return 0;
+       return pdata;
 }
+#else
+static inline struct tc3589x_platform_data *
+tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
+{
+       dev_err(dev, "no device tree support\n");
+       return ERR_PTR(-ENODEV);
+}
+#endif
 
 static int tc3589x_probe(struct i2c_client *i2c,
                                   const struct i2c_device_id *id)
 {
-       struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
        struct device_node *np = i2c->dev.of_node;
+       struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
        struct tc3589x *tc3589x;
+       enum tc3589x_version version;
        int ret;
 
        if (!pdata) {
-               if (np) {
-                       pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
-                       if (!pdata)
-                               return -ENOMEM;
-
-                       ret = tc3589x_of_probe(np, pdata);
-                       if (ret)
-                               return ret;
-               }
-               else {
+               pdata = tc3589x_of_probe(&i2c->dev, &version);
+               if (IS_ERR(pdata)) {
                        dev_err(&i2c->dev, "No platform data or DT found\n");
-                       return -EINVAL;
+                       return PTR_ERR(pdata);
                }
+       } else {
+               /* When not probing from device tree we have this ID */
+               version = id->driver_data;
        }
 
        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
@@ -375,7 +406,7 @@ static int tc3589x_probe(struct i2c_client *i2c,
        tc3589x->pdata = pdata;
        tc3589x->irq_base = pdata->irq_base;
 
-       switch (id->driver_data) {
+       switch (version) {
        case TC3589X_TC35893:
        case TC3589X_TC35895:
        case TC3589X_TC35896:
@@ -471,9 +502,12 @@ static const struct i2c_device_id tc3589x_id[] = {
 MODULE_DEVICE_TABLE(i2c, tc3589x_id);
 
 static struct i2c_driver tc3589x_driver = {
-       .driver.name    = "tc3589x",
-       .driver.owner   = THIS_MODULE,
-       .driver.pm      = &tc3589x_dev_pm_ops,
+       .driver = {
+               .name   = "tc3589x",
+               .owner  = THIS_MODULE,
+               .pm     = &tc3589x_dev_pm_ops,
+               .of_match_table = of_match_ptr(tc3589x_match),
+       },
        .probe          = tc3589x_probe,
        .remove         = tc3589x_remove,
        .id_table       = tc3589x_id,
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
deleted file mode 100644 (file)
index a542457..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Sequencer Serial Port (SSP) driver for Texas Instruments' SoCs
- *
- * Copyright (C) 2010 Texas Instruments Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/ti_ssp.h>
-
-/* Register Offsets */
-#define REG_REV                0x00
-#define REG_IOSEL_1    0x04
-#define REG_IOSEL_2    0x08
-#define REG_PREDIV     0x0c
-#define REG_INTR_ST    0x10
-#define REG_INTR_EN    0x14
-#define REG_TEST_CTRL  0x18
-
-/* Per port registers */
-#define PORT_CFG_2     0x00
-#define PORT_ADDR      0x04
-#define PORT_DATA      0x08
-#define PORT_CFG_1     0x0c
-#define PORT_STATE     0x10
-
-#define SSP_PORT_CONFIG_MASK   (SSP_EARLY_DIN | SSP_DELAY_DOUT)
-#define SSP_PORT_CLKRATE_MASK  0x0f
-
-#define SSP_SEQRAM_WR_EN       BIT(4)
-#define SSP_SEQRAM_RD_EN       BIT(5)
-#define SSP_START              BIT(15)
-#define SSP_BUSY               BIT(10)
-#define SSP_PORT_ASL           BIT(7)
-#define SSP_PORT_CFO1          BIT(6)
-
-#define SSP_PORT_SEQRAM_SIZE   32
-
-static const int ssp_port_base[]   = {0x040, 0x080};
-static const int ssp_port_seqram[] = {0x100, 0x180};
-
-struct ti_ssp {
-       struct resource         *res;
-       struct device           *dev;
-       void __iomem            *regs;
-       spinlock_t              lock;
-       struct clk              *clk;
-       int                     irq;
-       wait_queue_head_t       wqh;
-
-       /*
-        * Some of the iosel2 register bits always read-back as 0, we need to
-        * remember these values so that we don't clobber previously set
-        * values.
-        */
-       u32                     iosel2;
-};
-
-static inline struct ti_ssp *dev_to_ssp(struct device *dev)
-{
-       return dev_get_drvdata(dev->parent);
-}
-
-static inline int dev_to_port(struct device *dev)
-{
-       return to_platform_device(dev)->id;
-}
-
-/* Register Access Helpers, rmw() functions need to run locked */
-static inline u32 ssp_read(struct ti_ssp *ssp, int reg)
-{
-       return __raw_readl(ssp->regs + reg);
-}
-
-static inline void ssp_write(struct ti_ssp *ssp, int reg, u32 val)
-{
-       __raw_writel(val, ssp->regs + reg);
-}
-
-static inline void ssp_rmw(struct ti_ssp *ssp, int reg, u32 mask, u32 bits)
-{
-       ssp_write(ssp, reg, (ssp_read(ssp, reg) & ~mask) | bits);
-}
-
-static inline u32 ssp_port_read(struct ti_ssp *ssp, int port, int reg)
-{
-       return ssp_read(ssp, ssp_port_base[port] + reg);
-}
-
-static inline void ssp_port_write(struct ti_ssp *ssp, int port, int reg,
-                                 u32 val)
-{
-       ssp_write(ssp, ssp_port_base[port] + reg, val);
-}
-
-static inline void ssp_port_rmw(struct ti_ssp *ssp, int port, int reg,
-                               u32 mask, u32 bits)
-{
-       ssp_rmw(ssp, ssp_port_base[port] + reg, mask, bits);
-}
-
-static inline void ssp_port_clr_bits(struct ti_ssp *ssp, int port, int reg,
-                                    u32 bits)
-{
-       ssp_port_rmw(ssp, port, reg, bits, 0);
-}
-
-static inline void ssp_port_set_bits(struct ti_ssp *ssp, int port, int reg,
-                                    u32 bits)
-{
-       ssp_port_rmw(ssp, port, reg, 0, bits);
-}
-
-/* Called to setup port clock mode, caller must hold ssp->lock */
-static int __set_mode(struct ti_ssp *ssp, int port, int mode)
-{
-       mode &= SSP_PORT_CONFIG_MASK;
-       ssp_port_rmw(ssp, port, PORT_CFG_1, SSP_PORT_CONFIG_MASK, mode);
-
-       return 0;
-}
-
-int ti_ssp_set_mode(struct device *dev, int mode)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev);
-       int ret;
-
-       spin_lock(&ssp->lock);
-       ret = __set_mode(ssp, port, mode);
-       spin_unlock(&ssp->lock);
-
-       return ret;
-}
-EXPORT_SYMBOL(ti_ssp_set_mode);
-
-/* Called to setup iosel2, caller must hold ssp->lock */
-static void __set_iosel2(struct ti_ssp *ssp, u32 mask, u32 val)
-{
-       ssp->iosel2 = (ssp->iosel2 & ~mask) | val;
-       ssp_write(ssp, REG_IOSEL_2, ssp->iosel2);
-}
-
-/* Called to setup port iosel, caller must hold ssp->lock */
-static void __set_iosel(struct ti_ssp *ssp, int port, u32 iosel)
-{
-       unsigned val, shift = port ? 16 : 0;
-
-       /* IOSEL1 gets the least significant 16 bits */
-       val = ssp_read(ssp, REG_IOSEL_1);
-       val &= 0xffff << (port ? 0 : 16);
-       val |= (iosel & 0xffff) << (port ? 16 : 0);
-       ssp_write(ssp, REG_IOSEL_1, val);
-
-       /* IOSEL2 gets the most significant 16 bits */
-       val = (iosel >> 16) & 0x7;
-       __set_iosel2(ssp, 0x7 << shift, val << shift);
-}
-
-int ti_ssp_set_iosel(struct device *dev, u32 iosel)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev);
-
-       spin_lock(&ssp->lock);
-       __set_iosel(ssp, port, iosel);
-       spin_unlock(&ssp->lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(ti_ssp_set_iosel);
-
-int ti_ssp_load(struct device *dev, int offs, u32* prog, int len)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev);
-       int i;
-
-       if (len > SSP_PORT_SEQRAM_SIZE)
-               return -ENOSPC;
-
-       spin_lock(&ssp->lock);
-
-       /* Enable SeqRAM access */
-       ssp_port_set_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
-
-       /* Copy code */
-       for (i = 0; i < len; i++) {
-               __raw_writel(prog[i], ssp->regs + offs + 4*i +
-                            ssp_port_seqram[port]);
-       }
-
-       /* Disable SeqRAM access */
-       ssp_port_clr_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
-
-       spin_unlock(&ssp->lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(ti_ssp_load);
-
-int ti_ssp_raw_read(struct device *dev)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev);
-       int shift = port ? 27 : 11;
-
-       return (ssp_read(ssp, REG_IOSEL_2) >> shift) & 0xf;
-}
-EXPORT_SYMBOL(ti_ssp_raw_read);
-
-int ti_ssp_raw_write(struct device *dev, u32 val)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev), shift;
-
-       spin_lock(&ssp->lock);
-
-       shift = port ? 22 : 6;
-       val &= 0xf;
-       __set_iosel2(ssp, 0xf << shift, val << shift);
-
-       spin_unlock(&ssp->lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(ti_ssp_raw_write);
-
-static inline int __xfer_done(struct ti_ssp *ssp, int port)
-{
-       return !(ssp_port_read(ssp, port, PORT_CFG_1) & SSP_BUSY);
-}
-
-int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output)
-{
-       struct ti_ssp *ssp = dev_to_ssp(dev);
-       int port = dev_to_port(dev);
-       int ret;
-
-       if (pc & ~(0x3f))
-               return -EINVAL;
-
-       /* Grab ssp->lock to serialize rmw on ssp registers */
-       spin_lock(&ssp->lock);
-
-       ssp_port_write(ssp, port, PORT_ADDR, input >> 16);
-       ssp_port_write(ssp, port, PORT_DATA, input & 0xffff);
-       ssp_port_rmw(ssp, port, PORT_CFG_1, 0x3f, pc);
-
-       /* grab wait queue head lock to avoid race with the isr */
-       spin_lock_irq(&ssp->wqh.lock);
-
-       /* kick off sequence execution in hardware */
-       ssp_port_set_bits(ssp, port, PORT_CFG_1, SSP_START);
-
-       /* drop ssp lock; no register writes beyond this */
-       spin_unlock(&ssp->lock);
-
-       ret = wait_event_interruptible_locked_irq(ssp->wqh,
-                                                 __xfer_done(ssp, port));
-       spin_unlock_irq(&ssp->wqh.lock);
-
-       if (ret < 0)
-               return ret;
-
-       if (output) {
-               *output = (ssp_port_read(ssp, port, PORT_ADDR) << 16) |
-                         (ssp_port_read(ssp, port, PORT_DATA) &  0xffff);
-       }
-
-       ret = ssp_port_read(ssp, port, PORT_STATE) & 0x3f; /* stop address */
-
-       return ret;
-}
-EXPORT_SYMBOL(ti_ssp_run);
-
-static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
-{
-       struct ti_ssp *ssp = dev_data;
-
-       spin_lock(&ssp->wqh.lock);
-
-       ssp_write(ssp, REG_INTR_ST, 0x3);
-       wake_up_locked(&ssp->wqh);
-
-       spin_unlock(&ssp->wqh.lock);
-
-       return IRQ_HANDLED;
-}
-
-static int ti_ssp_probe(struct platform_device *pdev)
-{
-       static struct ti_ssp *ssp;
-       const struct ti_ssp_data *pdata = dev_get_platdata(&pdev->dev);
-       int error = 0, prediv = 0xff, id;
-       unsigned long sysclk;
-       struct device *dev = &pdev->dev;
-       struct mfd_cell cells[2];
-
-       ssp = kzalloc(sizeof(*ssp), GFP_KERNEL);
-       if (!ssp) {
-               dev_err(dev, "cannot allocate device info\n");
-               return -ENOMEM;
-       }
-
-       ssp->dev = dev;
-       dev_set_drvdata(dev, ssp);
-
-       ssp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!ssp->res) {
-               error = -ENODEV;
-               dev_err(dev, "cannot determine register area\n");
-               goto error_res;
-       }
-
-       if (!request_mem_region(ssp->res->start, resource_size(ssp->res),
-                               pdev->name)) {
-               error = -ENOMEM;
-               dev_err(dev, "cannot claim register memory\n");
-               goto error_res;
-       }
-
-       ssp->regs = ioremap(ssp->res->start, resource_size(ssp->res));
-       if (!ssp->regs) {
-               error = -ENOMEM;
-               dev_err(dev, "cannot map register memory\n");
-               goto error_map;
-       }
-
-       ssp->clk = clk_get(dev, NULL);
-       if (IS_ERR(ssp->clk)) {
-               error = PTR_ERR(ssp->clk);
-               dev_err(dev, "cannot claim device clock\n");
-               goto error_clk;
-       }
-
-       ssp->irq = platform_get_irq(pdev, 0);
-       if (ssp->irq < 0) {
-               error = -ENODEV;
-               dev_err(dev, "unknown irq\n");
-               goto error_irq;
-       }
-
-       error = request_threaded_irq(ssp->irq, NULL, ti_ssp_interrupt, 0,
-                                    dev_name(dev), ssp);
-       if (error < 0) {
-               dev_err(dev, "cannot acquire irq\n");
-               goto error_irq;
-       }
-
-       spin_lock_init(&ssp->lock);
-       init_waitqueue_head(&ssp->wqh);
-
-       /* Power on and initialize SSP */
-       error = clk_enable(ssp->clk);
-       if (error) {
-               dev_err(dev, "cannot enable device clock\n");
-               goto error_enable;
-       }
-
-       /* Reset registers to a sensible known state */
-       ssp_write(ssp, REG_IOSEL_1, 0);
-       ssp_write(ssp, REG_IOSEL_2, 0);
-       ssp_write(ssp, REG_INTR_EN, 0x3);
-       ssp_write(ssp, REG_INTR_ST, 0x3);
-       ssp_write(ssp, REG_TEST_CTRL, 0);
-       ssp_port_write(ssp, 0, PORT_CFG_1, SSP_PORT_ASL);
-       ssp_port_write(ssp, 1, PORT_CFG_1, SSP_PORT_ASL);
-       ssp_port_write(ssp, 0, PORT_CFG_2, SSP_PORT_CFO1);
-       ssp_port_write(ssp, 1, PORT_CFG_2, SSP_PORT_CFO1);
-
-       sysclk = clk_get_rate(ssp->clk);
-       if (pdata && pdata->out_clock)
-               prediv = (sysclk / pdata->out_clock) - 1;
-       prediv = clamp(prediv, 0, 0xff);
-       ssp_rmw(ssp, REG_PREDIV, 0xff, prediv);
-
-       memset(cells, 0, sizeof(cells));
-       for (id = 0; id < 2; id++) {
-               const struct ti_ssp_dev_data *data = &pdata->dev_data[id];
-
-               cells[id].id            = id;
-               cells[id].name          = data->dev_name;
-               cells[id].platform_data = data->pdata;
-       }
-
-       error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
-       if (error < 0) {
-               dev_err(dev, "cannot add mfd cells\n");
-               goto error_enable;
-       }
-
-       return 0;
-
-error_enable:
-       free_irq(ssp->irq, ssp);
-error_irq:
-       clk_put(ssp->clk);
-error_clk:
-       iounmap(ssp->regs);
-error_map:
-       release_mem_region(ssp->res->start, resource_size(ssp->res));
-error_res:
-       kfree(ssp);
-       return error;
-}
-
-static int ti_ssp_remove(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct ti_ssp *ssp = dev_get_drvdata(dev);
-
-       mfd_remove_devices(dev);
-       clk_disable(ssp->clk);
-       free_irq(ssp->irq, ssp);
-       clk_put(ssp->clk);
-       iounmap(ssp->regs);
-       release_mem_region(ssp->res->start, resource_size(ssp->res));
-       kfree(ssp);
-       return 0;
-}
-
-static struct platform_driver ti_ssp_driver = {
-       .probe          = ti_ssp_probe,
-       .remove         = ti_ssp_remove,
-       .driver         = {
-               .name   = "ti-ssp",
-               .owner  = THIS_MODULE,
-       }
-};
-
-module_platform_driver(ti_ssp_driver);
-
-MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ti-ssp");
index d4e8604..dd4bf58 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -184,12 +183,6 @@ static     int ti_tscadc_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no memory resource defined.\n");
-               return -EINVAL;
-       }
-
        /* Allocate memory for device */
        tscadc = devm_kzalloc(&pdev->dev,
                        sizeof(struct ti_tscadc_dev), GFP_KERNEL);
@@ -206,19 +199,10 @@ static    int ti_tscadc_probe(struct platform_device *pdev)
        } else
                tscadc->irq = err;
 
-       res = devm_request_mem_region(&pdev->dev,
-                       res->start, resource_size(res), pdev->name);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to reserve registers.\n");
-               return -EBUSY;
-       }
-
-       tscadc->tscadc_base = devm_ioremap(&pdev->dev,
-                       res->start, resource_size(res));
-       if (!tscadc->tscadc_base) {
-               dev_err(&pdev->dev, "failed to map registers.\n");
-               return -ENOMEM;
-       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(tscadc->tscadc_base))
+               return PTR_ERR(tscadc->tscadc_base);
 
        tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
                        tscadc->tscadc_base, &tscadc_regmap_config);
index 2bc5cfb..6ce36d6 100644 (file)
@@ -715,7 +715,7 @@ static int timb_probe(struct pci_dev *dev,
        for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
                msix_entries[i].entry = i;
 
-       err = pci_enable_msix(dev, msix_entries, TIMBERDALE_NR_IRQS);
+       err = pci_enable_msix_exact(dev, msix_entries, TIMBERDALE_NR_IRQS);
        if (err) {
                dev_err(&dev->dev,
                        "MSI-X init failed: %d, expected entries: %d\n",
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
new file mode 100644 (file)
index 0000000..a74bfb5
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Driver for TPS65218 Integrated power management chipsets
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65218.h>
+
+#define TPS65218_PASSWORD_REGS_UNLOCK   0x7D
+
+/**
+ * tps65218_reg_read: Read a single tps65218 register.
+ *
+ * @tps: Device to read from.
+ * @reg: Register to read.
+ * @val: Contians the value
+ */
+int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
+                       unsigned int *val)
+{
+       return regmap_read(tps->regmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65218_reg_read);
+
+/**
+ * tps65218_reg_write: Write a single tps65218 register.
+ *
+ * @tps65218: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int xor_reg_val;
+
+       switch (level) {
+       case TPS65218_PROTECT_NONE:
+               return regmap_write(tps->regmap, reg, val);
+       case TPS65218_PROTECT_L1:
+               xor_reg_val = reg ^ TPS65218_PASSWORD_REGS_UNLOCK;
+               ret = regmap_write(tps->regmap, TPS65218_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+
+               return regmap_write(tps->regmap, reg, val);
+       default:
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL_GPL(tps65218_reg_write);
+
+/**
+ * tps65218_update_bits: Modify bits w.r.t mask, val and level.
+ *
+ * @tps65218: Device to write to.
+ * @reg: Register to read-write to.
+ * @mask: Mask.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int data;
+
+       ret = tps65218_reg_read(tps, reg, &data);
+       if (ret) {
+               dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
+               return ret;
+       }
+
+       data &= ~mask;
+       data |= val & mask;
+
+       mutex_lock(&tps->tps_lock);
+       ret = tps65218_reg_write(tps, reg, data, level);
+       if (ret)
+               dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
+       mutex_unlock(&tps->tps_lock);
+
+       return ret;
+}
+
+int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       return tps65218_update_bits(tps, reg, mask, val, level);
+}
+EXPORT_SYMBOL_GPL(tps65218_set_bits);
+
+int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level)
+{
+       return tps65218_update_bits(tps, reg, mask, 0, level);
+}
+EXPORT_SYMBOL_GPL(tps65218_clear_bits);
+
+static struct regmap_config tps65218_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq tps65218_irqs[] = {
+       /* INT1 IRQs */
+       [TPS65218_PRGC_IRQ] = {
+               .mask = TPS65218_INT1_PRGC,
+       },
+       [TPS65218_CC_AQC_IRQ] = {
+               .mask = TPS65218_INT1_CC_AQC,
+       },
+       [TPS65218_HOT_IRQ] = {
+               .mask = TPS65218_INT1_HOT,
+       },
+       [TPS65218_PB_IRQ] = {
+               .mask = TPS65218_INT1_PB,
+       },
+       [TPS65218_AC_IRQ] = {
+               .mask = TPS65218_INT1_AC,
+       },
+       [TPS65218_VPRG_IRQ] = {
+               .mask = TPS65218_INT1_VPRG,
+       },
+       [TPS65218_INVALID1_IRQ] = {
+       },
+       [TPS65218_INVALID2_IRQ] = {
+       },
+       /* INT2 IRQs*/
+       [TPS65218_LS1_I_IRQ] = {
+               .mask = TPS65218_INT2_LS1_I,
+               .reg_offset = 1,
+       },
+       [TPS65218_LS2_I_IRQ] = {
+               .mask = TPS65218_INT2_LS2_I,
+               .reg_offset = 1,
+       },
+       [TPS65218_LS3_I_IRQ] = {
+               .mask = TPS65218_INT2_LS3_I,
+               .reg_offset = 1,
+       },
+       [TPS65218_LS1_F_IRQ] = {
+               .mask = TPS65218_INT2_LS1_F,
+               .reg_offset = 1,
+       },
+       [TPS65218_LS2_F_IRQ] = {
+               .mask = TPS65218_INT2_LS2_F,
+               .reg_offset = 1,
+       },
+       [TPS65218_LS3_F_IRQ] = {
+               .mask = TPS65218_INT2_LS3_F,
+               .reg_offset = 1,
+       },
+       [TPS65218_INVALID3_IRQ] = {
+       },
+       [TPS65218_INVALID4_IRQ] = {
+       },
+};
+
+static struct regmap_irq_chip tps65218_irq_chip = {
+       .name = "tps65218",
+       .irqs = tps65218_irqs,
+       .num_irqs = ARRAY_SIZE(tps65218_irqs),
+
+       .num_regs = 2,
+       .mask_base = TPS65218_REG_INT_MASK1,
+};
+
+static const struct of_device_id of_tps65218_match_table[] = {
+       { .compatible = "ti,tps65218", },
+};
+
+static int tps65218_probe(struct i2c_client *client,
+                               const struct i2c_device_id *ids)
+{
+       struct tps65218 *tps;
+       const struct of_device_id *match;
+       int ret;
+
+       match = of_match_device(of_tps65218_match_table, &client->dev);
+       if (!match) {
+               dev_err(&client->dev,
+                       "Failed to find matching dt id\n");
+               return -EINVAL;
+       }
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, tps);
+       tps->dev = &client->dev;
+       tps->irq = client->irq;
+       tps->regmap = devm_regmap_init_i2c(client, &tps65218_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(tps->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       mutex_init(&tps->tps_lock);
+
+       ret = regmap_add_irq_chip(tps->regmap, tps->irq,
+                       IRQF_ONESHOT, 0, &tps65218_irq_chip,
+                       &tps->irq_data);
+       if (ret < 0)
+               return ret;
+
+       ret = of_platform_populate(client->dev.of_node, NULL, NULL,
+                                  &client->dev);
+       if (ret < 0)
+               goto err_irq;
+
+       return 0;
+
+err_irq:
+       regmap_del_irq_chip(tps->irq, tps->irq_data);
+
+       return ret;
+}
+
+static int tps65218_remove(struct i2c_client *client)
+{
+       struct tps65218 *tps = i2c_get_clientdata(client);
+
+       regmap_del_irq_chip(tps->irq, tps->irq_data);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65218_id_table[] = {
+       { "tps65218", TPS65218 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, tps65218_id_table);
+
+static struct i2c_driver tps65218_driver = {
+       .driver         = {
+               .name   = "tps65218",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_tps65218_match_table,
+       },
+       .probe          = tps65218_probe,
+       .remove         = tps65218_remove,
+       .id_table       = tps65218_id_table,
+};
+
+module_i2c_driver(tps65218_driver);
+
+MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
+MODULE_DESCRIPTION("TPS65218 chip family multi-function driver");
+MODULE_LICENSE("GPL v2");
index 1f142d7..460a014 100644 (file)
@@ -255,8 +255,10 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
        ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq,
                IRQF_ONESHOT, pdata->irq_base,
                tps6591x_irqs_chip, &tps65910->irq_data);
-       if (ret < 0)
+       if (ret < 0) {
                dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);
+               tps65910->chip_irq = 0;
+       }
        return ret;
 }
 
@@ -509,6 +511,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
                              regmap_irq_get_domain(tps65910->irq_data));
        if (ret < 0) {
                dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
+               tps65910_irq_exit(tps65910);
                return ret;
        }
 
index 27a518e..1f82d60 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
index d360a83..fbecec7 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/bug.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
index ed71832..e87140b 100644 (file)
@@ -282,11 +282,11 @@ static struct reg_default twl4030_49_defaults[] = {
 static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
-       case 0:
-       case 3:
-       case 40:
-       case 41:
-       case 42:
+       case 0x00:
+       case 0x03:
+       case 0x40:
+       case 0x41:
+       case 0x42:
                return false;
        default:
                return true;
index 9aa6d1e..596b1f6 100644 (file)
@@ -27,7 +27,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/init.h>
 #include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
deleted file mode 100644 (file)
index 4c583e4..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- *
- * TWL4030 MADC module driver-This driver monitors the real time
- * conversion of analog signals like battery temperature,
- * battery type, battery level etc.
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- * J Keerthy <j-keerthy@ti.com>
- *
- * Based on twl4030-madc.c
- * Copyright (C) 2008 Nokia Corporation
- * Mikko Ylinen <mikko.k.ylinen@nokia.com>
- *
- * Amit Kucheria <amit.kucheria@canonical.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/i2c/twl.h>
-#include <linux/i2c/twl4030-madc.h>
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/err.h>
-
-/*
- * struct twl4030_madc_data - a container for madc info
- * @dev - pointer to device structure for madc
- * @lock - mutex protecting this data structure
- * @requests - Array of request struct corresponding to SW1, SW2 and RT
- * @imr - Interrupt mask register of MADC
- * @isr - Interrupt status register of MADC
- */
-struct twl4030_madc_data {
-       struct device *dev;
-       struct mutex lock;      /* mutex protecting this data structure */
-       struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
-       int imr;
-       int isr;
-};
-
-static struct twl4030_madc_data *twl4030_madc;
-
-struct twl4030_prescale_divider_ratios {
-       s16 numerator;
-       s16 denominator;
-};
-
-static const struct twl4030_prescale_divider_ratios
-twl4030_divider_ratios[16] = {
-       {1, 1},         /* CHANNEL 0 No Prescaler */
-       {1, 1},         /* CHANNEL 1 No Prescaler */
-       {6, 10},        /* CHANNEL 2 */
-       {6, 10},        /* CHANNEL 3 */
-       {6, 10},        /* CHANNEL 4 */
-       {6, 10},        /* CHANNEL 5 */
-       {6, 10},        /* CHANNEL 6 */
-       {6, 10},        /* CHANNEL 7 */
-       {3, 14},        /* CHANNEL 8 */
-       {1, 3},         /* CHANNEL 9 */
-       {1, 1},         /* CHANNEL 10 No Prescaler */
-       {15, 100},      /* CHANNEL 11 */
-       {1, 4},         /* CHANNEL 12 */
-       {1, 1},         /* CHANNEL 13 Reserved channels */
-       {1, 1},         /* CHANNEL 14 Reseved channels */
-       {5, 11},        /* CHANNEL 15 */
-};
-
-
-/*
- * Conversion table from -3 to 55 degree Celcius
- */
-static int therm_tbl[] = {
-30800, 29500,  28300,  27100,
-26000, 24900,  23900,  22900,  22000,  21100,  20300,  19400,  18700,  17900,
-17200, 16500,  15900,  15300,  14700,  14100,  13600,  13100,  12600,  12100,
-11600, 11200,  10800,  10400,  10000,  9630,   9280,   8950,   8620,   8310,
-8020,  7730,   7460,   7200,   6950,   6710,   6470,   6250,   6040,   5830,
-5640,  5450,   5260,   5090,   4920,   4760,   4600,   4450,   4310,   4170,
-4040,  3910,   3790,   3670,   3550
-};
-
-/*
- * Structure containing the registers
- * of different conversion methods supported by MADC.
- * Hardware or RT real time conversion request initiated by external host
- * processor for RT Signal conversions.
- * External host processors can also request for non RT conversions
- * SW1 and SW2 software conversions also called asynchronous or GPC request.
- */
-static
-const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
-       [TWL4030_MADC_RT] = {
-                            .sel = TWL4030_MADC_RTSELECT_LSB,
-                            .avg = TWL4030_MADC_RTAVERAGE_LSB,
-                            .rbase = TWL4030_MADC_RTCH0_LSB,
-                            },
-       [TWL4030_MADC_SW1] = {
-                             .sel = TWL4030_MADC_SW1SELECT_LSB,
-                             .avg = TWL4030_MADC_SW1AVERAGE_LSB,
-                             .rbase = TWL4030_MADC_GPCH0_LSB,
-                             .ctrl = TWL4030_MADC_CTRL_SW1,
-                             },
-       [TWL4030_MADC_SW2] = {
-                             .sel = TWL4030_MADC_SW2SELECT_LSB,
-                             .avg = TWL4030_MADC_SW2AVERAGE_LSB,
-                             .rbase = TWL4030_MADC_GPCH0_LSB,
-                             .ctrl = TWL4030_MADC_CTRL_SW2,
-                             },
-};
-
-/*
- * Function to read a particular channel value.
- * @madc - pointer to struct twl4030_madc_data
- * @reg - lsb of ADC Channel
- * If the i2c read fails it returns an error else returns 0.
- */
-static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
-{
-       u8 msb, lsb;
-       int ret;
-       /*
-        * For each ADC channel, we have MSB and LSB register pair. MSB address
-        * is always LSB address+1. reg parameter is the address of LSB register
-        */
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1);
-       if (ret) {
-               dev_err(madc->dev, "unable to read MSB register 0x%X\n",
-                       reg + 1);
-               return ret;
-       }
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg);
-       if (ret) {
-               dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
-               return ret;
-       }
-
-       return (int)(((msb << 8) | lsb) >> 6);
-}
-
-/*
- * Return battery temperature
- * Or < 0 on failure.
- */
-static int twl4030battery_temperature(int raw_volt)
-{
-       u8 val;
-       int temp, curr, volt, res, ret;
-
-       volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
-       /* Getting and calculating the supply current in micro ampers */
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
-               REG_BCICTL2);
-       if (ret < 0)
-               return ret;
-       curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
-       /* Getting and calculating the thermistor resistance in ohms */
-       res = volt * 1000 / curr;
-       /* calculating temperature */
-       for (temp = 58; temp >= 0; temp--) {
-               int actual = therm_tbl[temp];
-
-               if ((actual - res) >= 0)
-                       break;
-       }
-
-       return temp + 1;
-}
-
-static int twl4030battery_current(int raw_volt)
-{
-       int ret;
-       u8 val;
-
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
-               TWL4030_BCI_BCICTL1);
-       if (ret)
-               return ret;
-       if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
-               return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
-       else /* slope of 0.88 mV/mA */
-               return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
-}
-/*
- * Function to read channel values
- * @madc - pointer to twl4030_madc_data struct
- * @reg_base - Base address of the first channel
- * @Channels - 16 bit bitmap. If the bit is set, channel value is read
- * @buf - The channel values are stored here. if read fails error
- * @raw - Return raw values without conversion
- * value is stored
- * Returns the number of successfully read channels.
- */
-static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
-                                     u8 reg_base, unsigned
-                                     long channels, int *buf,
-                                     bool raw)
-{
-       int count = 0, count_req = 0, i;
-       u8 reg;
-
-       for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
-               reg = reg_base + 2 * i;
-               buf[i] = twl4030_madc_channel_raw_read(madc, reg);
-               if (buf[i] < 0) {
-                       dev_err(madc->dev,
-                               "Unable to read register 0x%X\n", reg);
-                       count_req++;
-                       continue;
-               }
-               if (raw) {
-                       count++;
-                       continue;
-               }
-               switch (i) {
-               case 10:
-                       buf[i] = twl4030battery_current(buf[i]);
-                       if (buf[i] < 0) {
-                               dev_err(madc->dev, "err reading current\n");
-                               count_req++;
-                       } else {
-                               count++;
-                               buf[i] = buf[i] - 750;
-                       }
-                       break;
-               case 1:
-                       buf[i] = twl4030battery_temperature(buf[i]);
-                       if (buf[i] < 0) {
-                               dev_err(madc->dev, "err reading temperature\n");
-                               count_req++;
-                       } else {
-                               buf[i] -= 3;
-                               count++;
-                       }
-                       break;
-               default:
-                       count++;
-                       /* Analog Input (V) = conv_result * step_size / R
-                        * conv_result = decimal value of 10-bit conversion
-                        *               result
-                        * step size = 1.5 / (2 ^ 10 -1)
-                        * R = Prescaler ratio for input channels.
-                        * Result given in mV hence multiplied by 1000.
-                        */
-                       buf[i] = (buf[i] * 3 * 1000 *
-                                twl4030_divider_ratios[i].denominator)
-                               / (2 * 1023 *
-                               twl4030_divider_ratios[i].numerator);
-               }
-       }
-       if (count_req)
-               dev_err(madc->dev, "%d channel conversion failed\n", count_req);
-
-       return count;
-}
-
-/*
- * Enables irq.
- * @madc - pointer to twl4030_madc_data struct
- * @id - irq number to be enabled
- * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
- * corresponding to RT, SW1, SW2 conversion requests.
- * If the i2c read fails it returns an error else returns 0.
- */
-static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
-{
-       u8 val;
-       int ret;
-
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
-       if (ret) {
-               dev_err(madc->dev, "unable to read imr register 0x%X\n",
-                       madc->imr);
-               return ret;
-       }
-       val &= ~(1 << id);
-       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
-       if (ret) {
-               dev_err(madc->dev,
-                       "unable to write imr register 0x%X\n", madc->imr);
-               return ret;
-
-       }
-
-       return 0;
-}
-
-/*
- * Disables irq.
- * @madc - pointer to twl4030_madc_data struct
- * @id - irq number to be disabled
- * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
- * corresponding to RT, SW1, SW2 conversion requests.
- * Returns error if i2c read/write fails.
- */
-static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
-{
-       u8 val;
-       int ret;
-
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
-       if (ret) {
-               dev_err(madc->dev, "unable to read imr register 0x%X\n",
-                       madc->imr);
-               return ret;
-       }
-       val |= (1 << id);
-       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
-       if (ret) {
-               dev_err(madc->dev,
-                       "unable to write imr register 0x%X\n", madc->imr);
-               return ret;
-       }
-
-       return 0;
-}
-
-static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
-{
-       struct twl4030_madc_data *madc = _madc;
-       const struct twl4030_madc_conversion_method *method;
-       u8 isr_val, imr_val;
-       int i, len, ret;
-       struct twl4030_madc_request *r;
-
-       mutex_lock(&madc->lock);
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
-       if (ret) {
-               dev_err(madc->dev, "unable to read isr register 0x%X\n",
-                       madc->isr);
-               goto err_i2c;
-       }
-       ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
-       if (ret) {
-               dev_err(madc->dev, "unable to read imr register 0x%X\n",
-                       madc->imr);
-               goto err_i2c;
-       }
-       isr_val &= ~imr_val;
-       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
-               if (!(isr_val & (1 << i)))
-                       continue;
-               ret = twl4030_madc_disable_irq(madc, i);
-               if (ret < 0)
-                       dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
-               madc->requests[i].result_pending = 1;
-       }
-       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
-               r = &madc->requests[i];
-               /* No pending results for this method, move to next one */
-               if (!r->result_pending)
-                       continue;
-               method = &twl4030_conversion_methods[r->method];
-               /* Read results */
-               len = twl4030_madc_read_channels(madc, method->rbase,
-                                                r->channels, r->rbuf, r->raw);
-               /* Return results to caller */
-               if (r->func_cb != NULL) {
-                       r->func_cb(len, r->channels, r->rbuf);
-                       r->func_cb = NULL;
-               }
-               /* Free request */
-               r->result_pending = 0;
-               r->active = 0;
-       }
-       mutex_unlock(&madc->lock);
-
-       return IRQ_HANDLED;
-
-err_i2c:
-       /*
-        * In case of error check whichever request is active
-        * and service the same.
-        */
-       for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
-               r = &madc->requests[i];
-               if (r->active == 0)
-                       continue;
-               method = &twl4030_conversion_methods[r->method];
-               /* Read results */
-               len = twl4030_madc_read_channels(madc, method->rbase,
-                                                r->channels, r->rbuf, r->raw);
-               /* Return results to caller */
-               if (r->func_cb != NULL) {
-                       r->func_cb(len, r->channels, r->rbuf);
-                       r->func_cb = NULL;
-               }
-               /* Free request */
-               r->result_pending = 0;
-               r->active = 0;
-       }
-       mutex_unlock(&madc->lock);
-
-       return IRQ_HANDLED;
-}
-
-static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
-                               struct twl4030_madc_request *req)
-{
-       struct twl4030_madc_request *p;
-       int ret;
-
-       p = &madc->requests[req->method];
-       memcpy(p, req, sizeof(*req));
-       ret = twl4030_madc_enable_irq(madc, req->method);
-       if (ret < 0) {
-               dev_err(madc->dev, "enable irq failed!!\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- * Function which enables the madc conversion
- * by writing to the control register.
- * @madc - pointer to twl4030_madc_data struct
- * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
- * corresponding to RT SW1 or SW2 conversion methods.
- * Returns 0 if succeeds else a negative error value
- */
-static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
-                                        int conv_method)
-{
-       const struct twl4030_madc_conversion_method *method;
-       int ret = 0;
-       method = &twl4030_conversion_methods[conv_method];
-       switch (conv_method) {
-       case TWL4030_MADC_SW1:
-       case TWL4030_MADC_SW2:
-               ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
-                                      TWL4030_MADC_SW_START, method->ctrl);
-               if (ret) {
-                       dev_err(madc->dev,
-                               "unable to write ctrl register 0x%X\n",
-                               method->ctrl);
-                       return ret;
-               }
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-/*
- * Function that waits for conversion to be ready
- * @madc - pointer to twl4030_madc_data struct
- * @timeout_ms - timeout value in milliseconds
- * @status_reg - ctrl register
- * returns 0 if succeeds else a negative error value
- */
-static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
-                                             unsigned int timeout_ms,
-                                             u8 status_reg)
-{
-       unsigned long timeout;
-       int ret;
-
-       timeout = jiffies + msecs_to_jiffies(timeout_ms);
-       do {
-               u8 reg;
-
-               ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
-               if (ret) {
-                       dev_err(madc->dev,
-                               "unable to read status register 0x%X\n",
-                               status_reg);
-                       return ret;
-               }
-               if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
-                       return 0;
-               usleep_range(500, 2000);
-       } while (!time_after(jiffies, timeout));
-       dev_err(madc->dev, "conversion timeout!\n");
-
-       return -EAGAIN;
-}
-
-/*
- * An exported function which can be called from other kernel drivers.
- * @req twl4030_madc_request structure
- * req->rbuf will be filled with read values of channels based on the
- * channel index. If a particular channel reading fails there will
- * be a negative error value in the corresponding array element.
- * returns 0 if succeeds else error value
- */
-int twl4030_madc_conversion(struct twl4030_madc_request *req)
-{
-       const struct twl4030_madc_conversion_method *method;
-       u8 ch_msb, ch_lsb;
-       int ret;
-
-       if (!req || !twl4030_madc)
-               return -EINVAL;
-
-       mutex_lock(&twl4030_madc->lock);
-       if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
-               ret = -EINVAL;
-               goto out;
-       }
-       /* Do we have a conversion request ongoing */
-       if (twl4030_madc->requests[req->method].active) {
-               ret = -EBUSY;
-               goto out;
-       }
-       ch_msb = (req->channels >> 8) & 0xff;
-       ch_lsb = req->channels & 0xff;
-       method = &twl4030_conversion_methods[req->method];
-       /* Select channels to be converted */
-       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
-       if (ret) {
-               dev_err(twl4030_madc->dev,
-                       "unable to write sel register 0x%X\n", method->sel + 1);
-               goto out;
-       }
-       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
-       if (ret) {
-               dev_err(twl4030_madc->dev,
-                       "unable to write sel register 0x%X\n", method->sel + 1);
-               goto out;
-       }
-       /* Select averaging for all channels if do_avg is set */
-       if (req->do_avg) {
-               ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
-                                      ch_msb, method->avg + 1);
-               if (ret) {
-                       dev_err(twl4030_madc->dev,
-                               "unable to write avg register 0x%X\n",
-                               method->avg + 1);
-                       goto out;
-               }
-               ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
-                                      ch_lsb, method->avg);
-               if (ret) {
-                       dev_err(twl4030_madc->dev,
-                               "unable to write sel reg 0x%X\n",
-                               method->sel + 1);
-                       goto out;
-               }
-       }
-       if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
-               ret = twl4030_madc_set_irq(twl4030_madc, req);
-               if (ret < 0)
-                       goto out;
-               ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
-               if (ret < 0)
-                       goto out;
-               twl4030_madc->requests[req->method].active = 1;
-               ret = 0;
-               goto out;
-       }
-       /* With RT method we should not be here anymore */
-       if (req->method == TWL4030_MADC_RT) {
-               ret = -EINVAL;
-               goto out;
-       }
-       ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
-       if (ret < 0)
-               goto out;
-       twl4030_madc->requests[req->method].active = 1;
-       /* Wait until conversion is ready (ctrl register returns EOC) */
-       ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
-       if (ret) {
-               twl4030_madc->requests[req->method].active = 0;
-               goto out;
-       }
-       ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
-                                        req->channels, req->rbuf, req->raw);
-       twl4030_madc->requests[req->method].active = 0;
-
-out:
-       mutex_unlock(&twl4030_madc->lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
-
-/*
- * Return channel value
- * Or < 0 on failure.
- */
-int twl4030_get_madc_conversion(int channel_no)
-{
-       struct twl4030_madc_request req;
-       int temp = 0;
-       int ret;
-
-       req.channels = (1 << channel_no);
-       req.method = TWL4030_MADC_SW2;
-       req.active = 0;
-       req.func_cb = NULL;
-       ret = twl4030_madc_conversion(&req);
-       if (ret < 0)
-               return ret;
-       if (req.rbuf[channel_no] > 0)
-               temp = req.rbuf[channel_no];
-
-       return temp;
-}
-EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
-
-/*
- * Function to enable or disable bias current for
- * main battery type reading or temperature sensing
- * @madc - pointer to twl4030_madc_data struct
- * @chan - can be one of the two values
- * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
- * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
- * sensing
- * @on - enable or disable chan.
- */
-static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
-                                             int chan, int on)
-{
-       int ret;
-       u8 regval;
-
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
-                             &regval, TWL4030_BCI_BCICTL1);
-       if (ret) {
-               dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
-                       TWL4030_BCI_BCICTL1);
-               return ret;
-       }
-       if (on)
-               regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
-       else
-               regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
-       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
-                              regval, TWL4030_BCI_BCICTL1);
-       if (ret) {
-               dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
-                       TWL4030_BCI_BCICTL1);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- * Function that sets MADC software power on bit to enable MADC
- * @madc - pointer to twl4030_madc_data struct
- * @on - Enable or disable MADC software powen on bit.
- * returns error if i2c read/write fails else 0
- */
-static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
-{
-       u8 regval;
-       int ret;
-
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
-                             &regval, TWL4030_MADC_CTRL1);
-       if (ret) {
-               dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
-                       TWL4030_MADC_CTRL1);
-               return ret;
-       }
-       if (on)
-               regval |= TWL4030_MADC_MADCON;
-       else
-               regval &= ~TWL4030_MADC_MADCON;
-       ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
-       if (ret) {
-               dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
-                       TWL4030_MADC_CTRL1);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- * Initialize MADC and request for threaded irq
- */
-static int twl4030_madc_probe(struct platform_device *pdev)
-{
-       struct twl4030_madc_data *madc;
-       struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       int ret;
-       u8 regval;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "platform_data not available\n");
-               return -EINVAL;
-       }
-       madc = kzalloc(sizeof(*madc), GFP_KERNEL);
-       if (!madc)
-               return -ENOMEM;
-
-       madc->dev = &pdev->dev;
-
-       /*
-        * Phoenix provides 2 interrupt lines. The first one is connected to
-        * the OMAP. The other one can be connected to the other processor such
-        * as modem. Hence two separate ISR and IMR registers.
-        */
-       madc->imr = (pdata->irq_line == 1) ?
-           TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
-       madc->isr = (pdata->irq_line == 1) ?
-           TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
-       ret = twl4030_madc_set_power(madc, 1);
-       if (ret < 0)
-               goto err_power;
-       ret = twl4030_madc_set_current_generator(madc, 0, 1);
-       if (ret < 0)
-               goto err_current_generator;
-
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
-                             &regval, TWL4030_BCI_BCICTL1);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
-                       TWL4030_BCI_BCICTL1);
-               goto err_i2c;
-       }
-       regval |= TWL4030_BCI_MESBAT;
-       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
-                              regval, TWL4030_BCI_BCICTL1);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
-                       TWL4030_BCI_BCICTL1);
-               goto err_i2c;
-       }
-
-       /* Check that MADC clock is on */
-       ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
-                               TWL4030_REG_GPBR1);
-               goto err_i2c;
-       }
-
-       /* If MADC clk is not on, turn it on */
-       if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
-               dev_info(&pdev->dev, "clk disabled, enabling\n");
-               regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
-               ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
-                                      TWL4030_REG_GPBR1);
-               if (ret) {
-                       dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
-                                       TWL4030_REG_GPBR1);
-                       goto err_i2c;
-               }
-       }
-
-       platform_set_drvdata(pdev, madc);
-       mutex_init(&madc->lock);
-       ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
-                                  twl4030_madc_threaded_irq_handler,
-                                  IRQF_TRIGGER_RISING, "twl4030_madc", madc);
-       if (ret) {
-               dev_dbg(&pdev->dev, "could not request irq\n");
-               goto err_i2c;
-       }
-       twl4030_madc = madc;
-       return 0;
-err_i2c:
-       twl4030_madc_set_current_generator(madc, 0, 0);
-err_current_generator:
-       twl4030_madc_set_power(madc, 0);
-err_power:
-       kfree(madc);
-
-       return ret;
-}
-
-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);
-       twl4030_madc_set_current_generator(madc, 0, 0);
-       twl4030_madc_set_power(madc, 0);
-       kfree(madc);
-
-       return 0;
-}
-
-static struct platform_driver twl4030_madc_driver = {
-       .probe = twl4030_madc_probe,
-       .remove = twl4030_madc_remove,
-       .driver = {
-                  .name = "twl4030_madc",
-                  .owner = THIS_MODULE,
-                  },
-};
-
-module_platform_driver(twl4030_madc_driver);
-
-MODULE_DESCRIPTION("TWL4030 ADC driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("J Keerthy");
-MODULE_ALIAS("platform:twl4030_madc");
index 18a607e..a6bb17d 100644 (file)
@@ -31,7 +31,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/init.h>
 #include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 75316fb..6e88f25 100644 (file)
@@ -661,6 +661,11 @@ static int twl6040_probe(struct i2c_client *client,
        init_completion(&twl6040->ready);
 
        twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+       if (twl6040->rev < 0) {
+               dev_err(&client->dev, "Failed to read revision register: %d\n",
+                       twl6040->rev);
+               goto gpio_err;
+       }
 
        /* ERRATA: Automatic power-up is not possible in ES1.0 */
        if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
@@ -703,7 +708,6 @@ static int twl6040_probe(struct i2c_client *client,
        }
 
        /* dual-access registers controlled by I2C only */
-       twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
        regmap_register_patch(twl6040->regmap, twl6040_patch,
                              ARRAY_SIZE(twl6040_patch));
 
index 0313f83..153d595 100644 (file)
@@ -742,9 +742,7 @@ static int ucb1x00_resume(struct device *dev)
 }
 #endif
 
-static const struct dev_pm_ops ucb1x00_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
-};
+static SIMPLE_DEV_PM_OPS(ucb1x00_pm_ops, ucb1x00_suspend, ucb1x00_resume);
 
 static struct mcp_driver ucb1x00_driver = {
        .drv            = {
index 84ce6b9..d0db89d 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 #include <linux/completion.h>
 #include <linux/export.h>
-#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -27,7 +26,7 @@
 
 #define VEXPRESS_CONFIG_MAX_BRIDGES 2
 
-struct vexpress_config_bridge {
+static struct vexpress_config_bridge {
        struct device_node *node;
        struct vexpress_config_bridge_info *info;
        struct list_head transactions;
index 981bef4..35281e8 100644 (file)
@@ -168,7 +168,7 @@ static void *vexpress_sysreg_config_func_get(struct device *dev,
                struct device_node *node)
 {
        struct vexpress_sysreg_config_func *config_func;
-       u32 site;
+       u32 site = 0;
        u32 position = 0;
        u32 dcc = 0;
        u32 func_device[2];
index bffc584..070f8cf 100644 (file)
@@ -73,6 +73,7 @@ static const struct reg_default wm5102_revb_patch[] = {
        { 0x171, 0x0000 },
        { 0x35E, 0x000C },
        { 0x2D4, 0x0000 },
+       { 0x4DC, 0x0900 },
        { 0x80, 0x0000 },
 };
 
@@ -1839,6 +1840,23 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP1_STATUS_1:
        case ARIZONA_DSP1_STATUS_2:
        case ARIZONA_DSP1_STATUS_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_1:
+       case ARIZONA_DSP1_WDMA_BUFFER_2:
+       case ARIZONA_DSP1_WDMA_BUFFER_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_5:
+       case ARIZONA_DSP1_WDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_BUFFER_7:
+       case ARIZONA_DSP1_WDMA_BUFFER_8:
+       case ARIZONA_DSP1_RDMA_BUFFER_1:
+       case ARIZONA_DSP1_RDMA_BUFFER_2:
+       case ARIZONA_DSP1_RDMA_BUFFER_3:
+       case ARIZONA_DSP1_RDMA_BUFFER_4:
+       case ARIZONA_DSP1_RDMA_BUFFER_5:
+       case ARIZONA_DSP1_RDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_CONFIG_1:
+       case ARIZONA_DSP1_WDMA_CONFIG_2:
+       case ARIZONA_DSP1_RDMA_CONFIG_1:
        case ARIZONA_DSP1_SCRATCH_0:
        case ARIZONA_DSP1_SCRATCH_1:
        case ARIZONA_DSP1_SCRATCH_2:
@@ -1894,9 +1912,27 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_AOD_IRQ1:
        case ARIZONA_AOD_IRQ2:
        case ARIZONA_AOD_IRQ_RAW_STATUS:
+       case ARIZONA_DSP1_CLOCKING_1:
        case ARIZONA_DSP1_STATUS_1:
        case ARIZONA_DSP1_STATUS_2:
        case ARIZONA_DSP1_STATUS_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_1:
+       case ARIZONA_DSP1_WDMA_BUFFER_2:
+       case ARIZONA_DSP1_WDMA_BUFFER_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_5:
+       case ARIZONA_DSP1_WDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_BUFFER_7:
+       case ARIZONA_DSP1_WDMA_BUFFER_8:
+       case ARIZONA_DSP1_RDMA_BUFFER_1:
+       case ARIZONA_DSP1_RDMA_BUFFER_2:
+       case ARIZONA_DSP1_RDMA_BUFFER_3:
+       case ARIZONA_DSP1_RDMA_BUFFER_4:
+       case ARIZONA_DSP1_RDMA_BUFFER_5:
+       case ARIZONA_DSP1_RDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_CONFIG_1:
+       case ARIZONA_DSP1_WDMA_CONFIG_2:
+       case ARIZONA_DSP1_RDMA_CONFIG_1:
        case ARIZONA_DSP1_SCRATCH_0:
        case ARIZONA_DSP1_SCRATCH_1:
        case ARIZONA_DSP1_SCRATCH_2:
index 11632f1..1942b6f 100644 (file)
@@ -538,7 +538,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 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 */
+       { 0x0000029B, 0x0028 },    /* R667   - Headphone Detect 1 */
        { 0x0000029C, 0x0000 },    /* R668   - Headphone Detect 2 */
        { 0x000002A2, 0x0000 },    /* R674   - Micd clamp control */
        { 0x000002A3, 0x1102 },    /* R675   - Mic Detect 1 */
@@ -2461,6 +2461,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP1_STATUS_1:
        case ARIZONA_DSP1_STATUS_2:
        case ARIZONA_DSP1_STATUS_3:
+       case ARIZONA_DSP1_STATUS_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_1:
+       case ARIZONA_DSP1_WDMA_BUFFER_2:
+       case ARIZONA_DSP1_WDMA_BUFFER_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_5:
+       case ARIZONA_DSP1_WDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_BUFFER_7:
+       case ARIZONA_DSP1_WDMA_BUFFER_8:
+       case ARIZONA_DSP1_RDMA_BUFFER_1:
+       case ARIZONA_DSP1_RDMA_BUFFER_2:
+       case ARIZONA_DSP1_RDMA_BUFFER_3:
+       case ARIZONA_DSP1_RDMA_BUFFER_4:
+       case ARIZONA_DSP1_RDMA_BUFFER_5:
+       case ARIZONA_DSP1_RDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_CONFIG_1:
+       case ARIZONA_DSP1_WDMA_CONFIG_2:
+       case ARIZONA_DSP1_WDMA_OFFSET_1:
+       case ARIZONA_DSP1_RDMA_CONFIG_1:
+       case ARIZONA_DSP1_RDMA_OFFSET_1:
+       case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP1_SCRATCH_0:
        case ARIZONA_DSP1_SCRATCH_1:
        case ARIZONA_DSP1_SCRATCH_2:
@@ -2470,6 +2491,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP2_STATUS_1:
        case ARIZONA_DSP2_STATUS_2:
        case ARIZONA_DSP2_STATUS_3:
+       case ARIZONA_DSP2_STATUS_4:
+       case ARIZONA_DSP2_WDMA_BUFFER_1:
+       case ARIZONA_DSP2_WDMA_BUFFER_2:
+       case ARIZONA_DSP2_WDMA_BUFFER_3:
+       case ARIZONA_DSP2_WDMA_BUFFER_4:
+       case ARIZONA_DSP2_WDMA_BUFFER_5:
+       case ARIZONA_DSP2_WDMA_BUFFER_6:
+       case ARIZONA_DSP2_WDMA_BUFFER_7:
+       case ARIZONA_DSP2_WDMA_BUFFER_8:
+       case ARIZONA_DSP2_RDMA_BUFFER_1:
+       case ARIZONA_DSP2_RDMA_BUFFER_2:
+       case ARIZONA_DSP2_RDMA_BUFFER_3:
+       case ARIZONA_DSP2_RDMA_BUFFER_4:
+       case ARIZONA_DSP2_RDMA_BUFFER_5:
+       case ARIZONA_DSP2_RDMA_BUFFER_6:
+       case ARIZONA_DSP2_WDMA_CONFIG_1:
+       case ARIZONA_DSP2_WDMA_CONFIG_2:
+       case ARIZONA_DSP2_WDMA_OFFSET_1:
+       case ARIZONA_DSP2_RDMA_CONFIG_1:
+       case ARIZONA_DSP2_RDMA_OFFSET_1:
+       case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP2_SCRATCH_0:
        case ARIZONA_DSP2_SCRATCH_1:
        case ARIZONA_DSP2_SCRATCH_2:
@@ -2479,6 +2521,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP3_STATUS_1:
        case ARIZONA_DSP3_STATUS_2:
        case ARIZONA_DSP3_STATUS_3:
+       case ARIZONA_DSP3_STATUS_4:
+       case ARIZONA_DSP3_WDMA_BUFFER_1:
+       case ARIZONA_DSP3_WDMA_BUFFER_2:
+       case ARIZONA_DSP3_WDMA_BUFFER_3:
+       case ARIZONA_DSP3_WDMA_BUFFER_4:
+       case ARIZONA_DSP3_WDMA_BUFFER_5:
+       case ARIZONA_DSP3_WDMA_BUFFER_6:
+       case ARIZONA_DSP3_WDMA_BUFFER_7:
+       case ARIZONA_DSP3_WDMA_BUFFER_8:
+       case ARIZONA_DSP3_RDMA_BUFFER_1:
+       case ARIZONA_DSP3_RDMA_BUFFER_2:
+       case ARIZONA_DSP3_RDMA_BUFFER_3:
+       case ARIZONA_DSP3_RDMA_BUFFER_4:
+       case ARIZONA_DSP3_RDMA_BUFFER_5:
+       case ARIZONA_DSP3_RDMA_BUFFER_6:
+       case ARIZONA_DSP3_WDMA_CONFIG_1:
+       case ARIZONA_DSP3_WDMA_CONFIG_2:
+       case ARIZONA_DSP3_WDMA_OFFSET_1:
+       case ARIZONA_DSP3_RDMA_CONFIG_1:
+       case ARIZONA_DSP3_RDMA_OFFSET_1:
+       case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP3_SCRATCH_0:
        case ARIZONA_DSP3_SCRATCH_1:
        case ARIZONA_DSP3_SCRATCH_2:
@@ -2488,6 +2551,27 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP4_STATUS_1:
        case ARIZONA_DSP4_STATUS_2:
        case ARIZONA_DSP4_STATUS_3:
+       case ARIZONA_DSP4_STATUS_4:
+       case ARIZONA_DSP4_WDMA_BUFFER_1:
+       case ARIZONA_DSP4_WDMA_BUFFER_2:
+       case ARIZONA_DSP4_WDMA_BUFFER_3:
+       case ARIZONA_DSP4_WDMA_BUFFER_4:
+       case ARIZONA_DSP4_WDMA_BUFFER_5:
+       case ARIZONA_DSP4_WDMA_BUFFER_6:
+       case ARIZONA_DSP4_WDMA_BUFFER_7:
+       case ARIZONA_DSP4_WDMA_BUFFER_8:
+       case ARIZONA_DSP4_RDMA_BUFFER_1:
+       case ARIZONA_DSP4_RDMA_BUFFER_2:
+       case ARIZONA_DSP4_RDMA_BUFFER_3:
+       case ARIZONA_DSP4_RDMA_BUFFER_4:
+       case ARIZONA_DSP4_RDMA_BUFFER_5:
+       case ARIZONA_DSP4_RDMA_BUFFER_6:
+       case ARIZONA_DSP4_WDMA_CONFIG_1:
+       case ARIZONA_DSP4_WDMA_CONFIG_2:
+       case ARIZONA_DSP4_WDMA_OFFSET_1:
+       case ARIZONA_DSP4_RDMA_CONFIG_1:
+       case ARIZONA_DSP4_RDMA_OFFSET_1:
+       case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP4_SCRATCH_0:
        case ARIZONA_DSP4_SCRATCH_1:
        case ARIZONA_DSP4_SCRATCH_2:
@@ -2543,31 +2627,119 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP1_STATUS_1:
        case ARIZONA_DSP1_STATUS_2:
        case ARIZONA_DSP1_STATUS_3:
+       case ARIZONA_DSP1_STATUS_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_1:
+       case ARIZONA_DSP1_WDMA_BUFFER_2:
+       case ARIZONA_DSP1_WDMA_BUFFER_3:
+       case ARIZONA_DSP1_WDMA_BUFFER_4:
+       case ARIZONA_DSP1_WDMA_BUFFER_5:
+       case ARIZONA_DSP1_WDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_BUFFER_7:
+       case ARIZONA_DSP1_WDMA_BUFFER_8:
+       case ARIZONA_DSP1_RDMA_BUFFER_1:
+       case ARIZONA_DSP1_RDMA_BUFFER_2:
+       case ARIZONA_DSP1_RDMA_BUFFER_3:
+       case ARIZONA_DSP1_RDMA_BUFFER_4:
+       case ARIZONA_DSP1_RDMA_BUFFER_5:
+       case ARIZONA_DSP1_RDMA_BUFFER_6:
+       case ARIZONA_DSP1_WDMA_CONFIG_1:
+       case ARIZONA_DSP1_WDMA_CONFIG_2:
+       case ARIZONA_DSP1_WDMA_OFFSET_1:
+       case ARIZONA_DSP1_RDMA_CONFIG_1:
+       case ARIZONA_DSP1_RDMA_OFFSET_1:
+       case ARIZONA_DSP1_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP1_SCRATCH_0:
        case ARIZONA_DSP1_SCRATCH_1:
        case ARIZONA_DSP1_SCRATCH_2:
        case ARIZONA_DSP1_SCRATCH_3:
+       case ARIZONA_DSP1_CLOCKING_1:
        case ARIZONA_DSP2_STATUS_1:
        case ARIZONA_DSP2_STATUS_2:
        case ARIZONA_DSP2_STATUS_3:
+       case ARIZONA_DSP2_STATUS_4:
+       case ARIZONA_DSP2_WDMA_BUFFER_1:
+       case ARIZONA_DSP2_WDMA_BUFFER_2:
+       case ARIZONA_DSP2_WDMA_BUFFER_3:
+       case ARIZONA_DSP2_WDMA_BUFFER_4:
+       case ARIZONA_DSP2_WDMA_BUFFER_5:
+       case ARIZONA_DSP2_WDMA_BUFFER_6:
+       case ARIZONA_DSP2_WDMA_BUFFER_7:
+       case ARIZONA_DSP2_WDMA_BUFFER_8:
+       case ARIZONA_DSP2_RDMA_BUFFER_1:
+       case ARIZONA_DSP2_RDMA_BUFFER_2:
+       case ARIZONA_DSP2_RDMA_BUFFER_3:
+       case ARIZONA_DSP2_RDMA_BUFFER_4:
+       case ARIZONA_DSP2_RDMA_BUFFER_5:
+       case ARIZONA_DSP2_RDMA_BUFFER_6:
+       case ARIZONA_DSP2_WDMA_CONFIG_1:
+       case ARIZONA_DSP2_WDMA_CONFIG_2:
+       case ARIZONA_DSP2_WDMA_OFFSET_1:
+       case ARIZONA_DSP2_RDMA_CONFIG_1:
+       case ARIZONA_DSP2_RDMA_OFFSET_1:
+       case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP2_SCRATCH_0:
        case ARIZONA_DSP2_SCRATCH_1:
        case ARIZONA_DSP2_SCRATCH_2:
        case ARIZONA_DSP2_SCRATCH_3:
+       case ARIZONA_DSP2_CLOCKING_1:
        case ARIZONA_DSP3_STATUS_1:
        case ARIZONA_DSP3_STATUS_2:
        case ARIZONA_DSP3_STATUS_3:
+       case ARIZONA_DSP3_STATUS_4:
+       case ARIZONA_DSP3_WDMA_BUFFER_1:
+       case ARIZONA_DSP3_WDMA_BUFFER_2:
+       case ARIZONA_DSP3_WDMA_BUFFER_3:
+       case ARIZONA_DSP3_WDMA_BUFFER_4:
+       case ARIZONA_DSP3_WDMA_BUFFER_5:
+       case ARIZONA_DSP3_WDMA_BUFFER_6:
+       case ARIZONA_DSP3_WDMA_BUFFER_7:
+       case ARIZONA_DSP3_WDMA_BUFFER_8:
+       case ARIZONA_DSP3_RDMA_BUFFER_1:
+       case ARIZONA_DSP3_RDMA_BUFFER_2:
+       case ARIZONA_DSP3_RDMA_BUFFER_3:
+       case ARIZONA_DSP3_RDMA_BUFFER_4:
+       case ARIZONA_DSP3_RDMA_BUFFER_5:
+       case ARIZONA_DSP3_RDMA_BUFFER_6:
+       case ARIZONA_DSP3_WDMA_CONFIG_1:
+       case ARIZONA_DSP3_WDMA_CONFIG_2:
+       case ARIZONA_DSP3_WDMA_OFFSET_1:
+       case ARIZONA_DSP3_RDMA_CONFIG_1:
+       case ARIZONA_DSP3_RDMA_OFFSET_1:
+       case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP3_SCRATCH_0:
        case ARIZONA_DSP3_SCRATCH_1:
        case ARIZONA_DSP3_SCRATCH_2:
        case ARIZONA_DSP3_SCRATCH_3:
+       case ARIZONA_DSP3_CLOCKING_1:
        case ARIZONA_DSP4_STATUS_1:
        case ARIZONA_DSP4_STATUS_2:
        case ARIZONA_DSP4_STATUS_3:
+       case ARIZONA_DSP4_STATUS_4:
+       case ARIZONA_DSP4_WDMA_BUFFER_1:
+       case ARIZONA_DSP4_WDMA_BUFFER_2:
+       case ARIZONA_DSP4_WDMA_BUFFER_3:
+       case ARIZONA_DSP4_WDMA_BUFFER_4:
+       case ARIZONA_DSP4_WDMA_BUFFER_5:
+       case ARIZONA_DSP4_WDMA_BUFFER_6:
+       case ARIZONA_DSP4_WDMA_BUFFER_7:
+       case ARIZONA_DSP4_WDMA_BUFFER_8:
+       case ARIZONA_DSP4_RDMA_BUFFER_1:
+       case ARIZONA_DSP4_RDMA_BUFFER_2:
+       case ARIZONA_DSP4_RDMA_BUFFER_3:
+       case ARIZONA_DSP4_RDMA_BUFFER_4:
+       case ARIZONA_DSP4_RDMA_BUFFER_5:
+       case ARIZONA_DSP4_RDMA_BUFFER_6:
+       case ARIZONA_DSP4_WDMA_CONFIG_1:
+       case ARIZONA_DSP4_WDMA_CONFIG_2:
+       case ARIZONA_DSP4_WDMA_OFFSET_1:
+       case ARIZONA_DSP4_RDMA_CONFIG_1:
+       case ARIZONA_DSP4_RDMA_OFFSET_1:
+       case ARIZONA_DSP4_EXTERNAL_START_SELECT_1:
        case ARIZONA_DSP4_SCRATCH_0:
        case ARIZONA_DSP4_SCRATCH_1:
        case ARIZONA_DSP4_SCRATCH_2:
        case ARIZONA_DSP4_SCRATCH_3:
+       case ARIZONA_DSP4_CLOCKING_1:
                return true;
        default:
                return wm5110_is_adsp_memory(dev, reg);
index 7c1ae24..4ab527f 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/bug.h>
 #include <linux/device.h>
index 624ff90..cd01f79 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/bug.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
index d66d256..e5eae75 100644 (file)
@@ -161,31 +161,19 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm8400 *wm8400;
-       int ret;
 
        wm8400 = devm_kzalloc(&i2c->dev, sizeof(struct wm8400), GFP_KERNEL);
-       if (wm8400 == NULL) {
-               ret = -ENOMEM;
-               goto err;
-       }
+       if (!wm8400)
+               return -ENOMEM;
 
        wm8400->regmap = devm_regmap_init_i2c(i2c, &wm8400_regmap_config);
-       if (IS_ERR(wm8400->regmap)) {
-               ret = PTR_ERR(wm8400->regmap);
-               goto err;
-       }
+       if (IS_ERR(wm8400->regmap))
+               return PTR_ERR(wm8400->regmap);
 
        wm8400->dev = &i2c->dev;
        i2c_set_clientdata(i2c, wm8400);
 
-       ret = wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       return ret;
+       return wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
 }
 
 static int wm8400_i2c_remove(struct i2c_client *i2c)
index 0e6c033..0ba1b7c 100644 (file)
@@ -48,7 +48,7 @@
 
 /* Module and version information */
 #define DRV_NAME       "iTCO_wdt"
-#define DRV_VERSION    "1.10"
+#define DRV_VERSION    "1.11"
 
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
@@ -92,9 +92,12 @@ static struct {              /* this is private data for the iTCO_wdt device */
        unsigned int iTCO_version;
        struct resource *tco_res;
        struct resource *smi_res;
-       struct resource *gcs_res;
-       /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
-       unsigned long __iomem *gcs;
+       /*
+        * NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2),
+        * or memory-mapped PMC register bit 4 (TCO version 3).
+        */
+       struct resource *gcs_pmc_res;
+       unsigned long __iomem *gcs_pmc;
        /* the lock for io operations */
        spinlock_t io_lock;
        struct platform_device *dev;
@@ -125,11 +128,19 @@ MODULE_PARM_DESC(turn_SMI_watchdog_clear_off,
  * Some TCO specific functions
  */
 
-static inline unsigned int seconds_to_ticks(int seconds)
+/*
+ * The iTCO v1 and v2's internal timer is stored as ticks which decrement
+ * every 0.6 seconds.  v3's internal timer is stored as seconds (some
+ * datasheets incorrectly state 0.6 seconds).
+ */
+static inline unsigned int seconds_to_ticks(int secs)
 {
-       /* the internal timer is stored as ticks which decrement
-        * every 0.6 seconds */
-       return (seconds * 10) / 6;
+       return iTCO_wdt_private.iTCO_version == 3 ? secs : (secs * 10) / 6;
+}
+
+static inline unsigned int ticks_to_seconds(int ticks)
+{
+       return iTCO_wdt_private.iTCO_version == 3 ? ticks : (ticks * 6) / 10;
 }
 
 static void iTCO_wdt_set_NO_REBOOT_bit(void)
@@ -137,10 +148,14 @@ static void iTCO_wdt_set_NO_REBOOT_bit(void)
        u32 val32;
 
        /* Set the NO_REBOOT bit: this disables reboots */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               val32 = readl(iTCO_wdt_private.gcs);
+       if (iTCO_wdt_private.iTCO_version == 3) {
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
+               val32 |= 0x00000010;
+               writel(val32, iTCO_wdt_private.gcs_pmc);
+       } else if (iTCO_wdt_private.iTCO_version == 2) {
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
                val32 |= 0x00000020;
-               writel(val32, iTCO_wdt_private.gcs);
+               writel(val32, iTCO_wdt_private.gcs_pmc);
        } else if (iTCO_wdt_private.iTCO_version == 1) {
                pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
                val32 |= 0x00000002;
@@ -154,12 +169,20 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
        u32 val32;
 
        /* Unset the NO_REBOOT bit: this enables reboots */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               val32 = readl(iTCO_wdt_private.gcs);
+       if (iTCO_wdt_private.iTCO_version == 3) {
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
+               val32 &= 0xffffffef;
+               writel(val32, iTCO_wdt_private.gcs_pmc);
+
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
+               if (val32 & 0x00000010)
+                       ret = -EIO;
+       } else if (iTCO_wdt_private.iTCO_version == 2) {
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
                val32 &= 0xffffffdf;
-               writel(val32, iTCO_wdt_private.gcs);
+               writel(val32, iTCO_wdt_private.gcs_pmc);
 
-               val32 = readl(iTCO_wdt_private.gcs);
+               val32 = readl(iTCO_wdt_private.gcs_pmc);
                if (val32 & 0x00000020)
                        ret = -EIO;
        } else if (iTCO_wdt_private.iTCO_version == 1) {
@@ -192,7 +215,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
 
        /* Force the timer to its reload value by writing to the TCO_RLD
           register */
-       if (iTCO_wdt_private.iTCO_version == 2)
+       if (iTCO_wdt_private.iTCO_version >= 2)
                outw(0x01, TCO_RLD);
        else if (iTCO_wdt_private.iTCO_version == 1)
                outb(0x01, TCO_RLD);
@@ -240,9 +263,9 @@ static int iTCO_wdt_ping(struct watchdog_device *wd_dev)
        iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, wd_dev->timeout);
 
        /* Reload the timer by writing to the TCO Timer Counter register */
-       if (iTCO_wdt_private.iTCO_version == 2)
+       if (iTCO_wdt_private.iTCO_version >= 2) {
                outw(0x01, TCO_RLD);
-       else if (iTCO_wdt_private.iTCO_version == 1) {
+       else if (iTCO_wdt_private.iTCO_version == 1) {
                /* Reset the timeout status bit so that the timer
                 * needs to count down twice again before rebooting */
                outw(0x0008, TCO1_STS); /* write 1 to clear bit */
@@ -270,14 +293,14 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
        /* "Values of 0h-3h are ignored and should not be attempted" */
        if (tmrval < 0x04)
                return -EINVAL;
-       if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
+       if (((iTCO_wdt_private.iTCO_version >= 2) && (tmrval > 0x3ff)) ||
            ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
                return -EINVAL;
 
        iTCO_vendor_pre_set_heartbeat(tmrval);
 
        /* Write new heartbeat to watchdog */
-       if (iTCO_wdt_private.iTCO_version == 2) {
+       if (iTCO_wdt_private.iTCO_version >= 2) {
                spin_lock(&iTCO_wdt_private.io_lock);
                val16 = inw(TCOv2_TMR);
                val16 &= 0xfc00;
@@ -312,13 +335,13 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
        unsigned int time_left = 0;
 
        /* read the TCO Timer */
-       if (iTCO_wdt_private.iTCO_version == 2) {
+       if (iTCO_wdt_private.iTCO_version >= 2) {
                spin_lock(&iTCO_wdt_private.io_lock);
                val16 = inw(TCO_RLD);
                val16 &= 0x3ff;
                spin_unlock(&iTCO_wdt_private.io_lock);
 
-               time_left = (val16 * 6) / 10;
+               time_left = ticks_to_seconds(val16);
        } else if (iTCO_wdt_private.iTCO_version == 1) {
                spin_lock(&iTCO_wdt_private.io_lock);
                val8 = inb(TCO_RLD);
@@ -327,7 +350,7 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
                        val8 += (inb(TCOv1_TMR) & 0x3f);
                spin_unlock(&iTCO_wdt_private.io_lock);
 
-               time_left = (val8 * 6) / 10;
+               time_left = ticks_to_seconds(val8);
        }
        return time_left;
 }
@@ -376,16 +399,16 @@ static void iTCO_wdt_cleanup(void)
                        resource_size(iTCO_wdt_private.tco_res));
        release_region(iTCO_wdt_private.smi_res->start,
                        resource_size(iTCO_wdt_private.smi_res));
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               iounmap(iTCO_wdt_private.gcs);
-               release_mem_region(iTCO_wdt_private.gcs_res->start,
-                               resource_size(iTCO_wdt_private.gcs_res));
+       if (iTCO_wdt_private.iTCO_version >= 2) {
+               iounmap(iTCO_wdt_private.gcs_pmc);
+               release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+                               resource_size(iTCO_wdt_private.gcs_pmc_res));
        }
 
        iTCO_wdt_private.tco_res = NULL;
        iTCO_wdt_private.smi_res = NULL;
-       iTCO_wdt_private.gcs_res = NULL;
-       iTCO_wdt_private.gcs = NULL;
+       iTCO_wdt_private.gcs_pmc_res = NULL;
+       iTCO_wdt_private.gcs_pmc = NULL;
 }
 
 static int iTCO_wdt_probe(struct platform_device *dev)
@@ -414,27 +437,27 @@ static int iTCO_wdt_probe(struct platform_device *dev)
        iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent);
 
        /*
-        * Get the Memory-Mapped GCS register, we need it for the
-        * NO_REBOOT flag (TCO v2).
+        * Get the Memory-Mapped GCS or PMC register, we need it for the
+        * NO_REBOOT flag (TCO v2 and v3).
         */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               iTCO_wdt_private.gcs_res = platform_get_resource(dev,
+       if (iTCO_wdt_private.iTCO_version >= 2) {
+               iTCO_wdt_private.gcs_pmc_res = platform_get_resource(dev,
                                                        IORESOURCE_MEM,
-                                                       ICH_RES_MEM_GCS);
+                                                       ICH_RES_MEM_GCS_PMC);
 
-               if (!iTCO_wdt_private.gcs_res)
+               if (!iTCO_wdt_private.gcs_pmc_res)
                        goto out;
 
-               if (!request_mem_region(iTCO_wdt_private.gcs_res->start,
-                       resource_size(iTCO_wdt_private.gcs_res), dev->name)) {
+               if (!request_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+                       resource_size(iTCO_wdt_private.gcs_pmc_res), dev->name)) {
                        ret = -EBUSY;
                        goto out;
                }
-               iTCO_wdt_private.gcs = ioremap(iTCO_wdt_private.gcs_res->start,
-                       resource_size(iTCO_wdt_private.gcs_res));
-               if (!iTCO_wdt_private.gcs) {
+               iTCO_wdt_private.gcs_pmc = ioremap(iTCO_wdt_private.gcs_pmc_res->start,
+                       resource_size(iTCO_wdt_private.gcs_pmc_res));
+               if (!iTCO_wdt_private.gcs_pmc) {
                        ret = -EIO;
-                       goto unreg_gcs;
+                       goto unreg_gcs_pmc;
                }
        }
 
@@ -442,7 +465,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
        if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
                pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
                ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
-               goto unmap_gcs;
+               goto unmap_gcs_pmc;
        }
 
        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
@@ -454,7 +477,7 @@ static int iTCO_wdt_probe(struct platform_device *dev)
                pr_err("I/O address 0x%04llx already in use, device disabled\n",
                       (u64)SMI_EN);
                ret = -EBUSY;
-               goto unmap_gcs;
+               goto unmap_gcs_pmc;
        }
        if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) {
                /*
@@ -478,9 +501,13 @@ static int iTCO_wdt_probe(struct platform_device *dev)
                ich_info->name, ich_info->iTCO_version, (u64)TCOBASE);
 
        /* Clear out the (probably old) status */
-       outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
-       outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
-       outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
+       if (iTCO_wdt_private.iTCO_version == 3) {
+               outl(0x20008, TCO1_STS);
+       } else {
+               outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
+               outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
+               outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
+       }
 
        iTCO_wdt_watchdog_dev.bootstatus = 0;
        iTCO_wdt_watchdog_dev.timeout = WATCHDOG_TIMEOUT;
@@ -515,18 +542,18 @@ unreg_tco:
 unreg_smi:
        release_region(iTCO_wdt_private.smi_res->start,
                        resource_size(iTCO_wdt_private.smi_res));
-unmap_gcs:
-       if (iTCO_wdt_private.iTCO_version == 2)
-               iounmap(iTCO_wdt_private.gcs);
-unreg_gcs:
-       if (iTCO_wdt_private.iTCO_version == 2)
-               release_mem_region(iTCO_wdt_private.gcs_res->start,
-                               resource_size(iTCO_wdt_private.gcs_res));
+unmap_gcs_pmc:
+       if (iTCO_wdt_private.iTCO_version >= 2)
+               iounmap(iTCO_wdt_private.gcs_pmc);
+unreg_gcs_pmc:
+       if (iTCO_wdt_private.iTCO_version >= 2)
+               release_mem_region(iTCO_wdt_private.gcs_pmc_res->start,
+                               resource_size(iTCO_wdt_private.gcs_pmc_res));
 out:
        iTCO_wdt_private.tco_res = NULL;
        iTCO_wdt_private.smi_res = NULL;
-       iTCO_wdt_private.gcs_res = NULL;
-       iTCO_wdt_private.gcs = NULL;
+       iTCO_wdt_private.gcs_pmc_res = NULL;
+       iTCO_wdt_private.gcs_pmc = NULL;
 
        return ret;
 }
index ade1c06..d2b1670 100644 (file)
@@ -195,6 +195,18 @@ static inline int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg) {
        return twl_i2c_read(mod_no, val, reg, 1);
 }
 
+static inline int twl_i2c_write_u16(u8 mod_no, u16 val, u8 reg) {
+       val = cpu_to_le16(val);
+       return twl_i2c_write(mod_no, (u8*) &val, reg, 2);
+}
+
+static inline int twl_i2c_read_u16(u8 mod_no, u16 *val, u8 reg) {
+       int ret;
+       ret = twl_i2c_read(mod_no, (u8*) val, reg, 2);
+       *val = le16_to_cpu(*val);
+       return ret;
+}
+
 int twl_get_type(void);
 int twl_get_version(void);
 int twl_get_hfclk_rate(void);
index 01f5951..1c0134d 100644 (file)
@@ -44,7 +44,7 @@ struct twl4030_madc_conversion_method {
 
 struct twl4030_madc_request {
        unsigned long channels;
-       u16 do_avg;
+       bool do_avg;
        u16 method;
        u16 type;
        bool active;
index 3ddaa63..7b35c21 100644 (file)
 #define ARIZONA_DSP1_STATUS_1                    0x1104
 #define ARIZONA_DSP1_STATUS_2                    0x1105
 #define ARIZONA_DSP1_STATUS_3                    0x1106
+#define ARIZONA_DSP1_STATUS_4                    0x1107
+#define ARIZONA_DSP1_WDMA_BUFFER_1               0x1110
+#define ARIZONA_DSP1_WDMA_BUFFER_2               0x1111
+#define ARIZONA_DSP1_WDMA_BUFFER_3               0x1112
+#define ARIZONA_DSP1_WDMA_BUFFER_4               0x1113
+#define ARIZONA_DSP1_WDMA_BUFFER_5               0x1114
+#define ARIZONA_DSP1_WDMA_BUFFER_6               0x1115
+#define ARIZONA_DSP1_WDMA_BUFFER_7               0x1116
+#define ARIZONA_DSP1_WDMA_BUFFER_8               0x1117
+#define ARIZONA_DSP1_RDMA_BUFFER_1               0x1120
+#define ARIZONA_DSP1_RDMA_BUFFER_2               0x1121
+#define ARIZONA_DSP1_RDMA_BUFFER_3               0x1122
+#define ARIZONA_DSP1_RDMA_BUFFER_4               0x1123
+#define ARIZONA_DSP1_RDMA_BUFFER_5               0x1124
+#define ARIZONA_DSP1_RDMA_BUFFER_6               0x1125
+#define ARIZONA_DSP1_WDMA_CONFIG_1               0x1130
+#define ARIZONA_DSP1_WDMA_CONFIG_2               0x1131
+#define ARIZONA_DSP1_WDMA_OFFSET_1               0x1132
+#define ARIZONA_DSP1_RDMA_CONFIG_1               0x1134
+#define ARIZONA_DSP1_RDMA_OFFSET_1               0x1135
+#define ARIZONA_DSP1_EXTERNAL_START_SELECT_1     0x1138
 #define ARIZONA_DSP1_SCRATCH_0                   0x1140
 #define ARIZONA_DSP1_SCRATCH_1                   0x1141
 #define ARIZONA_DSP1_SCRATCH_2                   0x1142
 #define ARIZONA_DSP2_STATUS_1                    0x1204
 #define ARIZONA_DSP2_STATUS_2                    0x1205
 #define ARIZONA_DSP2_STATUS_3                    0x1206
+#define ARIZONA_DSP2_STATUS_4                    0x1207
+#define ARIZONA_DSP2_WDMA_BUFFER_1               0x1210
+#define ARIZONA_DSP2_WDMA_BUFFER_2               0x1211
+#define ARIZONA_DSP2_WDMA_BUFFER_3               0x1212
+#define ARIZONA_DSP2_WDMA_BUFFER_4               0x1213
+#define ARIZONA_DSP2_WDMA_BUFFER_5               0x1214
+#define ARIZONA_DSP2_WDMA_BUFFER_6               0x1215
+#define ARIZONA_DSP2_WDMA_BUFFER_7               0x1216
+#define ARIZONA_DSP2_WDMA_BUFFER_8               0x1217
+#define ARIZONA_DSP2_RDMA_BUFFER_1               0x1220
+#define ARIZONA_DSP2_RDMA_BUFFER_2               0x1221
+#define ARIZONA_DSP2_RDMA_BUFFER_3               0x1222
+#define ARIZONA_DSP2_RDMA_BUFFER_4               0x1223
+#define ARIZONA_DSP2_RDMA_BUFFER_5               0x1224
+#define ARIZONA_DSP2_RDMA_BUFFER_6               0x1225
+#define ARIZONA_DSP2_WDMA_CONFIG_1               0x1230
+#define ARIZONA_DSP2_WDMA_CONFIG_2               0x1231
+#define ARIZONA_DSP2_WDMA_OFFSET_1               0x1232
+#define ARIZONA_DSP2_RDMA_CONFIG_1               0x1234
+#define ARIZONA_DSP2_RDMA_OFFSET_1               0x1235
+#define ARIZONA_DSP2_EXTERNAL_START_SELECT_1     0x1238
 #define ARIZONA_DSP2_SCRATCH_0                   0x1240
 #define ARIZONA_DSP2_SCRATCH_1                   0x1241
 #define ARIZONA_DSP2_SCRATCH_2                   0x1242
 #define ARIZONA_DSP3_STATUS_1                    0x1304
 #define ARIZONA_DSP3_STATUS_2                    0x1305
 #define ARIZONA_DSP3_STATUS_3                    0x1306
+#define ARIZONA_DSP3_STATUS_4                    0x1307
+#define ARIZONA_DSP3_WDMA_BUFFER_1               0x1310
+#define ARIZONA_DSP3_WDMA_BUFFER_2               0x1311
+#define ARIZONA_DSP3_WDMA_BUFFER_3               0x1312
+#define ARIZONA_DSP3_WDMA_BUFFER_4               0x1313
+#define ARIZONA_DSP3_WDMA_BUFFER_5               0x1314
+#define ARIZONA_DSP3_WDMA_BUFFER_6               0x1315
+#define ARIZONA_DSP3_WDMA_BUFFER_7               0x1316
+#define ARIZONA_DSP3_WDMA_BUFFER_8               0x1317
+#define ARIZONA_DSP3_RDMA_BUFFER_1               0x1320
+#define ARIZONA_DSP3_RDMA_BUFFER_2               0x1321
+#define ARIZONA_DSP3_RDMA_BUFFER_3               0x1322
+#define ARIZONA_DSP3_RDMA_BUFFER_4               0x1323
+#define ARIZONA_DSP3_RDMA_BUFFER_5               0x1324
+#define ARIZONA_DSP3_RDMA_BUFFER_6               0x1325
+#define ARIZONA_DSP3_WDMA_CONFIG_1               0x1330
+#define ARIZONA_DSP3_WDMA_CONFIG_2               0x1331
+#define ARIZONA_DSP3_WDMA_OFFSET_1               0x1332
+#define ARIZONA_DSP3_RDMA_CONFIG_1               0x1334
+#define ARIZONA_DSP3_RDMA_OFFSET_1               0x1335
+#define ARIZONA_DSP3_EXTERNAL_START_SELECT_1     0x1338
 #define ARIZONA_DSP3_SCRATCH_0                   0x1340
 #define ARIZONA_DSP3_SCRATCH_1                   0x1341
 #define ARIZONA_DSP3_SCRATCH_2                   0x1342
 #define ARIZONA_DSP4_STATUS_1                    0x1404
 #define ARIZONA_DSP4_STATUS_2                    0x1405
 #define ARIZONA_DSP4_STATUS_3                    0x1406
+#define ARIZONA_DSP4_STATUS_4                    0x1407
+#define ARIZONA_DSP4_WDMA_BUFFER_1               0x1410
+#define ARIZONA_DSP4_WDMA_BUFFER_2               0x1411
+#define ARIZONA_DSP4_WDMA_BUFFER_3               0x1412
+#define ARIZONA_DSP4_WDMA_BUFFER_4               0x1413
+#define ARIZONA_DSP4_WDMA_BUFFER_5               0x1414
+#define ARIZONA_DSP4_WDMA_BUFFER_6               0x1415
+#define ARIZONA_DSP4_WDMA_BUFFER_7               0x1416
+#define ARIZONA_DSP4_WDMA_BUFFER_8               0x1417
+#define ARIZONA_DSP4_RDMA_BUFFER_1               0x1420
+#define ARIZONA_DSP4_RDMA_BUFFER_2               0x1421
+#define ARIZONA_DSP4_RDMA_BUFFER_3               0x1422
+#define ARIZONA_DSP4_RDMA_BUFFER_4               0x1423
+#define ARIZONA_DSP4_RDMA_BUFFER_5               0x1424
+#define ARIZONA_DSP4_RDMA_BUFFER_6               0x1425
+#define ARIZONA_DSP4_WDMA_CONFIG_1               0x1430
+#define ARIZONA_DSP4_WDMA_CONFIG_2               0x1431
+#define ARIZONA_DSP4_WDMA_OFFSET_1               0x1432
+#define ARIZONA_DSP4_RDMA_CONFIG_1               0x1434
+#define ARIZONA_DSP4_RDMA_OFFSET_1               0x1435
+#define ARIZONA_DSP4_EXTERNAL_START_SELECT_1     0x1438
 #define ARIZONA_DSP4_SCRATCH_0                   0x1440
 #define ARIZONA_DSP4_SCRATCH_1                   0x1441
 #define ARIZONA_DSP4_SCRATCH_2                   0x1442
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
new file mode 100644 (file)
index 0000000..434df2d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Broadcom BCM590xx PMU
+ *
+ * Copyright 2014 Linaro Limited
+ * Author: Matt Porter <mporter@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_BCM590XX_H
+#define __LINUX_MFD_BCM590XX_H
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+/* max register address */
+#define BCM590XX_MAX_REGISTER  0xe7
+
+struct bcm590xx {
+       struct device *dev;
+       struct i2c_client *i2c_client;
+       struct regmap *regmap;
+       unsigned int id;
+};
+
+#endif /*  __LINUX_MFD_BCM590XX_H */
index 21e21b8..bba65f5 100644 (file)
@@ -83,6 +83,7 @@ enum da9052_chip_id {
        DA9053_AA,
        DA9053_BA,
        DA9053_BB,
+       DA9053_BC,
 };
 
 struct da9052_pdata;
index 2d2a0af..00a9aac 100644 (file)
@@ -33,6 +33,10 @@ enum da9063_models {
        PMIC_DA9063 = 0x61,
 };
 
+enum da9063_variant_codes {
+       PMIC_DA9063_BB = 0x5
+};
+
 /* Interrupts */
 enum da9063_irqs {
        DA9063_IRQ_ONKEY = 0,
@@ -72,7 +76,7 @@ struct da9063 {
        /* Device */
        struct device   *dev;
        unsigned short  model;
-       unsigned short  revision;
+       unsigned char   variant_code;
        unsigned int    flags;
 
        /* Control interface */
index 5834813..09a85c6 100644 (file)
 #define        _DA9063_REG_H
 
 #define DA9063_I2C_PAGE_SEL_SHIFT      1
-
 #define        DA9063_EVENT_REG_NUM            4
-#define        DA9210_EVENT_REG_NUM            2
-#define        DA9063_EXT_EVENT_REG_NUM        (DA9063_EVENT_REG_NUM + \
-                                               DA9210_EVENT_REG_NUM)
 
 /* Page selection I2C or SPI always in the begining of any page. */
 /* Page 0 : I2C access 0x000 - 0x0FF   SPI access 0x000 - 0x07F */
@@ -61,9 +57,9 @@
 #define        DA9063_REG_GPIO_10_11           0x1A
 #define        DA9063_REG_GPIO_12_13           0x1B
 #define        DA9063_REG_GPIO_14_15           0x1C
-#define        DA9063_REG_GPIO_MODE_0_7        0x1D
-#define        DA9063_REG_GPIO_MODE_8_15       0x1E
-#define        DA9063_REG_GPIO_SWITCH_CONT     0x1F
+#define        DA9063_REG_GPIO_MODE0_7         0x1D
+#define        DA9063_REG_GPIO_MODE8_15        0x1E
+#define        DA9063_REG_SWITCH_CONT          0x1F
 
 /* Regulator Control Registers */
 #define        DA9063_REG_BCORE2_CONT          0x20
@@ -83,7 +79,7 @@
 #define        DA9063_REG_LDO9_CONT            0x2E
 #define        DA9063_REG_LDO10_CONT           0x2F
 #define        DA9063_REG_LDO11_CONT           0x30
-#define        DA9063_REG_VIB                  0x31
+#define        DA9063_REG_SUPPLIES             0x31
 #define        DA9063_REG_DVC_1                0x32
 #define        DA9063_REG_DVC_2                0x33
 
@@ -97,9 +93,9 @@
 #define        DA9063_REG_ADCIN1_RES           0x3A
 #define        DA9063_REG_ADCIN2_RES           0x3B
 #define        DA9063_REG_ADCIN3_RES           0x3C
-#define        DA9063_REG_MON1_RES             0x3D
-#define        DA9063_REG_MON2_RES             0x3E
-#define        DA9063_REG_MON3_RES             0x3F
+#define        DA9063_REG_MON_A8_RES           0x3D
+#define        DA9063_REG_MON_A9_RES           0x3E
+#define        DA9063_REG_MON_A10_RES          0x3F
 
 /* RTC Calendar and Alarm Registers */
 #define        DA9063_REG_COUNT_S              0x40
 #define        DA9063_REG_COUNT_D              0x43
 #define        DA9063_REG_COUNT_MO             0x44
 #define        DA9063_REG_COUNT_Y              0x45
-#define        DA9063_REG_ALARM_MI             0x46
-#define        DA9063_REG_ALARM_H              0x47
-#define        DA9063_REG_ALARM_D              0x48
-#define        DA9063_REG_ALARM_MO             0x49
-#define        DA9063_REG_ALARM_Y              0x4A
-#define        DA9063_REG_SECOND_A             0x4B
-#define        DA9063_REG_SECOND_B             0x4C
-#define        DA9063_REG_SECOND_C             0x4D
-#define        DA9063_REG_SECOND_D             0x4E
+#define        DA9063_REG_ALARM_S              0x46
+#define        DA9063_REG_ALARM_MI             0x47
+#define        DA9063_REG_ALARM_H              0x48
+#define        DA9063_REG_ALARM_D              0x49
+#define        DA9063_REG_ALARM_MO             0x4A
+#define        DA9063_REG_ALARM_Y              0x4B
+#define        DA9063_REG_SECOND_A             0x4C
+#define        DA9063_REG_SECOND_B             0x4D
+#define        DA9063_REG_SECOND_C             0x4E
+#define        DA9063_REG_SECOND_D             0x4F
 
 /* Sequencer Control Registers */
 #define        DA9063_REG_SEQ                  0x81
 #define        DA9063_REG_CONFIG_J             0x10F
 #define        DA9063_REG_CONFIG_K             0x110
 #define        DA9063_REG_CONFIG_L             0x111
-#define        DA9063_REG_MON_REG_1            0x112
-#define        DA9063_REG_MON_REG_2            0x113
-#define        DA9063_REG_MON_REG_3            0x114
-#define        DA9063_REG_MON_REG_4            0x115
-#define        DA9063_REG_MON_REG_5            0x116
-#define        DA9063_REG_MON_REG_6            0x117
-#define        DA9063_REG_TRIM_CLDR            0x118
-
+#define        DA9063_REG_CONFIG_M             0x112
+#define        DA9063_REG_CONFIG_N             0x113
+
+#define        DA9063_REG_MON_REG_1            0x114
+#define        DA9063_REG_MON_REG_2            0x115
+#define        DA9063_REG_MON_REG_3            0x116
+#define        DA9063_REG_MON_REG_4            0x117
+#define        DA9063_REG_MON_REG_5            0x11E
+#define        DA9063_REG_MON_REG_6            0x11F
+#define        DA9063_REG_TRIM_CLDR            0x120
 /* General Purpose Registers */
-#define        DA9063_REG_GP_ID_0              0x119
-#define        DA9063_REG_GP_ID_1              0x11A
-#define        DA9063_REG_GP_ID_2              0x11B
-#define        DA9063_REG_GP_ID_3              0x11C
-#define        DA9063_REG_GP_ID_4              0x11D
-#define        DA9063_REG_GP_ID_5              0x11E
-#define        DA9063_REG_GP_ID_6              0x11F
-#define        DA9063_REG_GP_ID_7              0x120
-#define        DA9063_REG_GP_ID_8              0x121
-#define        DA9063_REG_GP_ID_9              0x122
-#define        DA9063_REG_GP_ID_10             0x123
-#define        DA9063_REG_GP_ID_11             0x124
-#define        DA9063_REG_GP_ID_12             0x125
-#define        DA9063_REG_GP_ID_13             0x126
-#define        DA9063_REG_GP_ID_14             0x127
-#define        DA9063_REG_GP_ID_15             0x128
-#define        DA9063_REG_GP_ID_16             0x129
-#define        DA9063_REG_GP_ID_17             0x12A
-#define        DA9063_REG_GP_ID_18             0x12B
-#define        DA9063_REG_GP_ID_19             0x12C
+#define        DA9063_REG_GP_ID_0              0x121
+#define        DA9063_REG_GP_ID_1              0x122
+#define        DA9063_REG_GP_ID_2              0x123
+#define        DA9063_REG_GP_ID_3              0x124
+#define        DA9063_REG_GP_ID_4              0x125
+#define        DA9063_REG_GP_ID_5              0x126
+#define        DA9063_REG_GP_ID_6              0x127
+#define        DA9063_REG_GP_ID_7              0x128
+#define        DA9063_REG_GP_ID_8              0x129
+#define        DA9063_REG_GP_ID_9              0x12A
+#define        DA9063_REG_GP_ID_10             0x12B
+#define        DA9063_REG_GP_ID_11             0x12C
+#define        DA9063_REG_GP_ID_12             0x12D
+#define        DA9063_REG_GP_ID_13             0x12E
+#define        DA9063_REG_GP_ID_14             0x12F
+#define        DA9063_REG_GP_ID_15             0x130
+#define        DA9063_REG_GP_ID_16             0x131
+#define        DA9063_REG_GP_ID_17             0x132
+#define        DA9063_REG_GP_ID_18             0x133
+#define        DA9063_REG_GP_ID_19             0x134
 
 /* Chip ID and variant */
 #define        DA9063_REG_CHIP_ID              0x181
 /* DA9063_REG_CONTROL_B (addr=0x0F) */
 #define        DA9063_CHG_SEL                          0x01
 #define        DA9063_WATCHDOG_PD                      0x02
+#define        DA9063_RESET_BLINKING                   0x04
 #define        DA9063_NRES_MODE                        0x08
 #define        DA9063_NONKEY_LOCK                      0x10
+#define        DA9063_BUCK_SLOWSTART                   0x80
 
 /* DA9063_REG_CONTROL_C (addr=0x10) */
 #define        DA9063_DEBOUNCING_MASK                  0x07
 #define        DA9063_GPADC_PAUSE                      0x02
 #define        DA9063_PMIF_DIS                         0x04
 #define        DA9063_HS2WIRE_DIS                      0x08
+#define        DA9063_CLDR_PAUSE                       0x10
 #define        DA9063_BBAT_DIS                         0x20
 #define        DA9063_OUT_32K_PAUSE                    0x40
 #define        DA9063_PMCONT_DIS                       0x80
 #define                DA9063_GPIO15_TYPE_GPO          0x04
 #define        DA9063_GPIO15_NO_WAKEUP                 0x80
 
-/* DA9063_REG_GPIO_MODE_0_7 (addr=0x1D) */
+/* DA9063_REG_GPIO_MODE0_7 (addr=0x1D) */
 #define        DA9063_GPIO0_MODE                       0x01
 #define        DA9063_GPIO1_MODE                       0x02
 #define        DA9063_GPIO2_MODE                       0x04
 #define        DA9063_GPIO6_MODE                       0x40
 #define        DA9063_GPIO7_MODE                       0x80
 
-/* DA9063_REG_GPIO_MODE_8_15 (addr=0x1E) */
+/* DA9063_REG_GPIO_MODE8_15 (addr=0x1E) */
 #define        DA9063_GPIO8_MODE                       0x01
 #define        DA9063_GPIO9_MODE                       0x02
 #define        DA9063_GPIO10_MODE                      0x04
 #define                DA9063_SWITCH_SR_5MV            0x10
 #define                DA9063_SWITCH_SR_10MV           0x20
 #define                DA9063_SWITCH_SR_50MV           0x30
-#define        DA9063_SWITCH_SR_DIS                    0x40
+#define        DA9063_CORE_SW_INTERNAL                 0x40
 #define        DA9063_CP_EN_MODE                       0x80
 
 /* DA9063_REGL_Bxxxx_CONT common bits (addr=0x20-0x25) */
 #define        DA9063_BUCK_EN                          0x01
-#define DA9063_BUCK_GPI_MASK                   0x06
+#define        DA9063_BUCK_GPI_MASK                    0x06
 #define                DA9063_BUCK_GPI_OFF             0x00
 #define                DA9063_BUCK_GPI_GPIO1           0x02
 #define                DA9063_BUCK_GPI_GPIO2           0x04
 #define DA9063_COUNT_YEAR_MASK                 0x3F
 #define DA9063_MONITOR                         0x40
 
-/* DA9063_REG_ALARM_MI (addr=0x46) */
+/* DA9063_REG_ALARM_S (addr=0x46) */
+#define DA9063_ALARM_S_MASK                    0x3F
 #define DA9063_ALARM_STATUS_ALARM              0x80
 #define DA9063_ALARM_STATUS_TICK               0x40
+/* DA9063_REG_ALARM_MI (addr=0x47) */
 #define DA9063_ALARM_MIN_MASK                  0x3F
 
-/* DA9063_REG_ALARM_H (addr=0x47) */
+/* DA9063_REG_ALARM_H (addr=0x48) */
 #define DA9063_ALARM_HOUR_MASK                 0x1F
 
-/* DA9063_REG_ALARM_D (addr=0x48) */
+/* DA9063_REG_ALARM_D (addr=0x49) */
 #define DA9063_ALARM_DAY_MASK                  0x1F
 
-/* DA9063_REG_ALARM_MO (addr=0x49) */
+/* DA9063_REG_ALARM_MO (addr=0x4A) */
 #define DA9063_TICK_WAKE                       0x20
 #define DA9063_TICK_TYPE                       0x10
 #define                DA9063_TICK_TYPE_SEC            0x00
 #define                DA9063_TICK_TYPE_MIN            0x10
 #define DA9063_ALARM_MONTH_MASK                        0x0F
 
-/* DA9063_REG_ALARM_Y (addr=0x4A) */
+/* DA9063_REG_ALARM_Y (addr=0x4B) */
 #define DA9063_TICK_ON                         0x80
 #define DA9063_ALARM_ON                                0x40
 #define DA9063_ALARM_YEAR_MASK                 0x3F
 
 /* DA9063_REG_Bxxxx_CFG common bits (addr=0x9D-0xA2) */
 #define DA9063_BUCK_FB_MASK                    0x07
-#define DA9063_BUCK_PD_DIS_SHIFT               5
+#define DA9063_BUCK_PD_DIS_MASK                0x20
 #define DA9063_BUCK_MODE_MASK                  0xC0
 #define                DA9063_BUCK_MODE_MANUAL         0x00
 #define                DA9063_BUCK_MODE_SLEEP          0x40
index 3e1df64..8feac78 100644 (file)
 #define LPC_ICH_H
 
 /* Watchdog resources */
-#define ICH_RES_IO_TCO 0
-#define ICH_RES_IO_SMI 1
-#define ICH_RES_MEM_OFF        2
-#define ICH_RES_MEM_GCS        0
+#define ICH_RES_IO_TCO         0
+#define ICH_RES_IO_SMI         1
+#define ICH_RES_MEM_OFF                2
+#define ICH_RES_MEM_GCS_PMC    0
 
 /* GPIO resources */
 #define ICH_RES_GPIO   0
 #define ICH_RES_GPE0   1
 
 /* GPIO compatibility */
-#define ICH_I3100_GPIO         0x401
-#define ICH_V5_GPIO            0x501
-#define ICH_V6_GPIO            0x601
-#define ICH_V7_GPIO            0x701
-#define ICH_V9_GPIO            0x801
-#define ICH_V10CORP_GPIO       0xa01
-#define ICH_V10CONS_GPIO       0xa11
+enum {
+       ICH_I3100_GPIO,
+       ICH_V5_GPIO,
+       ICH_V6_GPIO,
+       ICH_V7_GPIO,
+       ICH_V9_GPIO,
+       ICH_V10CORP_GPIO,
+       ICH_V10CONS_GPIO,
+       AVOTON_GPIO,
+};
 
 struct lpc_ich_info {
        char name[32];
index a3d0185..c9b332f 100644 (file)
@@ -248,14 +248,6 @@ enum max14577_charger_reg {
 /* MAX14577 regulator SFOUT LDO voltage, fixed, uV */
 #define MAX14577_REGULATOR_SAFEOUT_VOLTAGE             4900000
 
-enum max14577_irq_source {
-       MAX14577_IRQ_INT1 = 0,
-       MAX14577_IRQ_INT2,
-       MAX14577_IRQ_INT3,
-
-       MAX14577_IRQ_REGS_NUM,
-};
-
 enum max14577_irq {
        /* INT1 */
        MAX14577_IRQ_INT1_ADC,
index 247b021..736d39c 100644 (file)
 #ifndef __MAX14577_H__
 #define __MAX14577_H__
 
-#include <linux/mfd/max14577-private.h>
 #include <linux/regulator/consumer.h>
 
-/*
- * MAX14577 Regulator
- */
-
 /* MAX14577 regulator IDs */
 enum max14577_regulators {
        MAX14577_SAFEOUT = 0,
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
deleted file mode 100644 (file)
index f83d6b4..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC irq 8xxx driver header file
- *
- */
-
-#ifndef __MFD_PM8XXX_IRQ_H
-#define __MFD_PM8XXX_IRQ_H
-
-#include <linux/errno.h>
-#include <linux/err.h>
-
-struct pm8xxx_irq_core_data {
-       u32             rev;
-       int             nirqs;
-};
-
-struct pm8xxx_irq_platform_data {
-       int                             irq_base;
-       struct pm8xxx_irq_core_data     irq_cdata;
-       int                             devirq;
-       int                             irq_trigger_flag;
-};
-
-struct pm_irq_chip;
-
-#ifdef CONFIG_MFD_PM8XXX_IRQ
-int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
-struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
-                               const struct pm8xxx_irq_platform_data *pdata);
-int pm8xxx_irq_exit(struct pm_irq_chip *chip);
-#else
-static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
-       return -ENXIO;
-}
-static inline struct pm_irq_chip *pm8xxx_irq_init(
-                               const struct device *dev,
-                               const struct pm8xxx_irq_platform_data *pdata)
-{
-       return ERR_PTR(-ENXIO);
-}
-static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
-{
-       return -ENXIO;
-}
-#endif /* CONFIG_MFD_PM8XXX_IRQ */
-#endif /* __MFD_PM8XXX_IRQ_H */
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
deleted file mode 100644 (file)
index 00fa3de..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC 8921 driver header file
- *
- */
-
-#ifndef __MFD_PM8921_H
-#define __MFD_PM8921_H
-
-#include <linux/mfd/pm8xxx/irq.h>
-
-#define PM8921_NR_IRQS         256
-
-struct pm8921_platform_data {
-       int                                     irq_base;
-       struct pm8xxx_irq_platform_data         *irq_pdata;
-};
-
-#endif
diff --git a/include/linux/mfd/rtsx_usb.h b/include/linux/mfd/rtsx_usb.h
new file mode 100644 (file)
index 0000000..c446e4f
--- /dev/null
@@ -0,0 +1,628 @@
+/* Driver for Realtek RTS5139 USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+
+#ifndef __RTSX_USB_H
+#define __RTSX_USB_H
+
+#include <linux/usb.h>
+
+/* related module names */
+#define RTSX_USB_SD_CARD       0
+#define RTSX_USB_MS_CARD       1
+
+/* endpoint numbers */
+#define EP_BULK_OUT            1
+#define EP_BULK_IN             2
+#define EP_INTR_IN             3
+
+/* USB vendor requests */
+#define RTSX_USB_REQ_REG_OP    0x00
+#define RTSX_USB_REQ_POLL      0x02
+
+/* miscellaneous parameters */
+#define MIN_DIV_N              60
+#define MAX_DIV_N              120
+
+#define MAX_PHASE              15
+#define RX_TUNING_CNT          3
+
+#define QFN24                  0
+#define LQFP48                 1
+#define CHECK_PKG(ucr, pkg)    ((ucr)->package == (pkg))
+
+/* data structures */
+struct rtsx_ucr {
+       u16                     vendor_id;
+       u16                     product_id;
+
+       int                     package;
+       u8                      ic_version;
+       bool                    is_rts5179;
+
+       unsigned int            cur_clk;
+
+       u8                      *cmd_buf;
+       unsigned int            cmd_idx;
+       u8                      *rsp_buf;
+
+       struct usb_device       *pusb_dev;
+       struct usb_interface    *pusb_intf;
+       struct usb_sg_request   current_sg;
+       unsigned char           *iobuf;
+       dma_addr_t              iobuf_dma;
+
+       struct timer_list       sg_timer;
+       struct mutex            dev_mutex;
+};
+
+/* buffer size */
+#define IOBUF_SIZE             1024
+
+/* prototypes of exported functions */
+extern int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status);
+
+extern int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data);
+extern int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+               u8 data);
+
+extern int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+               u8 data);
+extern int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr,
+               u8 *data);
+
+extern void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type,
+               u16 reg_addr, u8 mask, u8 data);
+extern int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout);
+extern int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout);
+extern int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+                             void *buf, unsigned int len, int use_sg,
+                             unsigned int *act_len, int timeout);
+
+extern int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
+
+/* card status */
+#define SD_CD          0x01
+#define MS_CD          0x02
+#define XD_CD          0x04
+#define CD_MASK                (SD_CD | MS_CD | XD_CD)
+#define SD_WP          0x08
+
+/* reader command field offset & parameters */
+#define READ_REG_CMD           0
+#define WRITE_REG_CMD          1
+#define CHECK_REG_CMD          2
+
+#define PACKET_TYPE            4
+#define CNT_H                  5
+#define CNT_L                  6
+#define STAGE_FLAG             7
+#define CMD_OFFSET             8
+#define SEQ_WRITE_DATA_OFFSET  12
+
+#define BATCH_CMD              0
+#define SEQ_READ               1
+#define SEQ_WRITE              2
+
+#define STAGE_R                        0x01
+#define STAGE_DI               0x02
+#define STAGE_DO               0x04
+#define STAGE_MS_STATUS                0x08
+#define STAGE_XD_STATUS                0x10
+#define MODE_C                 0x00
+#define MODE_CR                        (STAGE_R)
+#define MODE_CDIR              (STAGE_R | STAGE_DI)
+#define MODE_CDOR              (STAGE_R | STAGE_DO)
+
+#define EP0_OP_SHIFT           14
+#define EP0_READ_REG_CMD       2
+#define EP0_WRITE_REG_CMD      3
+
+#define rtsx_usb_cmd_hdr_tag(ucr)              \
+       do {                                    \
+               ucr->cmd_buf[0] = 'R';          \
+               ucr->cmd_buf[1] = 'T';          \
+               ucr->cmd_buf[2] = 'C';          \
+               ucr->cmd_buf[3] = 'R';          \
+       } while (0)
+
+static inline void rtsx_usb_init_cmd(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_cmd_hdr_tag(ucr);
+       ucr->cmd_idx = 0;
+       ucr->cmd_buf[PACKET_TYPE] = BATCH_CMD;
+}
+
+/* internal register address */
+#define FPDCTL                         0xFC00
+#define SSC_DIV_N_0                    0xFC07
+#define SSC_CTL1                       0xFC09
+#define SSC_CTL2                       0xFC0A
+#define CFG_MODE                       0xFC0E
+#define CFG_MODE_1                     0xFC0F
+#define RCCTL                          0xFC14
+#define SOF_WDOG                       0xFC28
+#define SYS_DUMMY0                     0xFC30
+
+#define MS_BLKEND                      0xFD30
+#define MS_READ_START                  0xFD31
+#define MS_READ_COUNT                  0xFD32
+#define MS_WRITE_START                 0xFD33
+#define MS_WRITE_COUNT                 0xFD34
+#define MS_COMMAND                     0xFD35
+#define MS_OLD_BLOCK_0                 0xFD36
+#define MS_OLD_BLOCK_1                 0xFD37
+#define MS_NEW_BLOCK_0                 0xFD38
+#define MS_NEW_BLOCK_1                 0xFD39
+#define MS_LOG_BLOCK_0                 0xFD3A
+#define MS_LOG_BLOCK_1                 0xFD3B
+#define MS_BUS_WIDTH                   0xFD3C
+#define MS_PAGE_START                  0xFD3D
+#define MS_PAGE_LENGTH                 0xFD3E
+#define MS_CFG                         0xFD40
+#define MS_TPC                         0xFD41
+#define MS_TRANS_CFG                   0xFD42
+#define MS_TRANSFER                    0xFD43
+#define MS_INT_REG                     0xFD44
+#define MS_BYTE_CNT                    0xFD45
+#define MS_SECTOR_CNT_L                        0xFD46
+#define MS_SECTOR_CNT_H                        0xFD47
+#define MS_DBUS_H                      0xFD48
+
+#define CARD_DMA1_CTL                  0xFD5C
+#define CARD_PULL_CTL1                 0xFD60
+#define CARD_PULL_CTL2                 0xFD61
+#define CARD_PULL_CTL3                 0xFD62
+#define CARD_PULL_CTL4                 0xFD63
+#define CARD_PULL_CTL5                 0xFD64
+#define CARD_PULL_CTL6                 0xFD65
+#define CARD_EXIST                     0xFD6F
+#define CARD_INT_PEND                  0xFD71
+
+#define LDO_POWER_CFG                  0xFD7B
+
+#define SD_CFG1                                0xFDA0
+#define SD_CFG2                                0xFDA1
+#define SD_CFG3                                0xFDA2
+#define SD_STAT1                       0xFDA3
+#define SD_STAT2                       0xFDA4
+#define SD_BUS_STAT                    0xFDA5
+#define SD_PAD_CTL                     0xFDA6
+#define SD_SAMPLE_POINT_CTL            0xFDA7
+#define SD_PUSH_POINT_CTL              0xFDA8
+#define SD_CMD0                                0xFDA9
+#define SD_CMD1                                0xFDAA
+#define SD_CMD2                                0xFDAB
+#define SD_CMD3                                0xFDAC
+#define SD_CMD4                                0xFDAD
+#define SD_CMD5                                0xFDAE
+#define SD_BYTE_CNT_L                  0xFDAF
+#define SD_BYTE_CNT_H                  0xFDB0
+#define SD_BLOCK_CNT_L                 0xFDB1
+#define SD_BLOCK_CNT_H                 0xFDB2
+#define SD_TRANSFER                    0xFDB3
+#define SD_CMD_STATE                   0xFDB5
+#define SD_DATA_STATE                  0xFDB6
+#define SD_VPCLK0_CTL                  0xFC2A
+#define SD_VPCLK1_CTL                  0xFC2B
+#define SD_DCMPS0_CTL                  0xFC2C
+#define SD_DCMPS1_CTL                  0xFC2D
+
+#define CARD_DMA1_CTL                  0xFD5C
+
+#define HW_VERSION                     0xFC01
+
+#define SSC_CLK_FPGA_SEL               0xFC02
+#define CLK_DIV                                0xFC03
+#define SFSM_ED                                0xFC04
+
+#define CD_DEGLITCH_WIDTH              0xFC20
+#define CD_DEGLITCH_EN                 0xFC21
+#define AUTO_DELINK_EN                 0xFC23
+
+#define FPGA_PULL_CTL                  0xFC1D
+#define CARD_CLK_SOURCE                        0xFC2E
+
+#define CARD_SHARE_MODE                        0xFD51
+#define CARD_DRIVE_SEL                 0xFD52
+#define CARD_STOP                      0xFD53
+#define CARD_OE                                0xFD54
+#define CARD_AUTO_BLINK                        0xFD55
+#define CARD_GPIO                      0xFD56
+#define SD30_DRIVE_SEL                 0xFD57
+
+#define CARD_DATA_SOURCE               0xFD5D
+#define CARD_SELECT                    0xFD5E
+
+#define CARD_CLK_EN                    0xFD79
+#define CARD_PWR_CTL                   0xFD7A
+
+#define OCPCTL                         0xFD80
+#define OCPPARA1                       0xFD81
+#define OCPPARA2                       0xFD82
+#define OCPSTAT                                0xFD83
+
+#define HS_USB_STAT                    0xFE01
+#define HS_VCONTROL                    0xFE26
+#define HS_VSTAIN                      0xFE27
+#define HS_VLOADM                      0xFE28
+#define HS_VSTAOUT                     0xFE29
+
+#define MC_IRQ                         0xFF00
+#define MC_IRQEN                       0xFF01
+#define MC_FIFO_CTL                    0xFF02
+#define MC_FIFO_BC0                    0xFF03
+#define MC_FIFO_BC1                    0xFF04
+#define MC_FIFO_STAT                   0xFF05
+#define MC_FIFO_MODE                   0xFF06
+#define MC_FIFO_RD_PTR0                        0xFF07
+#define MC_FIFO_RD_PTR1                        0xFF08
+#define MC_DMA_CTL                     0xFF10
+#define MC_DMA_TC0                     0xFF11
+#define MC_DMA_TC1                     0xFF12
+#define MC_DMA_TC2                     0xFF13
+#define MC_DMA_TC3                     0xFF14
+#define MC_DMA_RST                     0xFF15
+
+#define RBUF_SIZE_MASK                 0xFBFF
+#define RBUF_BASE                      0xF000
+#define PPBUF_BASE1                    0xF800
+#define PPBUF_BASE2                    0xFA00
+
+/* internal register value macros */
+#define POWER_OFF                      0x03
+#define PARTIAL_POWER_ON               0x02
+#define POWER_ON                       0x00
+#define POWER_MASK                     0x03
+#define LDO3318_PWR_MASK               0x0C
+#define LDO_ON                         0x00
+#define LDO_SUSPEND                    0x08
+#define LDO_OFF                                0x0C
+#define DV3318_AUTO_PWR_OFF            0x10
+#define FORCE_LDO_POWERB               0x60
+
+/* LDO_POWER_CFG */
+#define TUNE_SD18_MASK                 0x1C
+#define TUNE_SD18_1V7                  0x00
+#define TUNE_SD18_1V8                  (0x01 << 2)
+#define TUNE_SD18_1V9                  (0x02 << 2)
+#define TUNE_SD18_2V0                  (0x03 << 2)
+#define TUNE_SD18_2V7                  (0x04 << 2)
+#define TUNE_SD18_2V8                  (0x05 << 2)
+#define TUNE_SD18_2V9                  (0x06 << 2)
+#define TUNE_SD18_3V3                  (0x07 << 2)
+
+/* CLK_DIV */
+#define CLK_CHANGE                     0x80
+#define CLK_DIV_1                      0x00
+#define CLK_DIV_2                      0x01
+#define CLK_DIV_4                      0x02
+#define CLK_DIV_8                      0x03
+
+#define SSC_POWER_MASK                 0x01
+#define SSC_POWER_DOWN                 0x01
+#define SSC_POWER_ON                   0x00
+
+#define FPGA_VER                       0x80
+#define HW_VER_MASK                    0x0F
+
+#define EXTEND_DMA1_ASYNC_SIGNAL       0x02
+
+/* CFG_MODE*/
+#define XTAL_FREE                      0x80
+#define CLK_MODE_MASK                  0x03
+#define CLK_MODE_12M_XTAL              0x00
+#define CLK_MODE_NON_XTAL              0x01
+#define CLK_MODE_24M_OSC               0x02
+#define CLK_MODE_48M_OSC               0x03
+
+/* CFG_MODE_1*/
+#define RTS5179                                0x02
+
+#define NYET_EN                                0x01
+#define NYET_MSAK                      0x01
+
+#define SD30_DRIVE_MASK                        0x07
+#define SD20_DRIVE_MASK                        0x03
+
+#define DISABLE_SD_CD                  0x08
+#define DISABLE_MS_CD                  0x10
+#define DISABLE_XD_CD                  0x20
+#define SD_CD_DEGLITCH_EN              0x01
+#define MS_CD_DEGLITCH_EN              0x02
+#define XD_CD_DEGLITCH_EN              0x04
+
+#define        CARD_SHARE_LQFP48               0x04
+#define        CARD_SHARE_QFN24                0x00
+#define CARD_SHARE_LQFP_SEL            0x04
+#define        CARD_SHARE_XD                   0x00
+#define        CARD_SHARE_SD                   0x01
+#define        CARD_SHARE_MS                   0x02
+#define CARD_SHARE_MASK                        0x03
+
+
+/* SD30_DRIVE_SEL */
+#define DRIVER_TYPE_A                  0x05
+#define DRIVER_TYPE_B                  0x03
+#define DRIVER_TYPE_C                  0x02
+#define DRIVER_TYPE_D                  0x01
+
+/* SD_BUS_STAT */
+#define        SD_CLK_TOGGLE_EN                0x80
+#define        SD_CLK_FORCE_STOP               0x40
+#define        SD_DAT3_STATUS                  0x10
+#define        SD_DAT2_STATUS                  0x08
+#define        SD_DAT1_STATUS                  0x04
+#define        SD_DAT0_STATUS                  0x02
+#define        SD_CMD_STATUS                   0x01
+
+/* SD_PAD_CTL */
+#define        SD_IO_USING_1V8                 0x80
+#define        SD_IO_USING_3V3                 0x7F
+#define        TYPE_A_DRIVING                  0x00
+#define        TYPE_B_DRIVING                  0x01
+#define        TYPE_C_DRIVING                  0x02
+#define        TYPE_D_DRIVING                  0x03
+
+/* CARD_CLK_EN */
+#define SD_CLK_EN                      0x04
+#define MS_CLK_EN                      0x08
+
+/* CARD_SELECT */
+#define SD_MOD_SEL                     2
+#define MS_MOD_SEL                     3
+
+/* CARD_SHARE_MODE */
+#define        CARD_SHARE_LQFP48               0x04
+#define        CARD_SHARE_QFN24                0x00
+#define CARD_SHARE_LQFP_SEL            0x04
+#define        CARD_SHARE_XD                   0x00
+#define        CARD_SHARE_SD                   0x01
+#define        CARD_SHARE_MS                   0x02
+#define CARD_SHARE_MASK                        0x03
+
+/* SSC_CTL1 */
+#define SSC_RSTB                       0x80
+#define SSC_8X_EN                      0x40
+#define SSC_FIX_FRAC                   0x20
+#define SSC_SEL_1M                     0x00
+#define SSC_SEL_2M                     0x08
+#define SSC_SEL_4M                     0x10
+#define SSC_SEL_8M                     0x18
+
+/* SSC_CTL2 */
+#define SSC_DEPTH_MASK                 0x03
+#define SSC_DEPTH_DISALBE              0x00
+#define SSC_DEPTH_2M                   0x01
+#define SSC_DEPTH_1M                   0x02
+#define SSC_DEPTH_512K                 0x03
+
+/* SD_VPCLK0_CTL */
+#define PHASE_CHANGE                   0x80
+#define PHASE_NOT_RESET                        0x40
+
+/* SD_TRANSFER */
+#define        SD_TRANSFER_START               0x80
+#define        SD_TRANSFER_END                 0x40
+#define SD_STAT_IDLE                   0x20
+#define        SD_TRANSFER_ERR                 0x10
+#define        SD_TM_NORMAL_WRITE              0x00
+#define        SD_TM_AUTO_WRITE_3              0x01
+#define        SD_TM_AUTO_WRITE_4              0x02
+#define        SD_TM_AUTO_READ_3               0x05
+#define        SD_TM_AUTO_READ_4               0x06
+#define        SD_TM_CMD_RSP                   0x08
+#define        SD_TM_AUTO_WRITE_1              0x09
+#define        SD_TM_AUTO_WRITE_2              0x0A
+#define        SD_TM_NORMAL_READ               0x0C
+#define        SD_TM_AUTO_READ_1               0x0D
+#define        SD_TM_AUTO_READ_2               0x0E
+#define        SD_TM_AUTO_TUNING               0x0F
+
+/* SD_CFG1 */
+#define SD_CLK_DIVIDE_0                        0x00
+#define        SD_CLK_DIVIDE_256               0xC0
+#define        SD_CLK_DIVIDE_128               0x80
+#define SD_CLK_DIVIDE_MASK             0xC0
+#define        SD_BUS_WIDTH_1BIT               0x00
+#define        SD_BUS_WIDTH_4BIT               0x01
+#define        SD_BUS_WIDTH_8BIT               0x02
+#define        SD_ASYNC_FIFO_RST               0x10
+#define        SD_20_MODE                      0x00
+#define        SD_DDR_MODE                     0x04
+#define        SD_30_MODE                      0x08
+
+/* SD_CFG2 */
+#define        SD_CALCULATE_CRC7               0x00
+#define        SD_NO_CALCULATE_CRC7            0x80
+#define        SD_CHECK_CRC16                  0x00
+#define        SD_NO_CHECK_CRC16               0x40
+#define SD_WAIT_CRC_TO_EN              0x20
+#define        SD_WAIT_BUSY_END                0x08
+#define        SD_NO_WAIT_BUSY_END             0x00
+#define        SD_CHECK_CRC7                   0x00
+#define        SD_NO_CHECK_CRC7                0x04
+#define        SD_RSP_LEN_0                    0x00
+#define        SD_RSP_LEN_6                    0x01
+#define        SD_RSP_LEN_17                   0x02
+#define        SD_RSP_TYPE_R0                  0x04
+#define        SD_RSP_TYPE_R1                  0x01
+#define        SD_RSP_TYPE_R1b                 0x09
+#define        SD_RSP_TYPE_R2                  0x02
+#define        SD_RSP_TYPE_R3                  0x05
+#define        SD_RSP_TYPE_R4                  0x05
+#define        SD_RSP_TYPE_R5                  0x01
+#define        SD_RSP_TYPE_R6                  0x01
+#define        SD_RSP_TYPE_R7                  0x01
+
+/* SD_STAT1 */
+#define        SD_CRC7_ERR                     0x80
+#define        SD_CRC16_ERR                    0x40
+#define        SD_CRC_WRITE_ERR                0x20
+#define        SD_CRC_WRITE_ERR_MASK           0x1C
+#define        GET_CRC_TIME_OUT                0x02
+#define        SD_TUNING_COMPARE_ERR           0x01
+
+/* SD_DATA_STATE */
+#define SD_DATA_IDLE                   0x80
+
+/* CARD_DATA_SOURCE */
+#define PINGPONG_BUFFER                        0x01
+#define RING_BUFFER                    0x00
+
+/* CARD_OE */
+#define SD_OUTPUT_EN                   0x04
+#define MS_OUTPUT_EN                   0x08
+
+/* CARD_STOP */
+#define SD_STOP                                0x04
+#define MS_STOP                                0x08
+#define SD_CLR_ERR                     0x40
+#define MS_CLR_ERR                     0x80
+
+/* CARD_CLK_SOURCE */
+#define CRC_FIX_CLK                    (0x00 << 0)
+#define CRC_VAR_CLK0                   (0x01 << 0)
+#define CRC_VAR_CLK1                   (0x02 << 0)
+#define SD30_FIX_CLK                   (0x00 << 2)
+#define SD30_VAR_CLK0                  (0x01 << 2)
+#define SD30_VAR_CLK1                  (0x02 << 2)
+#define SAMPLE_FIX_CLK                 (0x00 << 4)
+#define SAMPLE_VAR_CLK0                        (0x01 << 4)
+#define SAMPLE_VAR_CLK1                        (0x02 << 4)
+
+/* SD_SAMPLE_POINT_CTL */
+#define        DDR_FIX_RX_DAT                  0x00
+#define        DDR_VAR_RX_DAT                  0x80
+#define        DDR_FIX_RX_DAT_EDGE             0x00
+#define        DDR_FIX_RX_DAT_14_DELAY         0x40
+#define        DDR_FIX_RX_CMD                  0x00
+#define        DDR_VAR_RX_CMD                  0x20
+#define        DDR_FIX_RX_CMD_POS_EDGE         0x00
+#define        DDR_FIX_RX_CMD_14_DELAY         0x10
+#define        SD20_RX_POS_EDGE                0x00
+#define        SD20_RX_14_DELAY                0x08
+#define SD20_RX_SEL_MASK               0x08
+
+/* SD_PUSH_POINT_CTL */
+#define        DDR_FIX_TX_CMD_DAT              0x00
+#define        DDR_VAR_TX_CMD_DAT              0x80
+#define        DDR_FIX_TX_DAT_14_TSU           0x00
+#define        DDR_FIX_TX_DAT_12_TSU           0x40
+#define        DDR_FIX_TX_CMD_NEG_EDGE         0x00
+#define        DDR_FIX_TX_CMD_14_AHEAD         0x20
+#define        SD20_TX_NEG_EDGE                0x00
+#define        SD20_TX_14_AHEAD                0x10
+#define SD20_TX_SEL_MASK               0x10
+#define        DDR_VAR_SDCLK_POL_SWAP          0x01
+
+/* MS_CFG */
+#define        SAMPLE_TIME_RISING              0x00
+#define        SAMPLE_TIME_FALLING             0x80
+#define        PUSH_TIME_DEFAULT               0x00
+#define        PUSH_TIME_ODD                   0x40
+#define        NO_EXTEND_TOGGLE                0x00
+#define        EXTEND_TOGGLE_CHK               0x20
+#define        MS_BUS_WIDTH_1                  0x00
+#define        MS_BUS_WIDTH_4                  0x10
+#define        MS_BUS_WIDTH_8                  0x18
+#define        MS_2K_SECTOR_MODE               0x04
+#define        MS_512_SECTOR_MODE              0x00
+#define        MS_TOGGLE_TIMEOUT_EN            0x00
+#define        MS_TOGGLE_TIMEOUT_DISEN         0x01
+#define MS_NO_CHECK_INT                        0x02
+
+/* MS_TRANS_CFG */
+#define        WAIT_INT                        0x80
+#define        NO_WAIT_INT                     0x00
+#define        NO_AUTO_READ_INT_REG            0x00
+#define        AUTO_READ_INT_REG               0x40
+#define        MS_CRC16_ERR                    0x20
+#define        MS_RDY_TIMEOUT                  0x10
+#define        MS_INT_CMDNK                    0x08
+#define        MS_INT_BREQ                     0x04
+#define        MS_INT_ERR                      0x02
+#define        MS_INT_CED                      0x01
+
+/* MS_TRANSFER */
+#define        MS_TRANSFER_START               0x80
+#define        MS_TRANSFER_END                 0x40
+#define        MS_TRANSFER_ERR                 0x20
+#define        MS_BS_STATE                     0x10
+#define        MS_TM_READ_BYTES                0x00
+#define        MS_TM_NORMAL_READ               0x01
+#define        MS_TM_WRITE_BYTES               0x04
+#define        MS_TM_NORMAL_WRITE              0x05
+#define        MS_TM_AUTO_READ                 0x08
+#define        MS_TM_AUTO_WRITE                0x0C
+#define MS_TM_SET_CMD                  0x06
+#define MS_TM_COPY_PAGE                        0x07
+#define MS_TM_MULTI_READ               0x02
+#define MS_TM_MULTI_WRITE              0x03
+
+/* MC_FIFO_CTL */
+#define FIFO_FLUSH                     0x01
+
+/* MC_DMA_RST */
+#define DMA_RESET  0x01
+
+/* MC_DMA_CTL */
+#define DMA_TC_EQ_0                    0x80
+#define DMA_DIR_TO_CARD                        0x00
+#define DMA_DIR_FROM_CARD              0x02
+#define DMA_EN                         0x01
+#define DMA_128                                (0 << 2)
+#define DMA_256                                (1 << 2)
+#define DMA_512                                (2 << 2)
+#define DMA_1024                       (3 << 2)
+#define DMA_PACK_SIZE_MASK             0x0C
+
+/* CARD_INT_PEND */
+#define XD_INT                         0x10
+#define MS_INT                         0x08
+#define SD_INT                         0x04
+
+/* LED operations*/
+static inline int rtsx_usb_turn_on_led(struct rtsx_ucr *ucr)
+{
+       return  rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x02);
+}
+
+static inline int rtsx_usb_turn_off_led(struct rtsx_ucr *ucr)
+{
+       return rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x03);
+}
+
+/* HW error clearing */
+static inline void rtsx_usb_clear_fsm_err(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);
+}
+
+static inline void rtsx_usb_clear_dma_err(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_ep0_write_register(ucr, MC_FIFO_CTL,
+                       FIFO_FLUSH, FIFO_FLUSH);
+       rtsx_usb_ep0_write_register(ucr, MC_DMA_RST, DMA_RESET, DMA_RESET);
+}
+#endif /* __RTS51139_H */
diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h
new file mode 100644 (file)
index 0000000..d2e357d
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * linux/mfd/tps65218.h
+ *
+ * Functions to access TPS65219 power management chip.
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ */
+
+#ifndef __LINUX_MFD_TPS65218_H
+#define __LINUX_MFD_TPS65218_H
+
+#include <linux/i2c.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/bitops.h>
+
+/* TPS chip id list */
+#define TPS65218                       0xF0
+
+/* I2C ID for TPS65218 part */
+#define TPS65218_I2C_ID                        0x24
+
+/* All register addresses */
+#define TPS65218_REG_CHIPID            0x00
+#define TPS65218_REG_INT1              0x01
+#define TPS65218_REG_INT2              0x02
+#define TPS65218_REG_INT_MASK1         0x03
+#define TPS65218_REG_INT_MASK2         0x04
+#define TPS65218_REG_STATUS            0x05
+#define TPS65218_REG_CONTROL           0x06
+#define TPS65218_REG_FLAG              0x07
+
+#define TPS65218_REG_PASSWORD          0x10
+#define TPS65218_REG_ENABLE1           0x11
+#define TPS65218_REG_ENABLE2           0x12
+#define TPS65218_REG_CONFIG1           0x13
+#define TPS65218_REG_CONFIG2           0x14
+#define TPS65218_REG_CONFIG3           0x15
+#define TPS65218_REG_CONTROL_DCDC1     0x16
+#define TPS65218_REG_CONTROL_DCDC2     0x17
+#define TPS65218_REG_CONTROL_DCDC3     0x18
+#define TPS65218_REG_CONTROL_DCDC4     0x19
+#define TPS65218_REG_CONTRL_SLEW_RATE  0x1A
+#define TPS65218_REG_CONTROL_LDO1      0x1B
+#define TPS65218_REG_SEQ1              0x20
+#define TPS65218_REG_SEQ2              0x21
+#define TPS65218_REG_SEQ3              0x22
+#define TPS65218_REG_SEQ4              0x23
+#define TPS65218_REG_SEQ5              0x24
+#define TPS65218_REG_SEQ6              0x25
+#define TPS65218_REG_SEQ7              0x26
+
+/* Register field definitions */
+#define TPS65218_CHIPID_CHIP_MASK      0xF8
+#define TPS65218_CHIPID_REV_MASK       0x07
+
+#define TPS65218_INT1_VPRG             BIT(5)
+#define TPS65218_INT1_AC               BIT(4)
+#define TPS65218_INT1_PB               BIT(3)
+#define TPS65218_INT1_HOT              BIT(2)
+#define TPS65218_INT1_CC_AQC           BIT(1)
+#define TPS65218_INT1_PRGC             BIT(0)
+
+#define TPS65218_INT2_LS3_F            BIT(5)
+#define TPS65218_INT2_LS2_F            BIT(4)
+#define TPS65218_INT2_LS1_F            BIT(3)
+#define TPS65218_INT2_LS3_I            BIT(2)
+#define TPS65218_INT2_LS2_I            BIT(1)
+#define TPS65218_INT2_LS1_I            BIT(0)
+
+#define TPS65218_INT_MASK1_VPRG                BIT(5)
+#define TPS65218_INT_MASK1_AC          BIT(4)
+#define TPS65218_INT_MASK1_PB          BIT(3)
+#define TPS65218_INT_MASK1_HOT         BIT(2)
+#define TPS65218_INT_MASK1_CC_AQC      BIT(1)
+#define TPS65218_INT_MASK1_PRGC                BIT(0)
+
+#define TPS65218_INT_MASK2_LS3_F       BIT(5)
+#define TPS65218_INT_MASK2_LS2_F       BIT(4)
+#define TPS65218_INT_MASK2_LS1_F       BIT(3)
+#define TPS65218_INT_MASK2_LS3_I       BIT(2)
+#define TPS65218_INT_MASK2_LS2_I       BIT(1)
+#define TPS65218_INT_MASK2_LS1_I       BIT(0)
+
+#define TPS65218_STATUS_FSEAL          BIT(7)
+#define TPS65218_STATUS_EE             BIT(6)
+#define TPS65218_STATUS_AC_STATE       BIT(5)
+#define TPS65218_STATUS_PB_STATE       BIT(4)
+#define TPS65218_STATUS_STATE_MASK     0xC
+#define TPS65218_STATUS_CC_STAT                0x3
+
+#define TPS65218_CONTROL_OFFNPFO       BIT(1)
+#define TPS65218_CONTROL_CC_AQ BIT(0)
+
+#define TPS65218_FLAG_GPO3_FLG         BIT(7)
+#define TPS65218_FLAG_GPO2_FLG         BIT(6)
+#define TPS65218_FLAG_GPO1_FLG         BIT(5)
+#define TPS65218_FLAG_LDO1_FLG         BIT(4)
+#define TPS65218_FLAG_DC4_FLG          BIT(3)
+#define TPS65218_FLAG_DC3_FLG          BIT(2)
+#define TPS65218_FLAG_DC2_FLG          BIT(1)
+#define TPS65218_FLAG_DC1_FLG          BIT(0)
+
+#define TPS65218_ENABLE1_DC6_EN                BIT(5)
+#define TPS65218_ENABLE1_DC5_EN                BIT(4)
+#define TPS65218_ENABLE1_DC4_EN                BIT(3)
+#define TPS65218_ENABLE1_DC3_EN                BIT(2)
+#define TPS65218_ENABLE1_DC2_EN                BIT(1)
+#define TPS65218_ENABLE1_DC1_EN                BIT(0)
+
+#define TPS65218_ENABLE2_GPIO3         BIT(6)
+#define TPS65218_ENABLE2_GPIO2         BIT(5)
+#define TPS65218_ENABLE2_GPIO1         BIT(4)
+#define TPS65218_ENABLE2_LS3_EN                BIT(3)
+#define TPS65218_ENABLE2_LS2_EN                BIT(2)
+#define TPS65218_ENABLE2_LS1_EN                BIT(1)
+#define TPS65218_ENABLE2_LDO1_EN       BIT(0)
+
+
+#define TPS65218_CONFIG1_TRST          BIT(7)
+#define TPS65218_CONFIG1_GPO2_BUF      BIT(6)
+#define TPS65218_CONFIG1_IO1_SEL       BIT(5)
+#define TPS65218_CONFIG1_PGDLY_MASK    0x18
+#define TPS65218_CONFIG1_STRICT                BIT(2)
+#define TPS65218_CONFIG1_UVLO_MASK     0x3
+
+#define TPS65218_CONFIG2_DC12_RST      BIT(7)
+#define TPS65218_CONFIG2_UVLOHYS       BIT(6)
+#define TPS65218_CONFIG2_LS3ILIM_MASK  0xC
+#define TPS65218_CONFIG2_LS2ILIM_MASK  0x3
+
+#define TPS65218_CONFIG3_LS3NPFO       BIT(5)
+#define TPS65218_CONFIG3_LS2NPFO       BIT(4)
+#define TPS65218_CONFIG3_LS1NPFO       BIT(3)
+#define TPS65218_CONFIG3_LS3DCHRG      BIT(2)
+#define TPS65218_CONFIG3_LS2DCHRG      BIT(1)
+#define TPS65218_CONFIG3_LS1DCHRG      BIT(0)
+
+#define TPS65218_CONTROL_DCDC1_PFM     BIT(7)
+#define TPS65218_CONTROL_DCDC1_MASK    0x7F
+
+#define TPS65218_CONTROL_DCDC2_PFM     BIT(7)
+#define TPS65218_CONTROL_DCDC2_MASK    0x3F
+
+#define TPS65218_CONTROL_DCDC3_PFM     BIT(7)
+#define TPS65218_CONTROL_DCDC3_MASK    0x3F
+
+#define TPS65218_CONTROL_DCDC4_PFM     BIT(7)
+#define TPS65218_CONTROL_DCDC4_MASK    0x3F
+
+#define TPS65218_SLEW_RATE_GO          BIT(7)
+#define TPS65218_SLEW_RATE_GODSBL      BIT(6)
+#define TPS65218_SLEW_RATE_SLEW_MASK   0x7
+
+#define TPS65218_CONTROL_LDO1_MASK     0x3F
+
+#define TPS65218_SEQ1_DLY8             BIT(7)
+#define TPS65218_SEQ1_DLY7             BIT(6)
+#define TPS65218_SEQ1_DLY6             BIT(5)
+#define TPS65218_SEQ1_DLY5             BIT(4)
+#define TPS65218_SEQ1_DLY4             BIT(3)
+#define TPS65218_SEQ1_DLY3             BIT(2)
+#define TPS65218_SEQ1_DLY2             BIT(1)
+#define TPS65218_SEQ1_DLY1             BIT(0)
+
+#define TPS65218_SEQ2_DLYFCTR          BIT(7)
+#define TPS65218_SEQ2_DLY9             BIT(0)
+
+#define TPS65218_SEQ3_DC2_SEQ_MASK     0xF0
+#define TPS65218_SEQ3_DC1_SEQ_MASK     0xF
+
+#define TPS65218_SEQ4_DC4_SEQ_MASK     0xF0
+#define TPS65218_SEQ4_DC3_SEQ_MASK     0xF
+
+#define TPS65218_SEQ5_DC6_SEQ_MASK     0xF0
+#define TPS65218_SEQ5_DC5_SEQ_MASK     0xF
+
+#define TPS65218_SEQ6_LS1_SEQ_MASK     0xF0
+#define TPS65218_SEQ6_LDO1_SEQ_MASK    0xF
+
+#define TPS65218_SEQ7_GPO3_SEQ_MASK    0xF0
+#define TPS65218_SEQ7_GPO1_SEQ_MASK    0xF
+#define TPS65218_PROTECT_NONE          0
+#define TPS65218_PROTECT_L1            1
+
+enum tps65218_regulator_id {
+       /* DCDC's */
+       TPS65218_DCDC_1,
+       TPS65218_DCDC_2,
+       TPS65218_DCDC_3,
+       TPS65218_DCDC_4,
+       TPS65218_DCDC_5,
+       TPS65218_DCDC_6,
+       /* LDOs */
+       TPS65218_LDO_1,
+};
+
+#define TPS65218_MAX_REG_ID            TPS65218_LDO_1
+
+/* Number of step-down converters available */
+#define TPS65218_NUM_DCDC              6
+/* Number of LDO voltage regulators available */
+#define TPS65218_NUM_LDO               1
+/* Number of total regulators available */
+#define TPS65218_NUM_REGULATOR         (TPS65218_NUM_DCDC + TPS65218_NUM_LDO)
+
+/* Define the TPS65218 IRQ numbers */
+enum tps65218_irqs {
+       /* INT1 registers */
+       TPS65218_PRGC_IRQ,
+       TPS65218_CC_AQC_IRQ,
+       TPS65218_HOT_IRQ,
+       TPS65218_PB_IRQ,
+       TPS65218_AC_IRQ,
+       TPS65218_VPRG_IRQ,
+       TPS65218_INVALID1_IRQ,
+       TPS65218_INVALID2_IRQ,
+       /* INT2 registers */
+       TPS65218_LS1_I_IRQ,
+       TPS65218_LS2_I_IRQ,
+       TPS65218_LS3_I_IRQ,
+       TPS65218_LS1_F_IRQ,
+       TPS65218_LS2_F_IRQ,
+       TPS65218_LS3_F_IRQ,
+       TPS65218_INVALID3_IRQ,
+       TPS65218_INVALID4_IRQ,
+};
+
+/**
+ * struct tps_info - packages regulator constraints
+ * @id:                        Id of the regulator
+ * @name:              Voltage regulator name
+ * @min_uV:            minimum micro volts
+ * @max_uV:            minimum micro volts
+ *
+ * This data is used to check the regualtor voltage limits while setting.
+ */
+struct tps_info {
+       int id;
+       const char *name;
+       int min_uV;
+       int max_uV;
+};
+
+/**
+ * struct tps65218 - tps65218 sub-driver chip access routines
+ *
+ * Device data may be used to access the TPS65218 chip
+ */
+
+struct tps65218 {
+       struct device *dev;
+       unsigned int id;
+
+       struct mutex tps_lock;          /* lock guarding the data structure */
+       /* IRQ Data */
+       int irq;
+       u32 irq_mask;
+       struct regmap_irq_chip_data *irq_data;
+       struct regulator_desc desc[TPS65218_NUM_REGULATOR];
+       struct regulator_dev *rdev[TPS65218_NUM_REGULATOR];
+       struct tps_info *info[TPS65218_NUM_REGULATOR];
+       struct regmap *regmap;
+};
+
+int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
+                                       unsigned int *val);
+int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level);
+int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level);
+int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level);
+
+#endif /*  __LINUX_MFD_TPS65218_H */
index bcbb642..087b08a 100644 (file)
 int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len);
 int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len);
 
+static inline int
+ssbi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+       int ret;
+       u8 v;
+
+       ret = ssbi_read(context, reg, &v, 1);
+       if (!ret)
+               *val = v;
+
+       return ret;
+}
+
+static inline int
+ssbi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+       u8 v = val;
+       return ssbi_write(context, reg, &v, 1);
+}
+
 #endif