Merge tag 'mfd-for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Nov 2015 18:23:50 +0000 (10:23 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Nov 2015 18:23:50 +0000 (10:23 -0800)
Pull MFD updates from Lee Jones:
 "New Device Support:
   - Add support for 88pm860; 88pm80x
   - Add support for 24c08 EEPROM; at24
   - Add support for Broxton Whiskey Cove; intel*
   - Add support for RTS522A; rts5227
   - Add support for I2C devices; intel_quark_i2c_gpio

  New Functionality:
   - Add microphone support; arizona
   - Add general purpose switch support; arizona
   - Add fuel-gauge support; da9150-core
   - Add shutdown support; sec-core
   - Add charger support; tps65217
   - Add flexible serial communication unit support; atmel-flexcom
   - Add power button support; axp20x
   - Add led-flash support; rt5033

  Core Frameworks:
   - Supply a generic macro for defining Regmap IRQs
   - Rework ACPI child device matching

  Fix-ups:
   - Use Regmap to access registers; tps6105x
   - Use DEFINE_RES_IRQ_NAMED() macro; da9150
   - Re-arrange device registration order; intel_quark_i2c_gpio
   - Allow OF matching; cros_ec_i2c, atmel-hlcdc, hi6421-pmic, max8997, sm501
   - Handle deferred probe; twl6040
   - Improve accuracy of headphone detect; arizona
   - Unnecessary MODULE_ALIAS() removal; bcm590xx, rt5033
   - Remove unused code; htc-i2cpld, arizona, pcf50633-irq, sec-core
   - Simplify code; kempld, rts5209, da903x, lm3533, da9052, arizona
   - Remove #iffery; arizona
   - DT binding adaptions; many

  Bug Fixes:
   - Fix possible NULL pointer dereference; wm831x, tps6105x
   - Fix 64bit bug; intel_soc_pmic_bxtwc
   - Fix signedness issue; arizona"

* tag 'mfd-for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (73 commits)
  bindings: mfd: s2mps11: Add documentation for s2mps15 PMIC
  mfd: sec-core: Remove unused s2mpu02-rtc and s2mpu02-clk children
  extcon: arizona: Add extcon specific device tree binding document
  MAINTAINERS: Add binding docs for Cirrus Logic/Wolfson Arizona devices
  mfd: arizona: Remove bindings covered in new subsystem specific docs
  mfd: rt5033: Add RT5033 Flash led sub device
  mfd: lpss: Add Intel Broxton PCI IDs
  mfd: lpss: Add Broxton ACPI IDs
  mfd: arizona: Signedness bug in arizona_runtime_suspend()
  mfd: axp20x: Add a cell for the power button part of the, axp288 PMICs
  mfd: dt-bindings: Document pulled down WRSTBI pin on S2MPS1X
  mfd: sec-core: Disable buck voltage reset on watchdog falling edge
  mfd: sec-core: Dump PMIC revision to find out the HW
  mfd: arizona: Use correct type ID for device tree config
  mfd: arizona: Remove use of codec build config #ifdefs
  mfd: arizona: Simplify adding subdevices
  mfd: arizona: Downgrade type mismatch messages to dev_warn
  mfd: arizona: Factor out checking of jack detection state
  mfd: arizona: Factor out DCVDD isolation control
  mfd: Make TPS6105X select REGMAP_I2C
  ...

74 files changed:
Documentation/acpi/enumeration.txt
Documentation/devicetree/bindings/extcon/extcon-arizona.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/arizona.txt
Documentation/devicetree/bindings/mfd/atmel-flexcom.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/cros-ec.txt
Documentation/devicetree/bindings/mfd/da9150.txt
Documentation/devicetree/bindings/mfd/s2mps11.txt
Documentation/devicetree/bindings/power/da9150-fg.txt [new file with mode: 0644]
MAINTAINERS
drivers/mfd/88pm80x.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/arizona-core.c
drivers/mfd/arizona-i2c.c
drivers/mfd/arizona-irq.c
drivers/mfd/arizona-spi.c
drivers/mfd/atmel-flexcom.c [new file with mode: 0644]
drivers/mfd/atmel-hlcdc.c
drivers/mfd/axp20x.c
drivers/mfd/bcm590xx.c
drivers/mfd/cros_ec_i2c.c
drivers/mfd/da903x.c
drivers/mfd/da9052-core.c
drivers/mfd/da9052-i2c.c
drivers/mfd/da9052-spi.c
drivers/mfd/da9062-core.c
drivers/mfd/da9150-core.c
drivers/mfd/hi6421-pmic-core.c
drivers/mfd/htc-i2cpld.c
drivers/mfd/intel-lpss-acpi.c
drivers/mfd/intel-lpss-pci.c
drivers/mfd/intel-lpss.c
drivers/mfd/intel_quark_i2c_gpio.c
drivers/mfd/intel_soc_pmic_bxtwc.c [new file with mode: 0644]
drivers/mfd/kempld-core.c
drivers/mfd/lm3533-core.c
drivers/mfd/lpc_ich.c
drivers/mfd/max8997.c
drivers/mfd/mfd-core.c
drivers/mfd/pcf50633-irq.c
drivers/mfd/qcom_rpm.c
drivers/mfd/rt5033.c
drivers/mfd/rts5209.c
drivers/mfd/rts5227.c
drivers/mfd/rts5229.c
drivers/mfd/rts5249.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/rtsx_pcr.h
drivers/mfd/sec-core.c
drivers/mfd/sm501.c
drivers/mfd/stmpe.c
drivers/mfd/tps6105x.c
drivers/mfd/tps65217.c
drivers/mfd/twl6040.c
drivers/mfd/wm5110-tables.c
drivers/mfd/wm831x-core.c
drivers/mfd/wm8998-tables.c
drivers/misc/eeprom/at24.c
drivers/platform/x86/Kconfig
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/da9150-fg.c [new file with mode: 0644]
include/dt-bindings/mfd/atmel-flexcom.h [new file with mode: 0644]
include/linux/mfd/88pm80x.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/core.h
include/linux/mfd/da9052/reg.h
include/linux/mfd/da9150/core.h
include/linux/mfd/intel_bxtwc.h [new file with mode: 0644]
include/linux/mfd/intel_soc_pmic.h
include/linux/mfd/rtsx_pci.h
include/linux/mfd/samsung/core.h
include/linux/mfd/samsung/s2mps11.h
include/linux/mfd/samsung/s2mps13.h

index b731b292e8128e30439ae54c1f0f328b56e79b72..a91ec5af52df28cf3ff3c2ae03b163272caae0e6 100644 (file)
@@ -347,13 +347,18 @@ For the first case, the MFD drivers do not need to do anything. The
 resulting child platform device will have its ACPI_COMPANION() set to point
 to the parent device.
 
-If the ACPI namespace has a device that we can match using an ACPI id,
-the id should be set like:
+If the ACPI namespace has a device that we can match using an ACPI id or ACPI
+adr, the cell should be set like:
+
+       static struct mfd_cell_acpi_match my_subdevice_cell_acpi_match = {
+               .pnpid = "XYZ0001",
+               .adr = 0,
+       };
 
        static struct mfd_cell my_subdevice_cell = {
                .name = "my_subdevice",
                /* set the resources relative to the parent */
-               .acpi_pnpid = "XYZ0001",
+               .acpi_match = &my_subdevice_cell_acpi_match,
        };
 
 The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
diff --git a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt
new file mode 100644 (file)
index 0000000..e1705fa
--- /dev/null
@@ -0,0 +1,15 @@
+Cirrus Logic Arizona class audio SoCs
+
+These devices are audio SoCs with extensive digital capabilities and a range
+of analogue I/O.
+
+This document lists Extcon specific bindings, see the primary binding document:
+  ../mfd/arizona.txt
+
+Optional properties:
+
+  - wlf,hpdet-channel : Headphone detection channel.
+    ARIZONA_ACCDET_MODE_HPL or 1 - Headphone detect mode is set to HPDETL
+    ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR
+    If this node is not mentioned or if the value is unknown, then
+    headphone detection mode is set to HPDETL.
index a8fee60dc20d0b9f1b858c11d54d1c8f1b21fcba..18be0cbfb456c92d47d959a98bdc9d27bb8f08bc 100644 (file)
@@ -44,7 +44,6 @@ Required properties:
 Optional properties:
 
   - wlf,reset : GPIO specifier for the GPIO controlling /RESET
-  - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA
 
   - wlf,gpio-defaults : A list of GPIO configuration register values. Defines
     for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
@@ -67,21 +66,13 @@ Optional properties:
     present, the number of values should be less than or equal to the
     number of inputs, unspecified inputs will use the chip default.
 
-  - wlf,hpdet-channel : Headphone detection channel.
-    ARIZONA_ACCDET_MODE_HPL or 1 - Headphone detect mode is set to HPDETL
-    ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR
-    If this node is not mentioned or if the value is unknown, then
-    headphone detection mode is set to HPDETL.
-
   - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
     they are being externally supplied. As covered in
     Documentation/devicetree/bindings/regulator/regulator.txt
 
-Optional subnodes:
-  - ldo1 : Initial data for the LDO1 regulator, as covered in
-    Documentation/devicetree/bindings/regulator/regulator.txt
-  - micvdd : Initial data for the MICVDD regulator, as covered in
-    Documentation/devicetree/bindings/regulator/regulator.txt
+Also see child specific device properties:
+  Regulator - ../regulator/arizona-regulator.txt
+  Extcon    - ../extcon/extcon-arizona.txt
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt b/Documentation/devicetree/bindings/mfd/atmel-flexcom.txt
new file mode 100644 (file)
index 0000000..6923001
--- /dev/null
@@ -0,0 +1,63 @@
+* Device tree bindings for Atmel Flexcom (Flexible Serial Communication Unit)
+
+The Atmel Flexcom is just a wrapper which embeds a SPI controller, an I2C
+controller and an USART. Only one function can be used at a time and is chosen
+at boot time according to the device tree.
+
+Required properties:
+- compatible:          Should be "atmel,sama5d2-flexcom"
+- reg:                 Should be the offset/length value for Flexcom dedicated
+                       I/O registers (without USART, TWI or SPI registers).
+- clocks:              Should be the Flexcom peripheral clock from PMC.
+- #address-cells:      Should be <1>
+- #size-cells:         Should be <1>
+- ranges:              Should be one range for the full I/O register region
+                       (including USART, TWI and SPI registers).
+- atmel,flexcom-mode:  Should be one of the following values:
+                       - <1> for USART
+                       - <2> for SPI
+                       - <3> for I2C
+
+Required child:
+A single available child device of type matching the "atmel,flexcom-mode"
+property.
+
+The phandle provided by the clocks property of the child is the same as one for
+the Flexcom parent.
+
+For other properties, please refer to the documentations of the respective
+device:
+- ../serial/atmel-usart.txt
+- ../spi/spi_atmel.txt
+- ../i2c/i2c-at91.txt
+
+Example:
+
+flexcom@f8034000 {
+       compatible = "atmel,sama5d2-flexcom";
+       reg = <0xf8034000 0x200>;
+       clocks = <&flx0_clk>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x0 0xf8034000 0x800>;
+       atmel,flexcom-mode = <2>;
+
+       spi@400 {
+               compatible = "atmel,at91rm9200-spi";
+               reg = <0x400 0x200>;
+               interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_flx0_default>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&flx0_clk>;
+               clock-names = "spi_clk";
+               atmel,fifo-size = <32>;
+
+               mtd_dataflash@0 {
+                       compatible = "atmel,at25f512b";
+                       reg = <0>;
+                       spi-max-frequency = <20000000>;
+               };
+       };
+};
index 1777916e9e280440f3bf6bac5066efd6eb92274e..136e0c2da44d100df1307617be5d4cdbd9dd4f23 100644 (file)
@@ -34,6 +34,10 @@ Required properties (LPC):
 - compatible: "google,cros-ec-lpc"
 - reg: List of (IO address, size) pairs defining the interface uses
 
+Optional properties (all):
+- google,has-vbc-nvram: Some implementations of the EC include a small
+  nvram space used to store verified boot context data. This boolean flag
+  is used to specify whether this nvram is present or not.
 
 Example for I2C:
 
index d0588eaa0d714d6b55958ad79f257a9d97fa9b5b..fd4dca7f4abab61523b2d5da8ed97ddd75537c5b 100644 (file)
@@ -6,6 +6,7 @@ Device                   Description
 ------                  -----------
 da9150-gpadc           : General Purpose ADC
 da9150-charger         : Battery Charger
+da9150-fg              : Battery Fuel-Gauge
 
 ======
 
@@ -16,13 +17,13 @@ Required properties:
   the IRQs from da9150 are delivered to.
 - interrupts: IRQ line info for da9150 chip.
 - interrupt-controller: da9150 has internal IRQs (own IRQ domain).
-  (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+  (See ../interrupt-controller/interrupts.txt for
    further information relating to interrupt properties)
 
 Sub-devices:
-- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
-- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt
-
+- da9150-gpadc: See ../iio/adc/da9150-gpadc.txt
+- da9150-charger: See ../power/da9150-charger.txt
+- da9150-fg: See ../power/da9150-fg.txt
 
 Example:
 
@@ -34,10 +35,28 @@ Example:
                interrupt-controller;
 
                gpadc: da9150-gpadc {
-                       ...
+                       compatible = "dlg,da9150-gpadc";
+                       #io-channel-cells = <1>;
+               };
+
+               charger {
+                       compatible = "dlg,da9150-charger";
+
+                       io-channels = <&gpadc 0>,
+                                     <&gpadc 2>,
+                                     <&gpadc 8>,
+                                     <&gpadc 5>;
+                       io-channel-names = "CHAN_IBUS",
+                                          "CHAN_VBUS",
+                                          "CHAN_TJUNC",
+                                          "CHAN_VBAT";
                };
 
-               da9150-charger {
-                       ...
+               fuel-gauge {
+                       compatible = "dlg,da9150-fuel-gauge";
+
+                       dlg,update-interval = <10000>;
+                       dlg,warn-soc-level = /bits/ 8 <15>;
+                       dlg,crit-soc-level = /bits/ 8 <5>
                };
        };
index 57a045016fca68b6408db6b13f472ba7c17c5e84..a42adda944bf146c382f71009884c755f10df87b 100644 (file)
@@ -1,5 +1,5 @@
 
-* Samsung S2MPS11, S2MPS13, S2MPS14 and S2MPU02 Voltage and Current Regulator
+* Samsung S2MPS11/13/14/15 and S2MPU02 Voltage and Current Regulator
 
 The Samsung S2MPS11 is a multi-function device which includes voltage and
 current regulators, RTC, charger controller and other sub-blocks. It is
@@ -7,17 +7,24 @@ interfaced to the host controller using an I2C interface. Each sub-block is
 addressed by the host system using different I2C slave addresses.
 
 Required properties:
-- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps13-pmic"
-             or "samsung,s2mps14-pmic" or "samsung,s2mpu02-pmic".
+- compatible: Should be one of the following
+       - "samsung,s2mps11-pmic"
+       - "samsung,s2mps13-pmic"
+       - "samsung,s2mps14-pmic"
+       - "samsung,s2mps15-pmic"
+       - "samsung,s2mpu02-pmic".
 - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
 
 Optional properties:
 - interrupt-parent: Specifies the phandle of the interrupt controller to which
   the interrupts from s2mps11 are delivered to.
 - interrupts: Interrupt specifiers for interrupt sources.
+- samsung,s2mps11-wrstbi-ground: Indicates that WRSTBI pin of PMIC is pulled
+  down. When the system is suspended it will always go down thus triggerring
+  unwanted buck warm reset (setting buck voltages to default values).
 
 Optional nodes:
-- clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768
+- clocks: s2mps11, s2mps13, s2mps15 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 :
@@ -30,12 +37,13 @@ Optional nodes:
     the clock which they consume.
     Clock               ID           Devices
     ----------------------------------------------------------
-    32KhzAP            0            S2MPS11, S2MPS13, S2MPS14, S5M8767
-    32KhzCP            1            S2MPS11, S2MPS13, S5M8767
-    32KhzBT            2            S2MPS11, S2MPS13, S2MPS14, S5M8767
+    32KhzAP            0            S2MPS11, S2MPS13, S2MPS14, S2MPS15, S5M8767
+    32KhzCP            1            S2MPS11, S2MPS13, S2MPS15, S5M8767
+    32KhzBT            2            S2MPS11, S2MPS13, S2MPS14, S2MPS15, S5M8767
 
   - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk",
                "samsung,s2mps14-clk", "samsung,s5m8767-clk"
+    The s2msp15 uses the same compatible as s2mps13, as both provides similar clocks.
 
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
@@ -83,6 +91,7 @@ as per the datasheet of s2mps11.
                        - S2MPS11: 1 to 38
                        - S2MPS13: 1 to 40
                        - S2MPS14: 1 to 25
+                       - S2MPS15: 1 to 27
                        - S2MPU02: 1 to 28
                  - Example: LDO1, LDO2, LDO28
        - BUCKn
@@ -90,6 +99,7 @@ as per the datasheet of s2mps11.
                        - S2MPS11: 1 to 10
                        - S2MPS13: 1 to 10
                        - S2MPS14: 1 to 5
+                       - S2MPS15: 1 to 10
                        - S2MPU02: 1 to 7
                  - Example: BUCK1, BUCK2, BUCK9
 
diff --git a/Documentation/devicetree/bindings/power/da9150-fg.txt b/Documentation/devicetree/bindings/power/da9150-fg.txt
new file mode 100644 (file)
index 0000000..00236fe
--- /dev/null
@@ -0,0 +1,23 @@
+Dialog Semiconductor DA9150 Fuel-Gauge Power Supply bindings
+
+Required properties:
+- compatible: "dlg,da9150-fuel-gauge" for DA9150 Fuel-Gauge Power Supply
+
+Optional properties:
+- dlg,update-interval: Interval time (milliseconds) between battery level checks.
+- dlg,warn-soc-level: Battery discharge level (%) where warning event raised.
+      [1 - 100]
+- dlg,crit-soc-level: Battery discharge level (%) where critical event raised.
+  This value should be lower than the warning level.
+      [1 - 100]
+
+
+Example:
+
+       fuel-gauge {
+               compatible = "dlg,da9150-fuel-gauge";
+
+               dlg,update-interval = <10000>;
+               dlg,warn-soc-level = /bits/ 8 <15>;
+               dlg,crit-soc-level = /bits/ 8 <5>;
+       };
index 15c38961d6ff9368d2cdb8a74cf9e3bb6868c002..653ee9a7a3b87b62dfac9d13190361c636b0fc0b 100644 (file)
@@ -7162,7 +7162,6 @@ F:        drivers/media/i2c/mt9v032.c
 F:     include/media/mt9v032.h
 
 MULTIFUNCTION DEVICES (MFD)
-M:     Samuel Ortiz <sameo@linux.intel.com>
 M:     Lee Jones <lee.jones@linaro.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
 S:     Supported
@@ -11567,6 +11566,9 @@ T:      git https://github.com/CirrusLogic/linux-drivers.git
 W:     https://github.com/CirrusLogic/linux-drivers/wiki
 S:     Supported
 F:     Documentation/hwmon/wm83??
+F:     Documentation/devicetree/bindings/extcon/extcon-arizona.txt
+F:     Documentation/devicetree/bindings/regulator/arizona-regulator.txt
+F:     Documentation/devicetree/bindings/mfd/arizona.txt
 F:     arch/arm/mach-s3c64xx/mach-crag6410*
 F:     drivers/clk/clk-wm83*.c
 F:     drivers/extcon/extcon-arizona.c
index 5e72f65ef94c3f48c4643dfa9f366dd8782ac956..63445ea6b0bfe2481c681e657d1b16d0abd7fea3 100644 (file)
@@ -33,6 +33,8 @@ static struct pm80x_chip_mapping chip_mapping[] = {
        {0x3,   CHIP_PM800},
        /* 88PM805 chip id number */
        {0x0,   CHIP_PM805},
+       /* 88PM860 chip id number */
+       {0x4,   CHIP_PM860},
 };
 
 /*
index 99d63675f073f1c44146131df04a7bc13bdae0cc..4d92df6ef9fe92ac69c6f26e99e33f83e7e2ac71 100644 (file)
@@ -60,6 +60,17 @@ config MFD_AAT2870_CORE
          additional drivers must be enabled in order to use the
          functionality of the device.
 
+config MFD_ATMEL_FLEXCOM
+       tristate "Atmel Flexcom (Flexible Serial Communication Unit)"
+       select MFD_CORE
+       depends on OF
+       help
+         Select this to get support for Atmel Flexcom. This is a wrapper
+         which embeds a SPI controller, a I2C controller and a USART. Only
+         one function can be used at a time. The choice is done at boot time
+         by the probe function of this MFD driver according to a device tree
+         property.
+
 config MFD_ATMEL_HLCDC
        tristate "Atmel HLCDC (High-end LCD Controller)"
        select MFD_CORE
@@ -725,9 +736,10 @@ config MFD_RTSX_PCI
        select MFD_CORE
        help
          This supports for Realtek PCI-Express card reader including rts5209,
-         rts5229, rtl8411, etc. Realtek card reader supports access to many
-         types of memory cards, such as Memory Stick, Memory Stick Pro,
-         Secure Digital and MultiMediaCard.
+         rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
+         Realtek card reader supports access to many types of memory cards,
+         such as Memory Stick, Memory Stick Pro, Secure Digital and
+         MultiMediaCard.
 
 config MFD_RT5033
        tristate "Richtek RT5033 Power Management IC"
@@ -1059,6 +1071,7 @@ config MFD_PALMAS
 config TPS6105X
        tristate "TI TPS61050/61052 Boost Converters"
        depends on I2C
+       select REGMAP_I2C
        select REGULATOR
        select MFD_CORE
        select REGULATOR_FIXED_VOLTAGE
@@ -1471,7 +1484,7 @@ config MFD_WM8994
 
 config MFD_STW481X
        tristate "Support for ST Microelectronics STw481x"
-       depends on I2C && ARCH_NOMADIK
+       depends on I2C && (ARCH_NOMADIK || COMPILE_TEST)
        select REGMAP_I2C
        select MFD_CORE
        help
index a59e3fcc8626d5fcc313bb708dc69a1f070be926..a8b76b81b467987383c7a857f2dc5f0620a5b4dc 100644 (file)
@@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_FLEXCOM)        += atmel-flexcom.o
 obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_LPSS)   += intel-lpss.o
 obj-$(CONFIG_MFD_INTEL_LPSS_PCI)       += intel-lpss-pci.o
@@ -190,5 +191,6 @@ obj-$(CONFIG_MFD_RT5033)    += rt5033.o
 obj-$(CONFIG_MFD_SKY81452)     += sky81452.o
 
 intel-soc-pmic-objs            := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)   += intel-soc-pmic.o
 obj-$(CONFIG_MFD_MT6397)       += mt6397-core.o
index 44cfdbb295dbca2e805635c426966e21b2b71c16..d474732cc65c80becb53ae93cb3b3699564d4cf0 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 #include <linux/slab.h>
+#include <linux/platform_device.h>
 
 #include <linux/mfd/arizona/core.h>
 #include <linux/mfd/arizona/registers.h>
@@ -69,8 +70,6 @@ EXPORT_SYMBOL_GPL(arizona_clk32k_enable);
 
 int arizona_clk32k_disable(struct arizona *arizona)
 {
-       int ret = 0;
-
        mutex_lock(&arizona->clk_lock);
 
        BUG_ON(arizona->clk32k_ref <= 0);
@@ -90,7 +89,7 @@ int arizona_clk32k_disable(struct arizona *arizona)
 
        mutex_unlock(&arizona->clk_lock);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_clk32k_disable);
 
@@ -462,6 +461,50 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona)
 }
 
 #ifdef CONFIG_PM
+static int arizona_isolate_dcvdd(struct arizona *arizona)
+{
+       int ret;
+
+       ret = regmap_update_bits(arizona->regmap,
+                                ARIZONA_ISOLATION_CONTROL,
+                                ARIZONA_ISOLATE_DCVDD1,
+                                ARIZONA_ISOLATE_DCVDD1);
+       if (ret != 0)
+               dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret);
+
+       return ret;
+}
+
+static int arizona_connect_dcvdd(struct arizona *arizona)
+{
+       int ret;
+
+       ret = regmap_update_bits(arizona->regmap,
+                                ARIZONA_ISOLATION_CONTROL,
+                                ARIZONA_ISOLATE_DCVDD1, 0);
+       if (ret != 0)
+               dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret);
+
+       return ret;
+}
+
+static int arizona_is_jack_det_active(struct arizona *arizona)
+{
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
+       if (ret) {
+               dev_err(arizona->dev,
+                       "Failed to check jack det status: %d\n", ret);
+               return ret;
+       } else if (val & ARIZONA_JD1_ENA) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 static int arizona_runtime_resume(struct device *dev)
 {
        struct arizona *arizona = dev_get_drvdata(dev);
@@ -501,14 +544,9 @@ static int arizona_runtime_resume(struct device *dev)
        switch (arizona->type) {
        case WM5102:
                if (arizona->external_dcvdd) {
-                       ret = regmap_update_bits(arizona->regmap,
-                                                ARIZONA_ISOLATION_CONTROL,
-                                                ARIZONA_ISOLATE_DCVDD1, 0);
-                       if (ret != 0) {
-                               dev_err(arizona->dev,
-                                       "Failed to connect DCVDD: %d\n", ret);
+                       ret = arizona_connect_dcvdd(arizona);
+                       if (ret != 0)
                                goto err;
-                       }
                }
 
                ret = wm5102_patch(arizona);
@@ -533,14 +571,9 @@ static int arizona_runtime_resume(struct device *dev)
                        goto err;
 
                if (arizona->external_dcvdd) {
-                       ret = regmap_update_bits(arizona->regmap,
-                                                ARIZONA_ISOLATION_CONTROL,
-                                                ARIZONA_ISOLATE_DCVDD1, 0);
-                       if (ret) {
-                               dev_err(arizona->dev,
-                                       "Failed to connect DCVDD: %d\n", ret);
+                       ret = arizona_connect_dcvdd(arizona);
+                       if (ret != 0)
                                goto err;
-                       }
                } else {
                        /*
                         * As this is only called for the internal regulator
@@ -571,14 +604,9 @@ static int arizona_runtime_resume(struct device *dev)
                        goto err;
 
                if (arizona->external_dcvdd) {
-                       ret = regmap_update_bits(arizona->regmap,
-                                                ARIZONA_ISOLATION_CONTROL,
-                                                ARIZONA_ISOLATE_DCVDD1, 0);
-                       if (ret != 0) {
-                               dev_err(arizona->dev,
-                                       "Failed to connect DCVDD: %d\n", ret);
+                       ret = arizona_connect_dcvdd(arizona);
+                       if (ret != 0)
                                goto err;
-                       }
                }
                break;
        }
@@ -600,49 +628,50 @@ err:
 static int arizona_runtime_suspend(struct device *dev)
 {
        struct arizona *arizona = dev_get_drvdata(dev);
-       unsigned int val;
+       int jd_active = 0;
        int ret;
 
        dev_dbg(arizona->dev, "Entering AoD mode\n");
 
-       ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val);
-       if (ret) {
-               dev_err(dev, "Failed to check jack det status: %d\n", ret);
-               return ret;
-       }
-
-       if (arizona->external_dcvdd) {
-               ret = regmap_update_bits(arizona->regmap,
-                                        ARIZONA_ISOLATION_CONTROL,
-                                        ARIZONA_ISOLATE_DCVDD1,
-                                        ARIZONA_ISOLATE_DCVDD1);
-               if (ret != 0) {
-                       dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n",
-                               ret);
-                       return ret;
-               }
-       }
-
        switch (arizona->type) {
        case WM5110:
        case WM8280:
-               if (arizona->external_dcvdd)
-                       break;
+               jd_active = arizona_is_jack_det_active(arizona);
+               if (jd_active < 0)
+                       return jd_active;
 
-               /*
-                * As this is only called for the internal regulator
-                * (where we know voltage ranges available) it is ok
-                * to request an exact range.
-                */
-               ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000);
-               if (ret < 0) {
-                       dev_err(arizona->dev,
-                               "Failed to set suspend voltage: %d\n", ret);
-                       return ret;
+               if (arizona->external_dcvdd) {
+                       ret = arizona_isolate_dcvdd(arizona);
+                       if (ret != 0)
+                               return ret;
+               } else {
+                       /*
+                        * As this is only called for the internal regulator
+                        * (where we know voltage ranges available) it is ok
+                        * to request an exact range.
+                        */
+                       ret = regulator_set_voltage(arizona->dcvdd,
+                                                   1175000, 1175000);
+                       if (ret < 0) {
+                               dev_err(arizona->dev,
+                                       "Failed to set suspend voltage: %d\n",
+                                       ret);
+                               return ret;
+                       }
                }
                break;
        case WM5102:
-               if (!(val & ARIZONA_JD1_ENA)) {
+               jd_active = arizona_is_jack_det_active(arizona);
+               if (jd_active < 0)
+                       return jd_active;
+
+               if (arizona->external_dcvdd) {
+                       ret = arizona_isolate_dcvdd(arizona);
+                       if (ret != 0)
+                               return ret;
+               }
+
+               if (!jd_active) {
                        ret = regmap_write(arizona->regmap,
                                           ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0);
                        if (ret) {
@@ -654,6 +683,15 @@ static int arizona_runtime_suspend(struct device *dev)
                }
                break;
        default:
+               jd_active = arizona_is_jack_det_active(arizona);
+               if (jd_active < 0)
+                       return jd_active;
+
+               if (arizona->external_dcvdd) {
+                       ret = arizona_isolate_dcvdd(arizona);
+                       if (ret != 0)
+                               return ret;
+               }
                break;
        }
 
@@ -662,7 +700,7 @@ static int arizona_runtime_suspend(struct device *dev)
        regulator_disable(arizona->dcvdd);
 
        /* Allow us to completely power down if no jack detection */
-       if (!(val & ARIZONA_JD1_ENA)) {
+       if (!jd_active) {
                dev_dbg(arizona->dev, "Fully powering off\n");
 
                arizona->has_fully_powered_off = true;
@@ -928,7 +966,8 @@ int arizona_dev_init(struct arizona *arizona)
        const char *type_name;
        unsigned int reg, val, mask;
        int (*apply_patch)(struct arizona *) = NULL;
-       int ret, i;
+       const struct mfd_cell *subdevs = NULL;
+       int n_subdevs, ret, i;
 
        dev_set_drvdata(arizona->dev, arizona);
        mutex_init(&arizona->clk_lock);
@@ -1089,74 +1128,95 @@ int arizona_dev_init(struct arizona *arizona)
        arizona->rev &= ARIZONA_DEVICE_REVISION_MASK;
 
        switch (reg) {
-#ifdef CONFIG_MFD_WM5102
        case 0x5102:
-               type_name = "WM5102";
-               if (arizona->type != WM5102) {
-                       dev_err(arizona->dev, "WM5102 registered as %d\n",
-                               arizona->type);
-                       arizona->type = WM5102;
+               if (IS_ENABLED(CONFIG_MFD_WM5102)) {
+                       type_name = "WM5102";
+                       if (arizona->type != WM5102) {
+                               dev_warn(arizona->dev,
+                                        "WM5102 registered as %d\n",
+                                        arizona->type);
+                               arizona->type = WM5102;
+                       }
+
+                       apply_patch = wm5102_patch;
+                       arizona->rev &= 0x7;
+                       subdevs = wm5102_devs;
+                       n_subdevs = ARRAY_SIZE(wm5102_devs);
                }
-               apply_patch = wm5102_patch;
-               arizona->rev &= 0x7;
                break;
-#endif
-#ifdef CONFIG_MFD_WM5110
        case 0x5110:
-               switch (arizona->type) {
-               case WM5110:
-                       type_name = "WM5110";
-                       break;
-               case WM8280:
-                       type_name = "WM8280";
-                       break;
-               default:
-                       type_name = "WM5110";
-                       dev_err(arizona->dev, "WM5110 registered as %d\n",
-                               arizona->type);
-                       arizona->type = WM5110;
-                       break;
+               if (IS_ENABLED(CONFIG_MFD_WM5110)) {
+                       switch (arizona->type) {
+                       case WM5110:
+                               type_name = "WM5110";
+                               break;
+                       case WM8280:
+                               type_name = "WM8280";
+                               break;
+                       default:
+                               type_name = "WM5110";
+                               dev_warn(arizona->dev,
+                                        "WM5110 registered as %d\n",
+                                        arizona->type);
+                               arizona->type = WM5110;
+                               break;
+                       }
+
+                       apply_patch = wm5110_patch;
+                       subdevs = wm5110_devs;
+                       n_subdevs = ARRAY_SIZE(wm5110_devs);
                }
-               apply_patch = wm5110_patch;
                break;
-#endif
-#ifdef CONFIG_MFD_WM8997
        case 0x8997:
-               type_name = "WM8997";
-               if (arizona->type != WM8997) {
-                       dev_err(arizona->dev, "WM8997 registered as %d\n",
-                               arizona->type);
-                       arizona->type = WM8997;
+               if (IS_ENABLED(CONFIG_MFD_WM8997)) {
+                       type_name = "WM8997";
+                       if (arizona->type != WM8997) {
+                               dev_warn(arizona->dev,
+                                        "WM8997 registered as %d\n",
+                                        arizona->type);
+                               arizona->type = WM8997;
+                       }
+
+                       apply_patch = wm8997_patch;
+                       subdevs = wm8997_devs;
+                       n_subdevs = ARRAY_SIZE(wm8997_devs);
                }
-               apply_patch = wm8997_patch;
                break;
-#endif
-#ifdef CONFIG_MFD_WM8998
        case 0x6349:
-               switch (arizona->type) {
-               case WM8998:
-                       type_name = "WM8998";
-                       break;
-
-               case WM1814:
-                       type_name = "WM1814";
-                       break;
+               if (IS_ENABLED(CONFIG_MFD_WM8998)) {
+                       switch (arizona->type) {
+                       case WM8998:
+                               type_name = "WM8998";
+                               break;
+
+                       case WM1814:
+                               type_name = "WM1814";
+                               break;
+
+                       default:
+                               type_name = "WM8998";
+                               dev_warn(arizona->dev,
+                                        "WM8998 registered as %d\n",
+                                        arizona->type);
+                               arizona->type = WM8998;
+                       }
 
-               default:
-                       type_name = "WM8998";
-                       dev_err(arizona->dev, "WM8998 registered as %d\n",
-                               arizona->type);
-                       arizona->type = WM8998;
+                       apply_patch = wm8998_patch;
+                       subdevs = wm8998_devs;
+                       n_subdevs = ARRAY_SIZE(wm8998_devs);
                }
-
-               apply_patch = wm8998_patch;
                break;
-#endif
        default:
                dev_err(arizona->dev, "Unknown device ID %x\n", reg);
                goto err_reset;
        }
 
+       if (!subdevs) {
+               dev_err(arizona->dev,
+                       "No kernel support for device ID %x\n", reg);
+               goto err_reset;
+       }
+
        dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A');
 
        if (apply_patch) {
@@ -1342,28 +1402,10 @@ int arizona_dev_init(struct arizona *arizona)
        arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked",
                            arizona_underclocked, arizona);
 
-       switch (arizona->type) {
-       case WM5102:
-               ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
-                                     ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
-               break;
-       case WM5110:
-       case WM8280:
-               ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
-                                     ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
-               break;
-       case WM8997:
-               ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
-                                     ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
-               break;
-       case WM8998:
-       case WM1814:
-               ret = mfd_add_devices(arizona->dev, -1, wm8998_devs,
-                                     ARRAY_SIZE(wm8998_devs), NULL, 0, NULL);
-               break;
-       }
+       ret = mfd_add_devices(arizona->dev, PLATFORM_DEVID_NONE,
+                             subdevs, n_subdevs, NULL, 0, NULL);
 
-       if (ret != 0) {
+       if (ret) {
                dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret);
                goto err_irq;
        }
index cea1b409fa27babe335e74dd6414e3bada8147ee..4e3afd1861fc4b16e998089c87db95e8085d13a8 100644 (file)
@@ -27,7 +27,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
        struct arizona *arizona;
-       const struct regmap_config *regmap_config;
+       const struct regmap_config *regmap_config = NULL;
        unsigned long type;
        int ret;
 
@@ -37,31 +37,32 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
                type = id->driver_data;
 
        switch (type) {
-#ifdef CONFIG_MFD_WM5102
        case WM5102:
-               regmap_config = &wm5102_i2c_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM5102))
+                       regmap_config = &wm5102_i2c_regmap;
                break;
-#endif
-#ifdef CONFIG_MFD_WM5110
        case WM5110:
        case WM8280:
-               regmap_config = &wm5110_i2c_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM5110))
+                       regmap_config = &wm5110_i2c_regmap;
                break;
-#endif
-#ifdef CONFIG_MFD_WM8997
        case WM8997:
-               regmap_config = &wm8997_i2c_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM8997))
+                       regmap_config = &wm8997_i2c_regmap;
                break;
-#endif
-#ifdef CONFIG_MFD_WM8998
        case WM8998:
        case WM1814:
-               regmap_config = &wm8998_i2c_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM8998))
+                       regmap_config = &wm8998_i2c_regmap;
                break;
-#endif
        default:
-               dev_err(&i2c->dev, "Unknown device type %ld\n",
-                       id->driver_data);
+               dev_err(&i2c->dev, "Unknown device type %ld\n", type);
+               return -EINVAL;
+       }
+
+       if (!regmap_config) {
+               dev_err(&i2c->dev,
+                       "No kernel support for device type %ld\n", type);
                return -EINVAL;
        }
 
@@ -77,7 +78,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       arizona->type = id->driver_data;
+       arizona->type = type;
        arizona->dev = &i2c->dev;
        arizona->irq = i2c->irq;
 
index 2cac4f463f1e679fca4cbd95ec03b5e461b590d2..3d425e93ce845602ee72bc425ef4543584952e31 100644 (file)
@@ -169,7 +169,7 @@ static struct irq_chip arizona_irq_chip = {
 static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
                              irq_hw_number_t hw)
 {
-       struct regmap_irq_chip_data *data = h->host_data;
+       struct arizona *data = h->host_data;
 
        irq_set_chip_data(virq, data);
        irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
index 03d62f7b47205cbd5c8db2bce120a8c5d124b84d..befbc89bfd3456c210d736d2ad295c646a2bd4fc 100644 (file)
@@ -27,7 +27,7 @@ static int arizona_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
        struct arizona *arizona;
-       const struct regmap_config *regmap_config;
+       const struct regmap_config *regmap_config = NULL;
        unsigned long type;
        int ret;
 
@@ -37,20 +37,23 @@ static int arizona_spi_probe(struct spi_device *spi)
                type = id->driver_data;
 
        switch (type) {
-#ifdef CONFIG_MFD_WM5102
        case WM5102:
-               regmap_config = &wm5102_spi_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM5102))
+                       regmap_config = &wm5102_spi_regmap;
                break;
-#endif
-#ifdef CONFIG_MFD_WM5110
        case WM5110:
        case WM8280:
-               regmap_config = &wm5110_spi_regmap;
+               if (IS_ENABLED(CONFIG_MFD_WM5110))
+                       regmap_config = &wm5110_spi_regmap;
                break;
-#endif
        default:
-               dev_err(&spi->dev, "Unknown device type %ld\n",
-                       id->driver_data);
+               dev_err(&spi->dev, "Unknown device type %ld\n", type);
+               return -EINVAL;
+       }
+
+       if (!regmap_config) {
+               dev_err(&spi->dev,
+                       "No kernel support for device type %ld\n", type);
                return -EINVAL;
        }
 
@@ -66,7 +69,7 @@ static int arizona_spi_probe(struct spi_device *spi)
                return ret;
        }
 
-       arizona->type = id->driver_data;
+       arizona->type = type;
        arizona->dev = &spi->dev;
        arizona->irq = spi->irq;
 
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
new file mode 100644 (file)
index 0000000..e8e67be
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Driver for Atmel Flexcom
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Cyrille Pitchen <cyrille.pitchen@atmel.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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+
+/* I/O register offsets */
+#define FLEX_MR                0x0     /* Mode Register */
+#define FLEX_VERSION   0xfc    /* Version Register */
+
+/* Mode Register bit fields */
+#define FLEX_MR_OPMODE_OFFSET  (0)  /* Operating Mode */
+#define FLEX_MR_OPMODE_MASK    (0x3 << FLEX_MR_OPMODE_OFFSET)
+#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) &  \
+                                FLEX_MR_OPMODE_MASK)
+
+
+static int atmel_flexcom_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct clk *clk;
+       struct resource *res;
+       void __iomem *base;
+       u32 opmode;
+       int err;
+
+       err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode);
+       if (err)
+               return err;
+
+       if (opmode < ATMEL_FLEXCOM_MODE_USART ||
+           opmode > ATMEL_FLEXCOM_MODE_TWI)
+               return -EINVAL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       err = clk_prepare_enable(clk);
+       if (err)
+               return err;
+
+       /*
+        * Set the Operating Mode in the Mode Register: only the selected device
+        * is clocked. Hence, registers of the other serial devices remain
+        * inaccessible and are read as zero. Also the external I/O lines of the
+        * Flexcom are muxed to reach the selected device.
+        */
+       writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR);
+
+       clk_disable_unprepare(clk);
+
+       return of_platform_populate(np, NULL, NULL, &pdev->dev);
+}
+
+static const struct of_device_id atmel_flexcom_of_match[] = {
+       { .compatible = "atmel,sama5d2-flexcom" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
+
+static struct platform_driver atmel_flexcom_driver = {
+       .probe  = atmel_flexcom_probe,
+       .driver = {
+               .name           = "atmel_flexcom",
+               .of_match_table = atmel_flexcom_of_match,
+       },
+};
+
+module_platform_driver(atmel_flexcom_driver);
+
+MODULE_AUTHOR("Cyrille Pitchen <cyrille.pitchen@atmel.com>");
+MODULE_DESCRIPTION("Atmel Flexcom MFD driver");
+MODULE_LICENSE("GPL v2");
index 3fff6b5d0426830833f98f708837f33c299100ef..06c205868573e8d7d7b98e1c142156a2cc572454 100644 (file)
@@ -148,6 +148,7 @@ static const struct of_device_id atmel_hlcdc_match[] = {
        { .compatible = "atmel,sama5d4-hlcdc" },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
 
 static struct platform_driver atmel_hlcdc_driver = {
        .probe = atmel_hlcdc_probe,
index 3f576b76c3223ed024a65224dac95da0a2a02eab..9842199e2e6c1101eea2c05ce12bdbfb5d7db570 100644 (file)
@@ -161,6 +161,21 @@ static struct resource axp22x_pek_resources[] = {
        },
 };
 
+static struct resource axp288_power_button_resources[] = {
+       {
+               .name   = "PEK_DBR",
+               .start  = AXP288_IRQ_POKN,
+               .end    = AXP288_IRQ_POKN,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "PEK_DBF",
+               .start  = AXP288_IRQ_POKP,
+               .end    = AXP288_IRQ_POKP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct resource axp288_fuel_gauge_resources[] = {
        {
                .start = AXP288_IRQ_QWBTU,
@@ -571,6 +586,11 @@ static struct mfd_cell axp288_cells[] = {
                .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
                .resources = axp288_fuel_gauge_resources,
        },
+       {
+               .name = "axp20x-pek",
+               .num_resources = ARRAY_SIZE(axp288_power_button_resources),
+               .resources = axp288_power_button_resources,
+       },
        {
                .name = "axp288_pmic_acpi",
        },
index da2af5b4f855150f34c106dade426e2b1e785fce..320aaefee7187f10da1d1735d15c7375daba38d3 100644 (file)
@@ -128,4 +128,3 @@ 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("i2c:bcm590xx");
index d06e4b46db80804b91e2e94640ac32049878cbbf..56a466469664cd65917e4e14e6fa222494bd59e7 100644 (file)
@@ -344,6 +344,12 @@ static int cros_ec_i2c_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
                          cros_ec_i2c_resume);
 
+static const struct of_device_id cros_ec_i2c_of_match[] = {
+       { .compatible = "google,cros-ec-i2c", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+
 static const struct i2c_device_id cros_ec_i2c_id[] = {
        { "cros-ec-i2c", 0 },
        { }
@@ -353,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
 static struct i2c_driver cros_ec_driver = {
        .driver = {
                .name   = "cros-ec-i2c",
+               .of_match_table = of_match_ptr(cros_ec_i2c_of_match),
                .pm     = &cros_ec_i2c_pm_ops,
        },
        .probe          = cros_ec_i2c_probe,
index ef7fe2ae2fa4c89c0b86642b678233a68614f96a..37e4426ef0610d9dab69093bc809a2bf5d1f090b 100644 (file)
@@ -532,11 +532,7 @@ static int da903x_probe(struct i2c_client *client,
                return ret;
        }
 
-       ret = da903x_add_subdevs(chip, pdata);
-       if (ret)
-               return ret;
-
-       return 0;
+       return da903x_add_subdevs(chip, pdata);
 }
 
 static int da903x_remove(struct i2c_client *client)
index 46e3840c7a37392402deb53a7a9eb2cb7b8b27b6..c0bf68a3e614fcbb43eda3c8a8d295f149007274 100644 (file)
@@ -51,6 +51,9 @@ static bool da9052_reg_readable(struct device *dev, unsigned int reg)
        case DA9052_GPIO_2_3_REG:
        case DA9052_GPIO_4_5_REG:
        case DA9052_GPIO_6_7_REG:
+       case DA9052_GPIO_8_9_REG:
+       case DA9052_GPIO_10_11_REG:
+       case DA9052_GPIO_12_13_REG:
        case DA9052_GPIO_14_15_REG:
        case DA9052_ID_0_1_REG:
        case DA9052_ID_2_3_REG:
@@ -178,6 +181,9 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg)
        case DA9052_GPIO_2_3_REG:
        case DA9052_GPIO_4_5_REG:
        case DA9052_GPIO_6_7_REG:
+       case DA9052_GPIO_8_9_REG:
+       case DA9052_GPIO_10_11_REG:
+       case DA9052_GPIO_12_13_REG:
        case DA9052_GPIO_14_15_REG:
        case DA9052_ID_0_1_REG:
        case DA9052_ID_2_3_REG:
index 02887001e800b0a08bb70a30346585e1914f6e4a..2697ffb08009b48c3803dbfc9263b309f13ff444 100644 (file)
@@ -174,11 +174,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
                return ret;
        }
 
-       ret = da9052_device_init(da9052, id->driver_data);
-       if (ret != 0)
-               return ret;
-
-       return 0;
+       return da9052_device_init(da9052, id->driver_data);
 }
 
 static int da9052_i2c_remove(struct i2c_client *client)
index 71b89dd4e8de26297b5487cd2c42c1e19dcbcba3..b9ea1b27db642d452b39ceaf1a5a96fa9657804c 100644 (file)
@@ -56,11 +56,7 @@ static int da9052_spi_probe(struct spi_device *spi)
                return ret;
        }
 
-       ret = da9052_device_init(da9052, id->driver_data);
-       if (ret != 0)
-               return ret;
-
-       return 0;
+       return da9052_device_init(da9052, id->driver_data);
 }
 
 static int da9052_spi_remove(struct spi_device *spi)
index f80d9471f2e7fd1b851d871df080a991e85bc1e6..a9ad024ec6b06a3401138d9600263a355235186e 100644 (file)
@@ -198,7 +198,7 @@ static int da9062_clear_fault_log(struct da9062 *chip)
        return ret;
 }
 
-int get_device_type(struct da9062 *chip)
+static int da9062_get_device_type(struct da9062 *chip)
 {
        int device_id, variant_id, variant_mrc;
        int ret;
@@ -466,7 +466,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                dev_warn(chip->dev, "Cannot clear fault log\n");
 
-       ret = get_device_type(chip);
+       ret = da9062_get_device_type(chip);
        if (ret)
                return ret;
 
index 94b9bbd1a69bab72e37ed5fef1f8a9e9166e105a..195fdcfa1a0d3923aadb7551b85e894f2dcfb3dc 100644 (file)
 #include <linux/mfd/da9150/core.h>
 #include <linux/mfd/da9150/registers.h>
 
+/* Raw device access, used for QIF */
+static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
+                                 u8 *buf)
+{
+       struct i2c_msg xfer;
+       int ret;
+
+       /*
+        * Read is split into two transfers as device expects STOP/START rather
+        * than repeated start to carry out this kind of access.
+        */
+
+       /* Write address */
+       xfer.addr = client->addr;
+       xfer.flags = 0;
+       xfer.len = 1;
+       xfer.buf = &addr;
+
+       ret = i2c_transfer(client->adapter, &xfer, 1);
+       if (ret != 1) {
+               if (ret < 0)
+                       return ret;
+               else
+                       return -EIO;
+       }
+
+       /* Read data */
+       xfer.addr = client->addr;
+       xfer.flags = I2C_M_RD;
+       xfer.len = count;
+       xfer.buf = buf;
+
+       ret = i2c_transfer(client->adapter, &xfer, 1);
+       if (ret == 1)
+               return 0;
+       else if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+
+static int da9150_i2c_write_device(struct i2c_client *client, u8 addr,
+                                  int count, const u8 *buf)
+{
+       struct i2c_msg xfer;
+       u8 *reg_data;
+       int ret;
+
+       reg_data = kzalloc(1 + count, GFP_KERNEL);
+       if (!reg_data)
+               return -ENOMEM;
+
+       reg_data[0] = addr;
+       memcpy(&reg_data[1], buf, count);
+
+       /* Write address & data */
+       xfer.addr = client->addr;
+       xfer.flags = 0;
+       xfer.len = 1 + count;
+       xfer.buf = reg_data;
+
+       ret = i2c_transfer(client->adapter, &xfer, 1);
+       kfree(reg_data);
+       if (ret == 1)
+               return 0;
+       else if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+
 static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = {
        .volatile_reg = da9150_volatile_reg,
 };
 
+void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
+{
+       int ret;
+
+       ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf);
+       if (ret < 0)
+               dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
+                       addr, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_read_qif);
+
+void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
+{
+       int ret;
+
+       ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf);
+       if (ret < 0)
+               dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
+                       addr, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_write_qif);
+
 u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
 {
        int val, ret;
@@ -262,54 +355,45 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = {
 };
 
 static struct resource da9150_gpadc_resources[] = {
-       {
-               .name = "GPADC",
-               .start = DA9150_IRQ_GPADC,
-               .end = DA9150_IRQ_GPADC,
-               .flags = IORESOURCE_IRQ,
-       },
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"),
 };
 
 static struct resource da9150_charger_resources[] = {
-       {
-               .name = "CHG_STATUS",
-               .start = DA9150_IRQ_CHG,
-               .end = DA9150_IRQ_CHG,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "CHG_TJUNC",
-               .start = DA9150_IRQ_TJUNC,
-               .end = DA9150_IRQ_TJUNC,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "CHG_VFAULT",
-               .start = DA9150_IRQ_VFAULT,
-               .end = DA9150_IRQ_VFAULT,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "CHG_VBUS",
-               .start = DA9150_IRQ_VBUS,
-               .end = DA9150_IRQ_VBUS,
-               .flags = IORESOURCE_IRQ,
-       },
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"),
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"),
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"),
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"),
+};
+
+static struct resource da9150_fg_resources[] = {
+       DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"),
+};
+
+enum da9150_dev_idx {
+       DA9150_GPADC_IDX = 0,
+       DA9150_CHARGER_IDX,
+       DA9150_FG_IDX,
 };
 
 static struct mfd_cell da9150_devs[] = {
-       {
+       [DA9150_GPADC_IDX] = {
                .name = "da9150-gpadc",
                .of_compatible = "dlg,da9150-gpadc",
                .resources = da9150_gpadc_resources,
                .num_resources = ARRAY_SIZE(da9150_gpadc_resources),
        },
-       {
+       [DA9150_CHARGER_IDX] = {
                .name = "da9150-charger",
                .of_compatible = "dlg,da9150-charger",
                .resources = da9150_charger_resources,
                .num_resources = ARRAY_SIZE(da9150_charger_resources),
        },
+       [DA9150_FG_IDX] = {
+               .name = "da9150-fuel-gauge",
+               .of_compatible = "dlg,da9150-fuel-gauge",
+               .resources = da9150_fg_resources,
+               .num_resources = ARRAY_SIZE(da9150_fg_resources),
+       },
 };
 
 static int da9150_probe(struct i2c_client *client,
@@ -317,6 +401,7 @@ static int da9150_probe(struct i2c_client *client,
 {
        struct da9150 *da9150;
        struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
+       int qif_addr;
        int ret;
 
        da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
@@ -335,16 +420,41 @@ static int da9150_probe(struct i2c_client *client,
                return ret;
        }
 
-       da9150->irq_base = pdata ? pdata->irq_base : -1;
+       /* Setup secondary I2C interface for QIF access */
+       qif_addr = da9150_reg_read(da9150, DA9150_CORE2WIRE_CTRL_A);
+       qif_addr = (qif_addr & DA9150_CORE_BASE_ADDR_MASK) >> 1;
+       qif_addr |= DA9150_QIF_I2C_ADDR_LSB;
+       da9150->core_qif = i2c_new_dummy(client->adapter, qif_addr);
+       if (!da9150->core_qif) {
+               dev_err(da9150->dev, "Failed to attach QIF client\n");
+               return -ENODEV;
+       }
+
+       i2c_set_clientdata(da9150->core_qif, da9150);
+
+       if (pdata) {
+               da9150->irq_base = pdata->irq_base;
+
+               da9150_devs[DA9150_FG_IDX].platform_data = pdata->fg_pdata;
+               da9150_devs[DA9150_FG_IDX].pdata_size =
+                       sizeof(struct da9150_fg_pdata);
+       } else {
+               da9150->irq_base = -1;
+       }
 
        ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
                                  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                  da9150->irq_base, &da9150_regmap_irq_chip,
                                  &da9150->regmap_irq_data);
-       if (ret)
-               return ret;
+       if (ret) {
+               dev_err(da9150->dev, "Failed to add regmap irq chip: %d\n",
+                       ret);
+               goto regmap_irq_fail;
+       }
+
 
        da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
+
        enable_irq_wake(da9150->irq);
 
        ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
@@ -352,11 +462,17 @@ static int da9150_probe(struct i2c_client *client,
                              da9150->irq_base, NULL);
        if (ret) {
                dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
-               regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
-               return ret;
+               goto mfd_fail;
        }
 
        return 0;
+
+mfd_fail:
+       regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+regmap_irq_fail:
+       i2c_unregister_device(da9150->core_qif);
+
+       return ret;
 }
 
 static int da9150_remove(struct i2c_client *client)
@@ -365,6 +481,7 @@ static int da9150_remove(struct i2c_client *client)
 
        regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
        mfd_remove_devices(da9150->dev);
+       i2c_unregister_device(da9150->core_qif);
 
        return 0;
 }
index 95b2ff8f223ab34bc06f45c585d1a5a55e02c810..f9ded45a992de31a1fa5c33a6da6be3cf376fa1f 100644 (file)
@@ -97,6 +97,7 @@ static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
        { .compatible = "hisilicon,hi6421-pmic", },
        { },
 };
+MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match_tbl);
 
 static struct platform_driver hi6421_pmic_driver = {
        .driver = {
index 1bd5b042c8b33b363845eb49ce5e0e161b402601..0c6ff727b2ec97895a83cfaf19d0fd98dfa170af 100644 (file)
@@ -318,7 +318,6 @@ static int htcpld_setup_chip_irq(
        struct htcpld_data *htcpld;
        struct htcpld_chip *chip;
        unsigned int irq, irq_end;
-       int ret = 0;
 
        /* Get the platform and driver data */
        htcpld = platform_get_drvdata(pdev);
@@ -333,7 +332,7 @@ static int htcpld_setup_chip_irq(
                irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
        }
 
-       return ret;
+       return 0;
 }
 
 static int htcpld_register_chip_i2c(
index 0d92d73bfa0ea80d84850f94b5225ddbae163c38..b6fd9041f82fcffec38325c140092de88adc3e57 100644 (file)
@@ -25,10 +25,26 @@ static const struct intel_lpss_platform_info spt_info = {
        .clk_rate = 120000000,
 };
 
+static const struct intel_lpss_platform_info bxt_info = {
+       .clk_rate = 100000000,
+};
+
+static const struct intel_lpss_platform_info bxt_i2c_info = {
+       .clk_rate = 133000000,
+};
+
 static const struct acpi_device_id intel_lpss_acpi_ids[] = {
        /* SPT */
        { "INT3446", (kernel_ulong_t)&spt_info },
        { "INT3447", (kernel_ulong_t)&spt_info },
+       /* BXT */
+       { "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
+       { "80860ABC", (kernel_ulong_t)&bxt_info },
+       { "80860AC2", (kernel_ulong_t)&bxt_info },
+       /* APL */
+       { "80865AAC", (kernel_ulong_t)&bxt_i2c_info },
+       { "80865ABC", (kernel_ulong_t)&bxt_info },
+       { "80865AC2", (kernel_ulong_t)&bxt_info },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids);
index 9236dffeb4d6bc3b73050df89fafa7d786bbca66..5bfdfccbb9a1acdea902c05a59394f01950ee5e3 100644 (file)
@@ -70,7 +70,52 @@ static const struct intel_lpss_platform_info spt_uart_info = {
        .clk_con_id = "baudclk",
 };
 
+static const struct intel_lpss_platform_info bxt_info = {
+       .clk_rate = 100000000,
+};
+
+static const struct intel_lpss_platform_info bxt_uart_info = {
+       .clk_rate = 100000000,
+       .clk_con_id = "baudclk",
+};
+
+static const struct intel_lpss_platform_info bxt_i2c_info = {
+       .clk_rate = 133000000,
+};
+
 static const struct pci_device_id intel_lpss_pci_ids[] = {
+       /* BXT */
+       { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0ab2), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0ab4), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0ab6), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0ab8), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0aba), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x0abc), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x0abe), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x0ac0), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x0ac2), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info },
+       /* APL */
+       { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x5ac2), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info },
+       { PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info },
        /* SPT-LP */
        { PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info },
        { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
index fdf4d5c1add24c74ce9fccbbd49fdf7910c3aa64..001a7d7708cee1ad84a53839c8c687582331e649 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 #include "intel-lpss.h"
 
 #define LPSS_DEV_OFFSET                0x000
@@ -52,8 +54,7 @@
 #define LPSS_PRIV_SSP_REG              0x20
 #define LPSS_PRIV_SSP_REG_DIS_DMA_FIN  BIT(0)
 
-#define LPSS_PRIV_REMAP_ADDR_LO                0x40
-#define LPSS_PRIV_REMAP_ADDR_HI                0x44
+#define LPSS_PRIV_REMAP_ADDR           0x40
 
 #define LPSS_PRIV_CAPS                 0xfc
 #define LPSS_PRIV_CAPS_NO_IDMA         BIT(8)
@@ -250,12 +251,7 @@ static void intel_lpss_set_remap_addr(const struct intel_lpss *lpss)
 {
        resource_size_t addr = lpss->info->mem->start;
 
-       writel(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR_LO);
-#if BITS_PER_LONG > 32
-       writel(addr >> 32, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
-#else
-       writel(0, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI);
-#endif
+       lo_hi_writeq(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR);
 }
 
 static void intel_lpss_deassert_reset(const struct intel_lpss *lpss)
index 1ce16037d043a1be95767f52f838a9ff751789a0..04213746530035af262a77bb7dd03e595e29c8c2 100644 (file)
 #define MFD_I2C_BAR            0
 #define MFD_GPIO_BAR           1
 
+/* ACPI _ADR value to match the child node */
+#define MFD_ACPI_MATCH_GPIO    0ULL
+#define MFD_ACPI_MATCH_I2C     1ULL
+
 /* The base GPIO number under GPIOLIB framework */
 #define INTEL_QUARK_MFD_GPIO_BASE      8
 
@@ -82,27 +86,37 @@ static struct resource intel_quark_i2c_res[] = {
        },
 };
 
+static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = {
+       .adr = MFD_ACPI_MATCH_I2C,
+};
+
 static struct resource intel_quark_gpio_res[] = {
        [INTEL_QUARK_IORES_MEM] = {
                .flags = IORESOURCE_MEM,
        },
 };
 
+static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
+       .adr = MFD_ACPI_MATCH_GPIO,
+};
+
 static struct mfd_cell intel_quark_mfd_cells[] = {
-       {
-               .id = MFD_I2C_BAR,
-               .name = "i2c_designware",
-               .num_resources = ARRAY_SIZE(intel_quark_i2c_res),
-               .resources = intel_quark_i2c_res,
-               .ignore_resource_conflicts = true,
-       },
        {
                .id = MFD_GPIO_BAR,
                .name = "gpio-dwapb",
+               .acpi_match = &intel_quark_acpi_match_gpio,
                .num_resources = ARRAY_SIZE(intel_quark_gpio_res),
                .resources = intel_quark_gpio_res,
                .ignore_resource_conflicts = true,
        },
+       {
+               .id = MFD_I2C_BAR,
+               .name = "i2c_designware",
+               .acpi_match = &intel_quark_acpi_match_i2c,
+               .num_resources = ARRAY_SIZE(intel_quark_i2c_res),
+               .resources = intel_quark_i2c_res,
+               .ignore_resource_conflicts = true,
+       },
 };
 
 static const struct pci_device_id intel_quark_mfd_ids[] = {
@@ -248,12 +262,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
 
        dev_set_drvdata(&pdev->dev, quark_mfd);
 
-       ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]);
+       ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
        if (ret)
                return ret;
 
-       ret = intel_quark_gpio_setup(pdev,
-                                    &intel_quark_mfd_cells[MFD_GPIO_BAR]);
+       ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
        if (ret)
                return ret;
 
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c
new file mode 100644 (file)
index 0000000..b942876
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * MFD core driver for Intel Broxton Whiskey Cove PMIC
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_bxtwc.h>
+#include <asm/intel_pmc_ipc.h>
+
+/* PMIC device registers */
+#define REG_ADDR_MASK          0xFF00
+#define REG_ADDR_SHIFT         8
+#define REG_OFFSET_MASK                0xFF
+
+/* Interrupt Status Registers */
+#define BXTWC_IRQLVL1          0x4E02
+#define BXTWC_PWRBTNIRQ                0x4E03
+
+#define BXTWC_THRM0IRQ         0x4E04
+#define BXTWC_THRM1IRQ         0x4E05
+#define BXTWC_THRM2IRQ         0x4E06
+#define BXTWC_BCUIRQ           0x4E07
+#define BXTWC_ADCIRQ           0x4E08
+#define BXTWC_CHGR0IRQ         0x4E09
+#define BXTWC_CHGR1IRQ         0x4E0A
+#define BXTWC_GPIOIRQ0         0x4E0B
+#define BXTWC_GPIOIRQ1         0x4E0C
+#define BXTWC_CRITIRQ          0x4E0D
+
+/* Interrupt MASK Registers */
+#define BXTWC_MIRQLVL1         0x4E0E
+#define BXTWC_MPWRTNIRQ                0x4E0F
+
+#define BXTWC_MTHRM0IRQ                0x4E12
+#define BXTWC_MTHRM1IRQ                0x4E13
+#define BXTWC_MTHRM2IRQ                0x4E14
+#define BXTWC_MBCUIRQ          0x4E15
+#define BXTWC_MADCIRQ          0x4E16
+#define BXTWC_MCHGR0IRQ                0x4E17
+#define BXTWC_MCHGR1IRQ                0x4E18
+#define BXTWC_MGPIO0IRQ                0x4E19
+#define BXTWC_MGPIO1IRQ                0x4E1A
+#define BXTWC_MCRITIRQ         0x4E1B
+
+/* Whiskey Cove PMIC share same ACPI ID between different platforms */
+#define BROXTON_PMIC_WC_HRV    4
+
+/* Manage in two IRQ chips since mask registers are not consecutive */
+enum bxtwc_irqs {
+       /* Level 1 */
+       BXTWC_PWRBTN_LVL1_IRQ = 0,
+       BXTWC_TMU_LVL1_IRQ,
+       BXTWC_THRM_LVL1_IRQ,
+       BXTWC_BCU_LVL1_IRQ,
+       BXTWC_ADC_LVL1_IRQ,
+       BXTWC_CHGR_LVL1_IRQ,
+       BXTWC_GPIO_LVL1_IRQ,
+       BXTWC_CRIT_LVL1_IRQ,
+
+       /* Level 2 */
+       BXTWC_PWRBTN_IRQ,
+};
+
+enum bxtwc_irqs_level2 {
+       /* Level 2 */
+       BXTWC_THRM0_IRQ = 0,
+       BXTWC_THRM1_IRQ,
+       BXTWC_THRM2_IRQ,
+       BXTWC_BCU_IRQ,
+       BXTWC_ADC_IRQ,
+       BXTWC_CHGR0_IRQ,
+       BXTWC_CHGR1_IRQ,
+       BXTWC_GPIO0_IRQ,
+       BXTWC_GPIO1_IRQ,
+       BXTWC_CRIT_IRQ,
+};
+
+static const struct regmap_irq bxtwc_regmap_irqs[] = {
+       REGMAP_IRQ_REG(BXTWC_PWRBTN_LVL1_IRQ, 0, BIT(0)),
+       REGMAP_IRQ_REG(BXTWC_TMU_LVL1_IRQ, 0, BIT(1)),
+       REGMAP_IRQ_REG(BXTWC_THRM_LVL1_IRQ, 0, BIT(2)),
+       REGMAP_IRQ_REG(BXTWC_BCU_LVL1_IRQ, 0, BIT(3)),
+       REGMAP_IRQ_REG(BXTWC_ADC_LVL1_IRQ, 0, BIT(4)),
+       REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)),
+       REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)),
+       REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)),
+       REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03),
+};
+
+static const struct regmap_irq bxtwc_regmap_irqs_level2[] = {
+       REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff),
+       REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf),
+       REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
+       REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
+       REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
+       REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
+       REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
+       REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
+       REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
+       REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
+};
+
+static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
+       .name = "bxtwc_irq_chip",
+       .status_base = BXTWC_IRQLVL1,
+       .mask_base = BXTWC_MIRQLVL1,
+       .irqs = bxtwc_regmap_irqs,
+       .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs),
+       .num_regs = 2,
+};
+
+static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = {
+       .name = "bxtwc_irq_chip_level2",
+       .status_base = BXTWC_THRM0IRQ,
+       .mask_base = BXTWC_MTHRM0IRQ,
+       .irqs = bxtwc_regmap_irqs_level2,
+       .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2),
+       .num_regs = 10,
+};
+
+static struct resource gpio_resources[] = {
+       DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"),
+       DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"),
+};
+
+static struct resource adc_resources[] = {
+       DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"),
+};
+
+static struct resource charger_resources[] = {
+       DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"),
+       DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"),
+};
+
+static struct resource thermal_resources[] = {
+       DEFINE_RES_IRQ(BXTWC_THRM0_IRQ),
+       DEFINE_RES_IRQ(BXTWC_THRM1_IRQ),
+       DEFINE_RES_IRQ(BXTWC_THRM2_IRQ),
+};
+
+static struct resource bcu_resources[] = {
+       DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"),
+};
+
+static struct mfd_cell bxt_wc_dev[] = {
+       {
+               .name = "bxt_wcove_gpadc",
+               .num_resources = ARRAY_SIZE(adc_resources),
+               .resources = adc_resources,
+       },
+       {
+               .name = "bxt_wcove_thermal",
+               .num_resources = ARRAY_SIZE(thermal_resources),
+               .resources = thermal_resources,
+       },
+       {
+               .name = "bxt_wcove_ext_charger",
+               .num_resources = ARRAY_SIZE(charger_resources),
+               .resources = charger_resources,
+       },
+       {
+               .name = "bxt_wcove_bcu",
+               .num_resources = ARRAY_SIZE(bcu_resources),
+               .resources = bcu_resources,
+       },
+       {
+               .name = "bxt_wcove_gpio",
+               .num_resources = ARRAY_SIZE(gpio_resources),
+               .resources = gpio_resources,
+       },
+       {
+               .name = "bxt_wcove_region",
+       },
+};
+
+static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
+                                   unsigned int *val)
+{
+       int ret;
+       int i2c_addr;
+       u8 ipc_in[2];
+       u8 ipc_out[4];
+       struct intel_soc_pmic *pmic = context;
+
+       if (reg & REG_ADDR_MASK)
+               i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+       else {
+               i2c_addr = BXTWC_DEVICE1_ADDR;
+               if (!i2c_addr) {
+                       dev_err(pmic->dev, "I2C address not set\n");
+                       return -EINVAL;
+               }
+       }
+       reg &= REG_OFFSET_MASK;
+
+       ipc_in[0] = reg;
+       ipc_in[1] = i2c_addr;
+       ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
+                       PMC_IPC_PMIC_ACCESS_READ,
+                       ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);
+       if (ret) {
+               dev_err(pmic->dev, "Failed to read from PMIC\n");
+               return ret;
+       }
+       *val = ipc_out[0];
+
+       return 0;
+}
+
+static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
+                                      unsigned int val)
+{
+       int ret;
+       int i2c_addr;
+       u8 ipc_in[3];
+       struct intel_soc_pmic *pmic = context;
+
+       if (reg & REG_ADDR_MASK)
+               i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+       else {
+               i2c_addr = BXTWC_DEVICE1_ADDR;
+               if (!i2c_addr) {
+                       dev_err(pmic->dev, "I2C address not set\n");
+                       return -EINVAL;
+               }
+       }
+       reg &= REG_OFFSET_MASK;
+
+       ipc_in[0] = reg;
+       ipc_in[1] = i2c_addr;
+       ipc_in[2] = val;
+       ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
+                       PMC_IPC_PMIC_ACCESS_WRITE,
+                       ipc_in, sizeof(ipc_in), NULL, 0);
+       if (ret) {
+               dev_err(pmic->dev, "Failed to write to PMIC\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/* sysfs interfaces to r/w PMIC registers, required by initial script */
+static unsigned long bxtwc_reg_addr;
+static ssize_t bxtwc_reg_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "0x%lx\n", bxtwc_reg_addr);
+}
+
+static ssize_t bxtwc_reg_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       if (kstrtoul(buf, 0, &bxtwc_reg_addr)) {
+               dev_err(dev, "Invalid register address\n");
+               return -EINVAL;
+       }
+       return (ssize_t)count;
+}
+
+static ssize_t bxtwc_val_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned int val;
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       ret = regmap_read(pmic->regmap, bxtwc_reg_addr, &val);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read 0x%lx\n", bxtwc_reg_addr);
+               return -EIO;
+       }
+
+       return sprintf(buf, "0x%02x\n", val);
+}
+
+static ssize_t bxtwc_val_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       int ret;
+       unsigned int val;
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       ret = kstrtouint(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val);
+       if (ret) {
+               dev_err(dev, "Failed to write value 0x%02x to address 0x%lx",
+                       val, bxtwc_reg_addr);
+               return -EIO;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(addr, S_IWUSR | S_IRUSR, bxtwc_reg_show, bxtwc_reg_store);
+static DEVICE_ATTR(val, S_IWUSR | S_IRUSR, bxtwc_val_show, bxtwc_val_store);
+static struct attribute *bxtwc_attrs[] = {
+       &dev_attr_addr.attr,
+       &dev_attr_val.attr,
+       NULL
+};
+
+static const struct attribute_group bxtwc_group = {
+       .attrs = bxtwc_attrs,
+};
+
+static const struct regmap_config bxtwc_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+       .reg_write = regmap_ipc_byte_reg_write,
+       .reg_read = regmap_ipc_byte_reg_read,
+};
+
+static int bxtwc_probe(struct platform_device *pdev)
+{
+       int ret;
+       acpi_handle handle;
+       acpi_status status;
+       unsigned long long hrv;
+       struct intel_soc_pmic *pmic;
+
+       handle = ACPI_HANDLE(&pdev->dev);
+       status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
+               return -ENODEV;
+       }
+       if (hrv != BROXTON_PMIC_WC_HRV) {
+               dev_err(&pdev->dev, "Invalid PMIC hardware revision: %llu\n",
+                       hrv);
+               return -ENODEV;
+       }
+
+       pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+       if (!pmic)
+               return -ENOMEM;
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Invalid IRQ\n");
+               return ret;
+       }
+       pmic->irq = ret;
+
+       dev_set_drvdata(&pdev->dev, pmic);
+       pmic->dev = &pdev->dev;
+
+       pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,
+                                       &bxtwc_regmap_config);
+       if (IS_ERR(pmic->regmap)) {
+               ret = PTR_ERR(pmic->regmap);
+               dev_err(&pdev->dev, "Failed to initialise regmap: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+                                 IRQF_ONESHOT | IRQF_SHARED,
+                                 0, &bxtwc_regmap_irq_chip,
+                                 &pmic->irq_chip_data);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to add IRQ chip\n");
+               return ret;
+       }
+
+       ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+                                 IRQF_ONESHOT | IRQF_SHARED,
+                                 0, &bxtwc_regmap_irq_chip_level2,
+                                 &pmic->irq_chip_data_level2);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n");
+               goto err_irq_chip_level2;
+       }
+
+       ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
+                             ARRAY_SIZE(bxt_wc_dev), NULL, 0,
+                             NULL);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to add devices\n");
+               goto err_mfd;
+       }
+
+       ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret);
+               goto err_sysfs;
+       }
+
+       return 0;
+
+err_sysfs:
+       mfd_remove_devices(&pdev->dev);
+err_mfd:
+       regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
+err_irq_chip_level2:
+       regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+
+       return ret;
+}
+
+static int bxtwc_remove(struct platform_device *pdev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
+
+       sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group);
+       mfd_remove_devices(&pdev->dev);
+       regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+       regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
+
+       return 0;
+}
+
+static void bxtwc_shutdown(struct platform_device *pdev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev);
+
+       disable_irq(pmic->irq);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bxtwc_suspend(struct device *dev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       disable_irq(pmic->irq);
+
+       return 0;
+}
+
+static int bxtwc_resume(struct device *dev)
+{
+       struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+       enable_irq(pmic->irq);
+       return 0;
+}
+#endif
+static SIMPLE_DEV_PM_OPS(bxtwc_pm_ops, bxtwc_suspend, bxtwc_resume);
+
+static const struct acpi_device_id bxtwc_acpi_ids[] = {
+       { "INT34D3", },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids);
+
+static struct platform_driver bxtwc_driver = {
+       .probe = bxtwc_probe,
+       .remove = bxtwc_remove,
+       .shutdown = bxtwc_shutdown,
+       .driver = {
+               .name   = "BXTWC PMIC",
+               .pm     = &bxtwc_pm_ops,
+               .acpi_match_table = ACPI_PTR(bxtwc_acpi_ids),
+       },
+};
+
+module_platform_driver(bxtwc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Qipeng Zha<qipeng.zha@intel.com>");
index 463f4eae20c1da40a2f7e215d031b91d27c30720..05b924542ee2b1118635e90348a6a8a8e8a6d603 100644 (file)
@@ -448,7 +448,6 @@ static int kempld_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct kempld_device_data *pld;
        struct resource *ioport;
-       int ret;
 
        pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
        if (!pld)
@@ -471,11 +470,7 @@ static int kempld_probe(struct platform_device *pdev)
        mutex_init(&pld->lock);
        platform_set_drvdata(pdev, pld);
 
-       ret = kempld_detect_device(pld);
-       if (ret)
-               return ret;
-
-       return 0;
+       return kempld_detect_device(pld);
 }
 
 static int kempld_remove(struct platform_device *pdev)
@@ -756,7 +751,6 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
 static int __init kempld_init(void)
 {
        const struct dmi_system_id *id;
-       int ret;
 
        if (force_device_id[0]) {
                for (id = kempld_dmi_table;
@@ -771,11 +765,7 @@ static int __init kempld_init(void)
                        return -ENODEV;
        }
 
-       ret = platform_driver_register(&kempld_driver);
-       if (ret)
-               return ret;
-
-       return 0;
+       return platform_driver_register(&kempld_driver);
 }
 
 static void __exit kempld_exit(void)
index 643f3750e83079d11e7042c7e36e73ce20c26c19..5abcbb2e8849607f2e626109d3ddda0eb60dc9dd 100644 (file)
@@ -472,11 +472,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533,
        if (ret)
                return ret;
 
-       ret = lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
-       if (ret)
-               return ret;
-
-       return 0;
+       return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
 }
 
 static int lm3533_device_init(struct lm3533 *lm3533)
@@ -596,7 +592,6 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
                                        const struct i2c_device_id *id)
 {
        struct lm3533 *lm3533;
-       int ret;
 
        dev_dbg(&i2c->dev, "%s\n", __func__);
 
@@ -613,11 +608,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c,
        lm3533->dev = &i2c->dev;
        lm3533->irq = i2c->irq;
 
-       ret = lm3533_device_init(lm3533);
-       if (ret)
-               return ret;
-
-       return 0;
+       return lm3533_device_init(lm3533);
 }
 
 static int lm3533_i2c_remove(struct i2c_client *i2c)
index c5a9a08b5dfbf91ce609b22bb4fbcf331871237f..b514f3cf140d1fdd8836b06df7eaeaf7ba7268c2 100644 (file)
@@ -132,24 +132,18 @@ static struct resource gpio_ich_res[] = {
        },
 };
 
-enum lpc_cells {
-       LPC_WDT = 0,
-       LPC_GPIO,
+static struct mfd_cell lpc_ich_wdt_cell = {
+       .name = "iTCO_wdt",
+       .num_resources = ARRAY_SIZE(wdt_ich_res),
+       .resources = wdt_ich_res,
+       .ignore_resource_conflicts = true,
 };
 
-static struct mfd_cell lpc_ich_cells[] = {
-       [LPC_WDT] = {
-               .name = "iTCO_wdt",
-               .num_resources = ARRAY_SIZE(wdt_ich_res),
-               .resources = wdt_ich_res,
-               .ignore_resource_conflicts = true,
-       },
-       [LPC_GPIO] = {
-               .name = "gpio_ich",
-               .num_resources = ARRAY_SIZE(gpio_ich_res),
-               .resources = gpio_ich_res,
-               .ignore_resource_conflicts = true,
-       },
+static struct mfd_cell lpc_ich_gpio_cell = {
+       .name = "gpio_ich",
+       .num_resources = ARRAY_SIZE(gpio_ich_res),
+       .resources = gpio_ich_res,
+       .ignore_resource_conflicts = true,
 };
 
 /* chipset related info */
@@ -841,7 +835,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
        struct itco_wdt_platform_data *pdata;
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
        struct lpc_ich_info *info;
-       struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT];
+       struct mfd_cell *cell = &lpc_ich_wdt_cell;
 
        pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -860,7 +854,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev)
 static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev)
 {
        struct lpc_ich_priv *priv = pci_get_drvdata(dev);
-       struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO];
+       struct mfd_cell *cell = &lpc_ich_gpio_cell;
 
        cell->platform_data = &lpc_chipset_info[priv->chipset];
        cell->pdata_size = sizeof(struct lpc_ich_info);
@@ -904,7 +898,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
        base_addr = base_addr_cfg & 0x0000ff80;
        if (!base_addr) {
                dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
-               lpc_ich_cells[LPC_GPIO].num_resources--;
+               lpc_ich_gpio_cell.num_resources--;
                goto gpe0_done;
        }
 
@@ -918,7 +912,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev)
                 * the platform_device subsystem doesn't see this resource
                 * or it will register an invalid region.
                 */
-               lpc_ich_cells[LPC_GPIO].num_resources--;
+               lpc_ich_gpio_cell.num_resources--;
                acpi_conflict = true;
        } else {
                lpc_ich_enable_acpi_space(dev);
@@ -958,12 +952,12 @@ gpe0_done:
 
        lpc_ich_finalize_gpio_cell(dev);
        ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
-                             &lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL);
+                             &lpc_ich_gpio_cell, 1, NULL, 0, NULL);
 
 gpio_done:
        if (acpi_conflict)
                pr_warn("Resource conflict(s) found affecting %s\n",
-                               lpc_ich_cells[LPC_GPIO].name);
+                               lpc_ich_gpio_cell.name);
        return ret;
 }
 
@@ -1007,7 +1001,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
         */
        if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
                /* Don't register iomem for TCO ver 1 */
-               lpc_ich_cells[LPC_WDT].num_resources--;
+               lpc_ich_wdt_cell.num_resources--;
        } 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;
@@ -1035,7 +1029,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
                goto wdt_done;
 
        ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO,
-                             &lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL);
+                             &lpc_ich_wdt_cell, 1, NULL, 0, NULL);
 
 wdt_done:
        return ret;
index d3cfa9cf5c8f903e83c80957112b6220ab0d253e..156ed6f92aa32fffca7ce9d39ff494d0a0487cd0 100644 (file)
@@ -55,6 +55,7 @@ static const struct of_device_id max8997_pmic_dt_match[] = {
        { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
        {},
 };
+MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match);
 #endif
 
 int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
index c17635d3e5048418f9758eb37290b4cda282e1e4..60b60dc63dddbc610d0ac1cf02111066b4af5095 100644 (file)
@@ -82,29 +82,49 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
 static void mfd_acpi_add_device(const struct mfd_cell *cell,
                                struct platform_device *pdev)
 {
-       struct acpi_device *parent_adev;
+       const struct mfd_cell_acpi_match *match = cell->acpi_match;
+       struct acpi_device *parent, *child;
        struct acpi_device *adev;
 
-       parent_adev = ACPI_COMPANION(pdev->dev.parent);
-       if (!parent_adev)
+       parent = ACPI_COMPANION(pdev->dev.parent);
+       if (!parent)
                return;
 
        /*
-        * MFD child device gets its ACPI handle either from the ACPI
-        * device directly under the parent that matches the acpi_pnpid or
-        * it will use the parent handle if is no acpi_pnpid is given.
+        * MFD child device gets its ACPI handle either from the ACPI device
+        * directly under the parent that matches the either _HID or _CID, or
+        * _ADR or it will use the parent handle if is no ID is given.
+        *
+        * Note that use of _ADR is a grey area in the ACPI specification,
+        * though Intel Galileo Gen2 is using it to distinguish the children
+        * devices.
         */
-       adev = parent_adev;
-       if (cell->acpi_pnpid) {
-               struct acpi_device_id ids[2] = {};
-               struct acpi_device *child_adev;
-
-               strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
-               list_for_each_entry(child_adev, &parent_adev->children, node)
-                       if (acpi_match_device_ids(child_adev, ids)) {
-                               adev = child_adev;
-                               break;
+       adev = parent;
+       if (match) {
+               if (match->pnpid) {
+                       struct acpi_device_id ids[2] = {};
+
+                       strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
+                       list_for_each_entry(child, &parent->children, node) {
+                               if (acpi_match_device_ids(child, ids)) {
+                                       adev = child;
+                                       break;
+                               }
+                       }
+               } else {
+                       unsigned long long adr;
+                       acpi_status status;
+
+                       list_for_each_entry(child, &parent->children, node) {
+                               status = acpi_evaluate_integer(child->handle,
+                                                              "_ADR", NULL,
+                                                              &adr);
+                               if (ACPI_SUCCESS(status) && match->adr == adr) {
+                                       adev = child;
+                                       break;
+                               }
                        }
+               }
        }
 
        ACPI_COMPANION_SET(&pdev->dev, adev);
index 498286cbb5300d31f160b693e0f1d85ec254041f..71d43edf110ca1b0025929459a4e7abb42ce5856 100644 (file)
@@ -55,7 +55,7 @@ EXPORT_SYMBOL_GPL(pcf50633_free_irq);
 static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
 {
        u8 reg, bit;
-       int ret = 0, idx;
+       int idx;
 
        idx = irq >> 3;
        reg = PCF50633_REG_INT1M + idx;
@@ -72,7 +72,7 @@ static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
 
        mutex_unlock(&pcf->lock);
 
-       return ret;
+       return 0;
 }
 
 int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
index 6afc9fabd94c1f71f9456321d8fd7ccb5c50e5c4..207a3bd6855979c9f3299b834889870bbb249b34 100644 (file)
@@ -550,7 +550,7 @@ static int qcom_rpm_probe(struct platform_device *pdev)
        ret = devm_request_irq(&pdev->dev,
                               irq_ack,
                               qcom_rpm_ack_interrupt,
-                              IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
+                              IRQF_TRIGGER_RISING,
                               "qcom_rpm_ack",
                               rpm);
        if (ret) {
index d60f91619c4a5b2377c5ac43fee450228a8594ca..2b95485f00574704f4a4eea300b4ada92987df53 100644 (file)
@@ -47,6 +47,9 @@ static const struct mfd_cell rt5033_devs[] = {
        }, {
                .name = "rt5033-battery",
                .of_compatible = "richtek,rt5033-battery",
+       }, {
+               .name = "rt5033-led",
+               .of_compatible = "richtek,rt5033-led",
        },
 };
 
@@ -137,7 +140,6 @@ static struct i2c_driver rt5033_driver = {
 };
 module_i2c_driver(rt5033_driver);
 
-MODULE_ALIAS("i2c:rt5033");
 MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver");
 MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
 MODULE_LICENSE("GPL");
index 373e253c33df945544a9c6ce6caac564d1647bbc..b95beecf767fffffbb06ca18c82dbd3f5aa18673 100644 (file)
@@ -138,11 +138,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
                        LDO3318_PWR_MASK, 0x00);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       return 0;
+       return rtsx_pci_send_cmd(pcr, 100);
 }
 
 static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
index ce012d78ce2a0fe45ac78e52c6d17bb0a91f8632..ff296a4bf3d235a2bd860989b4464be58a79341d 100644 (file)
 
 #include "rtsx_pcr.h"
 
+static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+       return val & 0x0F;
+}
+
 static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
 {
        u8 driving_3v3[4][3] = {
@@ -88,7 +96,7 @@ static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
 
        if (pm_state == HOST_ENTER_S3)
-               rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
+               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10);
 
        rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
 }
@@ -121,7 +129,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
        else
                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
 
        return rtsx_pci_send_cmd(pcr, 100);
 }
@@ -179,11 +187,7 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
                        SD_POWER_MASK, SD_POWER_ON);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
                        LDO3318_PWR_MASK, 0x06);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       return 0;
+       return rtsx_pci_send_cmd(pcr, 100);
 }
 
 static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
@@ -298,8 +302,73 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
        pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
        pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
 
+       pcr->ic_version = rts5227_get_ic_version(pcr);
        pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
        pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
        pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
        pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
+
+       pcr->reg_pm_ctrl3 = PM_CTRL3;
+}
+
+static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
+               0x00);
+       if (err < 0)
+               return err;
+
+       if (is_version(pcr, 0x522A, IC_VER_A)) {
+               err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
+                       PHY_RCR2_INIT_27S);
+               if (err)
+                       return err;
+
+               rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
+       }
+
+       return 0;
+}
+
+static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5227_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
+               FUNC_FORCE_UPME_XMT_DBG);
+       rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
+       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
+       rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
+
+       return 0;
+}
+
+/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
+ */
+static const struct pcr_ops rts522a_pcr_ops = {
+       .fetch_vendor_settings = rts5227_fetch_vendor_settings,
+       .extra_init_hw = rts522a_extra_init_hw,
+       .optimize_phy = rts522a_optimize_phy,
+       .turn_on_led = rts5227_turn_on_led,
+       .turn_off_led = rts5227_turn_off_led,
+       .enable_auto_blink = rts5227_enable_auto_blink,
+       .disable_auto_blink = rts5227_disable_auto_blink,
+       .card_power_on = rts5227_card_power_on,
+       .card_power_off = rts5227_card_power_off,
+       .switch_output_voltage = rts5227_switch_output_voltage,
+       .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
+       .force_power_down = rts5227_force_power_down,
+};
+
+void rts522a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5227_init_params(pcr);
+
+       pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
 }
index ace45384ec8bc2893f9c1ff2bb4ea6cb027e2a23..9ed9dc84eac8b1a89324a89dd5a202fa1d3d9e7c 100644 (file)
@@ -129,11 +129,7 @@ static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
                        SD_POWER_MASK, SD_POWER_ON);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
                        LDO3318_PWR_MASK, 0x06);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       return 0;
+       return rtsx_pci_send_cmd(pcr, 100);
 }
 
 static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
index eb2d5866f7195296999b5d9afb11ae2eb707d862..40f8bb14fc59720906a6ad4d2e65edc0b5c40d4e 100644 (file)
@@ -234,11 +234,7 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
                        SD_POWER_MASK, SD_VCC_POWER_ON);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
                        LDO3318_PWR_MASK, 0x06);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       return 0;
+       return rtsx_pci_send_cmd(pcr, 100);
 }
 
 static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
index a66540a4907995bfd7b0dec0e0511c7c090ac1b6..f3820d08c9a3c9193014602ccafa019352003a6a 100644 (file)
@@ -55,6 +55,7 @@ static const struct pci_device_id rtsx_pci_ids[] = {
        { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
@@ -571,11 +572,7 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
                tbl++;
        }
 
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       return 0;
+       return rtsx_pci_send_cmd(pcr, 100);
 }
 
 int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
@@ -1102,6 +1099,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
                rts5227_init_params(pcr);
                break;
 
+       case 0x522A:
+               rts522a_init_params(pcr);
+               break;
+
        case 0x5249:
                rts5249_init_params(pcr);
                break;
index ce48842570d7c93fb9aa51c0fa691e802324e5fd..931d1ae3ce32b726d015cf5de5b9aa820da40ff6 100644 (file)
@@ -27,6 +27,8 @@
 #define MIN_DIV_N_PCR          80
 #define MAX_DIV_N_PCR          208
 
+#define RTS522A_PM_CTRL3               0xFF7E
+
 #define RTS524A_PME_FORCE_CTL          0xFF78
 #define RTS524A_PM_CTRL3               0xFF7E
 
@@ -38,6 +40,7 @@ void rts5229_init_params(struct rtsx_pcr *pcr);
 void rtl8411_init_params(struct rtsx_pcr *pcr);
 void rtl8402_init_params(struct rtsx_pcr *pcr);
 void rts5227_init_params(struct rtsx_pcr *pcr);
+void rts522a_init_params(struct rtsx_pcr *pcr);
 void rts5249_init_params(struct rtsx_pcr *pcr);
 void rts524a_init_params(struct rtsx_pcr *pcr);
 void rts525a_init_params(struct rtsx_pcr *pcr);
index d206a3e8fe87823d9f03db83984feab059f25188..989076d6cb83415451fe0776c12506493993f12d 100644 (file)
@@ -103,12 +103,9 @@ static const struct mfd_cell s2mpa01_devs[] = {
 };
 
 static const struct mfd_cell s2mpu02_devs[] = {
-       { .name = "s2mpu02-pmic", },
-       { .name = "s2mpu02-rtc", },
        {
-               .name = "s2mpu02-clk",
-               .of_compatible = "samsung,s2mpu02-clk",
-       }
+               .name = "s2mpu02-pmic",
+       },
 };
 
 #ifdef CONFIG_OF
@@ -253,6 +250,38 @@ static const struct regmap_config s5m8767_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
+static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
+{
+       unsigned int val;
+
+       /* For each device type, the REG_ID is always the first register */
+       if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
+               dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
+}
+
+static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
+{
+       int err;
+
+       if (sec_pmic->device_type != S2MPS13X)
+               return;
+
+       if (sec_pmic->pdata->disable_wrstbi) {
+               /*
+                * If WRSTBI pin is pulled down this feature must be disabled
+                * because each Suspend to RAM will trigger buck voltage reset
+                * to default values.
+                */
+               err = regmap_update_bits(sec_pmic->regmap_pmic,
+                                        S2MPS13_REG_WRSTBI,
+                                        S2MPS13_REG_WRSTBI_MASK, 0x0);
+               if (err)
+                       dev_warn(sec_pmic->dev,
+                                "Cannot initialize WRSTBI config: %d\n",
+                                err);
+       }
+}
+
 #ifdef CONFIG_OF
 /*
  * Only the common platform data elements for s5m8767 are parsed here from the
@@ -278,6 +307,10 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
         * not parsed here.
         */
 
+       pd->manual_poweroff = of_property_read_bool(dev->of_node,
+                                               "samsung,s2mps11-acokb-ground");
+       pd->disable_wrstbi = of_property_read_bool(dev->of_node,
+                                               "samsung,s2mps11-wrstbi-ground");
        return pd;
 }
 #else
@@ -423,6 +456,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                goto err_mfd;
 
        device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
+       sec_pmic_configure(sec_pmic);
+       sec_pmic_dump_rev(sec_pmic);
 
        return ret;
 
@@ -440,6 +475,33 @@ static int sec_pmic_remove(struct i2c_client *i2c)
        return 0;
 }
 
+static void sec_pmic_shutdown(struct i2c_client *i2c)
+{
+       struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+       unsigned int reg, mask;
+
+       if (!sec_pmic->pdata->manual_poweroff)
+               return;
+
+       switch (sec_pmic->device_type) {
+       case S2MPS11X:
+               reg = S2MPS11_REG_CTRL1;
+               mask = S2MPS11_CTRL1_PWRHOLD_MASK;
+               break;
+       default:
+               /*
+                * Currently only one board with S2MPS11 needs this, so just
+                * ignore the rest.
+                */
+               dev_warn(sec_pmic->dev,
+                       "Unsupported device %lu for manual power off\n",
+                       sec_pmic->device_type);
+               return;
+       }
+
+       regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int sec_pmic_suspend(struct device *dev)
 {
@@ -491,6 +553,7 @@ static struct i2c_driver sec_pmic_driver = {
        },
        .probe = sec_pmic_probe,
        .remove = sec_pmic_remove,
+       .shutdown = sec_pmic_shutdown,
        .id_table = sec_pmic_id,
 };
 
index 91077efc8050d9477a03ca1d49ffb0fdd66cab0b..c646784c5a7d0a5de96165f584a51a9c65f1e6ac 100644 (file)
@@ -1719,6 +1719,7 @@ static const struct of_device_id of_sm501_match_tbl[] = {
        { .compatible = "smi,sm501", },
        { /* end */ }
 };
+MODULE_DEVICE_TABLE(of, of_sm501_match_tbl);
 
 static struct platform_driver sm501_plat_driver = {
        .driver         = {
index e971af86ce1ef7e495d47364aeee15f5c10b76a1..8222e374e4b17d55d3d514e9fc414b96b998008c 100644 (file)
@@ -795,6 +795,7 @@ static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
                return 2;
 
        case STMPE_BLOCK_KEYPAD:
+       case STMPE_BLOCK_PWM:
                return 1;
 
        case STMPE_BLOCK_GPIO:
index 4a174cdb50b623e97d9360291b4ab2a4798c92a6..51c54951c2206b98cd74daf638e3ddee7f978649 100644 (file)
@@ -64,27 +64,47 @@ static int tps6105x_startup(struct tps6105x *tps6105x)
 }
 
 /*
- * MFD cells - we have one cell which is selected operation
- * mode, and we always have a GPIO cell.
+ * MFD cells - we always have a GPIO cell and we have one cell
+ * which is selected operation mode.
  */
-static struct mfd_cell tps6105x_cells[] = {
-       {
-               /* name will be runtime assigned */
-               .id = -1,
-       },
-       {
-               .name = "tps6105x-gpio",
-               .id = -1,
-       },
+static struct mfd_cell tps6105x_gpio_cell = {
+       .name = "tps6105x-gpio",
+};
+
+static struct mfd_cell tps6105x_leds_cell = {
+       .name = "tps6105x-leds",
+};
+
+static struct mfd_cell tps6105x_flash_cell = {
+       .name = "tps6105x-flash",
 };
 
+static struct mfd_cell tps6105x_regulator_cell = {
+       .name = "tps6105x-regulator",
+};
+
+static int tps6105x_add_device(struct tps6105x *tps6105x,
+                              struct mfd_cell *cell)
+{
+       cell->platform_data = tps6105x;
+       cell->pdata_size = sizeof(*tps6105x);
+
+       return mfd_add_devices(&tps6105x->client->dev,
+                              PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);
+}
+
 static int tps6105x_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct tps6105x                 *tps6105x;
        struct tps6105x_platform_data   *pdata;
        int ret;
-       int i;
+
+       pdata = dev_get_platdata(&client->dev);
+       if (!pdata) {
+               dev_err(&client->dev, "missing platform data\n");
+               return -ENODEV;
+       }
 
        tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
        if (!tps6105x)
@@ -96,7 +116,6 @@ static int tps6105x_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, tps6105x);
        tps6105x->client = client;
-       pdata = dev_get_platdata(&client->dev);
        tps6105x->pdata = pdata;
 
        ret = tps6105x_startup(tps6105x);
@@ -105,38 +124,33 @@ static int tps6105x_probe(struct i2c_client *client,
                return ret;
        }
 
-       /* Remove warning texts when you implement new cell drivers */
+       ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell);
+       if (ret)
+               return ret;
+
        switch (pdata->mode) {
        case TPS6105X_MODE_SHUTDOWN:
                dev_info(&client->dev,
                         "present, not used for anything, only GPIO\n");
                break;
        case TPS6105X_MODE_TORCH:
-               tps6105x_cells[0].name = "tps6105x-leds";
-               dev_warn(&client->dev,
-                        "torch mode is unsupported\n");
+               ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell);
                break;
        case TPS6105X_MODE_TORCH_FLASH:
-               tps6105x_cells[0].name = "tps6105x-flash";
-               dev_warn(&client->dev,
-                        "flash mode is unsupported\n");
+               ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell);
                break;
        case TPS6105X_MODE_VOLTAGE:
-               tps6105x_cells[0].name ="tps6105x-regulator";
+               ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell);
                break;
        default:
+               dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode);
                break;
        }
 
-       /* Set up and register the platform devices. */
-       for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) {
-               /* One state holder for all drivers, this is simple */
-               tps6105x_cells[i].platform_data = tps6105x;
-               tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
-       }
+       if (ret)
+               mfd_remove_devices(&client->dev);
 
-       return mfd_add_devices(&client->dev, 0, tps6105x_cells,
-                              ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
+       return ret;
 }
 
 static int tps6105x_remove(struct i2c_client *client)
index 55add0453ae9ba642b8570f9f003007857607eda..d32b54426b70a3d8baf47cc9a5e47f609b5c19d1 100644 (file)
@@ -39,6 +39,10 @@ static const struct mfd_cell tps65217s[] = {
                .name = "tps65217-bl",
                .of_compatible = "ti,tps65217-bl",
        },
+       {
+               .name = "tps65217-charger",
+               .of_compatible = "ti,tps65217-charger",
+       },
 };
 
 /**
index a151ee2eed2a4dfa450bade9d35f0a953c730d42..08a693cd38cc4e2b17a7538be0e55ed743b6c002 100644 (file)
@@ -647,6 +647,8 @@ static int twl6040_probe(struct i2c_client *client,
 
        twl6040->clk32k = devm_clk_get(&client->dev, "clk32k");
        if (IS_ERR(twl6040->clk32k)) {
+               if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
                dev_info(&client->dev, "clk32k is not handled\n");
                twl6040->clk32k = NULL;
        }
index 28f2ae30507a2f8dd5a7905c858ff4746a6c5676..2bb2d0467a92d35f10a15edc83cb7e07a692343c 100644 (file)
@@ -250,7 +250,7 @@ static const struct reg_sequence wm5110_revd_patch[] = {
 };
 
 /* Add extra headphone write sequence locations */
-static const struct reg_default wm5110_reve_patch[] = {
+static const struct reg_sequence wm5110_reve_patch[] = {
        { 0x80, 0x3 },
        { 0x80, 0x3 },
        { 0x4b, 0x138 },
@@ -1633,6 +1633,185 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000EF8, 0x0000 },    /* R3832  - ISRC 3 CTRL 3 */
        { 0x00000F00, 0x0000 },    /* R3840  - Clock Control */
        { 0x00000F01, 0x0000 },    /* R3841  - ANC_SRC */
+       { 0x00000F08, 0x001c },    /* R3848  - ANC Coefficient */
+       { 0x00000F09, 0x0000 },    /* R3849  - ANC Coefficient */
+       { 0x00000F0A, 0x0000 },    /* R3850  - ANC Coefficient */
+       { 0x00000F0B, 0x0000 },    /* R3851  - ANC Coefficient */
+       { 0x00000F0C, 0x0000 },    /* R3852  - ANC Coefficient */
+       { 0x00000F0D, 0x0000 },    /* R3853  - ANC Coefficient */
+       { 0x00000F0E, 0x0000 },    /* R3854  - ANC Coefficient */
+       { 0x00000F0F, 0x0000 },    /* R3855  - ANC Coefficient */
+       { 0x00000F10, 0x0000 },    /* R3856  - ANC Coefficient */
+       { 0x00000F11, 0x0000 },    /* R3857  - ANC Coefficient */
+       { 0x00000F12, 0x0000 },    /* R3858  - ANC Coefficient */
+       { 0x00000F15, 0x0000 },    /* R3861  - FCL Filter Control */
+       { 0x00000F17, 0x0004 },    /* R3863  - FCL ADC Reformatter Control */
+       { 0x00000F18, 0x0004 },    /* R3864  - ANC Coefficient */
+       { 0x00000F19, 0x0002 },    /* R3865  - ANC Coefficient */
+       { 0x00000F1A, 0x0000 },    /* R3866  - ANC Coefficient */
+       { 0x00000F1B, 0x0010 },    /* R3867  - ANC Coefficient */
+       { 0x00000F1C, 0x0000 },    /* R3868  - ANC Coefficient */
+       { 0x00000F1D, 0x0000 },    /* R3869  - ANC Coefficient */
+       { 0x00000F1E, 0x0000 },    /* R3870  - ANC Coefficient */
+       { 0x00000F1F, 0x0000 },    /* R3871  - ANC Coefficient */
+       { 0x00000F20, 0x0000 },    /* R3872  - ANC Coefficient */
+       { 0x00000F21, 0x0000 },    /* R3873  - ANC Coefficient */
+       { 0x00000F22, 0x0000 },    /* R3874  - ANC Coefficient */
+       { 0x00000F23, 0x0000 },    /* R3875  - ANC Coefficient */
+       { 0x00000F24, 0x0000 },    /* R3876  - ANC Coefficient */
+       { 0x00000F25, 0x0000 },    /* R3877  - ANC Coefficient */
+       { 0x00000F26, 0x0000 },    /* R3878  - ANC Coefficient */
+       { 0x00000F27, 0x0000 },    /* R3879  - ANC Coefficient */
+       { 0x00000F28, 0x0000 },    /* R3880  - ANC Coefficient */
+       { 0x00000F29, 0x0000 },    /* R3881  - ANC Coefficient */
+       { 0x00000F2A, 0x0000 },    /* R3882  - ANC Coefficient */
+       { 0x00000F2B, 0x0000 },    /* R3883  - ANC Coefficient */
+       { 0x00000F2C, 0x0000 },    /* R3884  - ANC Coefficient */
+       { 0x00000F2D, 0x0000 },    /* R3885  - ANC Coefficient */
+       { 0x00000F2E, 0x0000 },    /* R3886  - ANC Coefficient */
+       { 0x00000F2F, 0x0000 },    /* R3887  - ANC Coefficient */
+       { 0x00000F30, 0x0000 },    /* R3888  - ANC Coefficient */
+       { 0x00000F31, 0x0000 },    /* R3889  - ANC Coefficient */
+       { 0x00000F32, 0x0000 },    /* R3890  - ANC Coefficient */
+       { 0x00000F33, 0x0000 },    /* R3891  - ANC Coefficient */
+       { 0x00000F34, 0x0000 },    /* R3892  - ANC Coefficient */
+       { 0x00000F35, 0x0000 },    /* R3893  - ANC Coefficient */
+       { 0x00000F36, 0x0000 },    /* R3894  - ANC Coefficient */
+       { 0x00000F37, 0x0000 },    /* R3895  - ANC Coefficient */
+       { 0x00000F38, 0x0000 },    /* R3896  - ANC Coefficient */
+       { 0x00000F39, 0x0000 },    /* R3897  - ANC Coefficient */
+       { 0x00000F3A, 0x0000 },    /* R3898  - ANC Coefficient */
+       { 0x00000F3B, 0x0000 },    /* R3899  - ANC Coefficient */
+       { 0x00000F3C, 0x0000 },    /* R3900  - ANC Coefficient */
+       { 0x00000F3D, 0x0000 },    /* R3901  - ANC Coefficient */
+       { 0x00000F3E, 0x0000 },    /* R3902  - ANC Coefficient */
+       { 0x00000F3F, 0x0000 },    /* R3903  - ANC Coefficient */
+       { 0x00000F40, 0x0000 },    /* R3904  - ANC Coefficient */
+       { 0x00000F41, 0x0000 },    /* R3905  - ANC Coefficient */
+       { 0x00000F42, 0x0000 },    /* R3906  - ANC Coefficient */
+       { 0x00000F43, 0x0000 },    /* R3907  - ANC Coefficient */
+       { 0x00000F44, 0x0000 },    /* R3908  - ANC Coefficient */
+       { 0x00000F45, 0x0000 },    /* R3909  - ANC Coefficient */
+       { 0x00000F46, 0x0000 },    /* R3910  - ANC Coefficient */
+       { 0x00000F47, 0x0000 },    /* R3911  - ANC Coefficient */
+       { 0x00000F48, 0x0000 },    /* R3912  - ANC Coefficient */
+       { 0x00000F49, 0x0000 },    /* R3913  - ANC Coefficient */
+       { 0x00000F4A, 0x0000 },    /* R3914  - ANC Coefficient */
+       { 0x00000F4B, 0x0000 },    /* R3915  - ANC Coefficient */
+       { 0x00000F4C, 0x0000 },    /* R3916  - ANC Coefficient */
+       { 0x00000F4D, 0x0000 },    /* R3917  - ANC Coefficient */
+       { 0x00000F4E, 0x0000 },    /* R3918  - ANC Coefficient */
+       { 0x00000F4F, 0x0000 },    /* R3919  - ANC Coefficient */
+       { 0x00000F50, 0x0000 },    /* R3920  - ANC Coefficient */
+       { 0x00000F51, 0x0000 },    /* R3921  - ANC Coefficient */
+       { 0x00000F52, 0x0000 },    /* R3922  - ANC Coefficient */
+       { 0x00000F53, 0x0000 },    /* R3923  - ANC Coefficient */
+       { 0x00000F54, 0x0000 },    /* R3924  - ANC Coefficient */
+       { 0x00000F55, 0x0000 },    /* R3925  - ANC Coefficient */
+       { 0x00000F56, 0x0000 },    /* R3926  - ANC Coefficient */
+       { 0x00000F57, 0x0000 },    /* R3927  - ANC Coefficient */
+       { 0x00000F58, 0x0000 },    /* R3928  - ANC Coefficient */
+       { 0x00000F59, 0x0000 },    /* R3929  - ANC Coefficient */
+       { 0x00000F5A, 0x0000 },    /* R3930  - ANC Coefficient */
+       { 0x00000F5B, 0x0000 },    /* R3931  - ANC Coefficient */
+       { 0x00000F5C, 0x0000 },    /* R3932  - ANC Coefficient */
+       { 0x00000F5D, 0x0000 },    /* R3933  - ANC Coefficient */
+       { 0x00000F5E, 0x0000 },    /* R3934  - ANC Coefficient */
+       { 0x00000F5F, 0x0000 },    /* R3935  - ANC Coefficient */
+       { 0x00000F60, 0x0000 },    /* R3936  - ANC Coefficient */
+       { 0x00000F61, 0x0000 },    /* R3937  - ANC Coefficient */
+       { 0x00000F62, 0x0000 },    /* R3938  - ANC Coefficient */
+       { 0x00000F63, 0x0000 },    /* R3939  - ANC Coefficient */
+       { 0x00000F64, 0x0000 },    /* R3940  - ANC Coefficient */
+       { 0x00000F65, 0x0000 },    /* R3941  - ANC Coefficient */
+       { 0x00000F66, 0x0000 },    /* R3942  - ANC Coefficient */
+       { 0x00000F67, 0x0000 },    /* R3943  - ANC Coefficient */
+       { 0x00000F68, 0x0000 },    /* R3944  - ANC Coefficient */
+       { 0x00000F69, 0x0000 },    /* R3945  - ANC Coefficient */
+       { 0x00000F70, 0x0000 },    /* R3952  - FCR Filter Control */
+       { 0x00000F72, 0x0004 },    /* R3954  - FCR ADC Reformatter Control */
+       { 0x00000F73, 0x0004 },    /* R3955  - ANC Coefficient */
+       { 0x00000F74, 0x0002 },    /* R3956  - ANC Coefficient */
+       { 0x00000F75, 0x0000 },    /* R3957  - ANC Coefficient */
+       { 0x00000F76, 0x0010 },    /* R3958  - ANC Coefficient */
+       { 0x00000F77, 0x0000 },    /* R3959  - ANC Coefficient */
+       { 0x00000F78, 0x0000 },    /* R3960  - ANC Coefficient */
+       { 0x00000F79, 0x0000 },    /* R3961  - ANC Coefficient */
+       { 0x00000F7A, 0x0000 },    /* R3962  - ANC Coefficient */
+       { 0x00000F7B, 0x0000 },    /* R3963  - ANC Coefficient */
+       { 0x00000F7C, 0x0000 },    /* R3964  - ANC Coefficient */
+       { 0x00000F7D, 0x0000 },    /* R3965  - ANC Coefficient */
+       { 0x00000F7E, 0x0000 },    /* R3966  - ANC Coefficient */
+       { 0x00000F7F, 0x0000 },    /* R3967  - ANC Coefficient */
+       { 0x00000F80, 0x0000 },    /* R3968  - ANC Coefficient */
+       { 0x00000F81, 0x0000 },    /* R3969  - ANC Coefficient */
+       { 0x00000F82, 0x0000 },    /* R3970  - ANC Coefficient */
+       { 0x00000F83, 0x0000 },    /* R3971  - ANC Coefficient */
+       { 0x00000F84, 0x0000 },    /* R3972  - ANC Coefficient */
+       { 0x00000F85, 0x0000 },    /* R3973  - ANC Coefficient */
+       { 0x00000F86, 0x0000 },    /* R3974  - ANC Coefficient */
+       { 0x00000F87, 0x0000 },    /* R3975  - ANC Coefficient */
+       { 0x00000F88, 0x0000 },    /* R3976  - ANC Coefficient */
+       { 0x00000F89, 0x0000 },    /* R3977  - ANC Coefficient */
+       { 0x00000F8A, 0x0000 },    /* R3978  - ANC Coefficient */
+       { 0x00000F8B, 0x0000 },    /* R3979  - ANC Coefficient */
+       { 0x00000F8C, 0x0000 },    /* R3980  - ANC Coefficient */
+       { 0x00000F8D, 0x0000 },    /* R3981  - ANC Coefficient */
+       { 0x00000F8E, 0x0000 },    /* R3982  - ANC Coefficient */
+       { 0x00000F8F, 0x0000 },    /* R3983  - ANC Coefficient */
+       { 0x00000F90, 0x0000 },    /* R3984  - ANC Coefficient */
+       { 0x00000F91, 0x0000 },    /* R3985  - ANC Coefficient */
+       { 0x00000F92, 0x0000 },    /* R3986  - ANC Coefficient */
+       { 0x00000F93, 0x0000 },    /* R3987  - ANC Coefficient */
+       { 0x00000F94, 0x0000 },    /* R3988  - ANC Coefficient */
+       { 0x00000F95, 0x0000 },    /* R3989  - ANC Coefficient */
+       { 0x00000F96, 0x0000 },    /* R3990  - ANC Coefficient */
+       { 0x00000F97, 0x0000 },    /* R3991  - ANC Coefficient */
+       { 0x00000F98, 0x0000 },    /* R3992  - ANC Coefficient */
+       { 0x00000F99, 0x0000 },    /* R3993  - ANC Coefficient */
+       { 0x00000F9A, 0x0000 },    /* R3994  - ANC Coefficient */
+       { 0x00000F9B, 0x0000 },    /* R3995  - ANC Coefficient */
+       { 0x00000F9C, 0x0000 },    /* R3996  - ANC Coefficient */
+       { 0x00000F9D, 0x0000 },    /* R3997  - ANC Coefficient */
+       { 0x00000F9E, 0x0000 },    /* R3998  - ANC Coefficient */
+       { 0x00000F9F, 0x0000 },    /* R3999  - ANC Coefficient */
+       { 0x00000FA0, 0x0000 },    /* R4000  - ANC Coefficient */
+       { 0x00000FA1, 0x0000 },    /* R4001  - ANC Coefficient */
+       { 0x00000FA2, 0x0000 },    /* R4002  - ANC Coefficient */
+       { 0x00000FA3, 0x0000 },    /* R4003  - ANC Coefficient */
+       { 0x00000FA4, 0x0000 },    /* R4004  - ANC Coefficient */
+       { 0x00000FA5, 0x0000 },    /* R4005  - ANC Coefficient */
+       { 0x00000FA6, 0x0000 },    /* R4006  - ANC Coefficient */
+       { 0x00000FA7, 0x0000 },    /* R4007  - ANC Coefficient */
+       { 0x00000FA8, 0x0000 },    /* R4008  - ANC Coefficient */
+       { 0x00000FA9, 0x0000 },    /* R4009  - ANC Coefficient */
+       { 0x00000FAA, 0x0000 },    /* R4010  - ANC Coefficient */
+       { 0x00000FAB, 0x0000 },    /* R4011  - ANC Coefficient */
+       { 0x00000FAC, 0x0000 },    /* R4012  - ANC Coefficient */
+       { 0x00000FAD, 0x0000 },    /* R4013  - ANC Coefficient */
+       { 0x00000FAE, 0x0000 },    /* R4014  - ANC Coefficient */
+       { 0x00000FAF, 0x0000 },    /* R4015  - ANC Coefficient */
+       { 0x00000FB0, 0x0000 },    /* R4016  - ANC Coefficient */
+       { 0x00000FB1, 0x0000 },    /* R4017  - ANC Coefficient */
+       { 0x00000FB2, 0x0000 },    /* R4018  - ANC Coefficient */
+       { 0x00000FB3, 0x0000 },    /* R4019  - ANC Coefficient */
+       { 0x00000FB4, 0x0000 },    /* R4020  - ANC Coefficient */
+       { 0x00000FB5, 0x0000 },    /* R4021  - ANC Coefficient */
+       { 0x00000FB6, 0x0000 },    /* R4022  - ANC Coefficient */
+       { 0x00000FB7, 0x0000 },    /* R4023  - ANC Coefficient */
+       { 0x00000FB8, 0x0000 },    /* R4024  - ANC Coefficient */
+       { 0x00000FB9, 0x0000 },    /* R4025  - ANC Coefficient */
+       { 0x00000FBA, 0x0000 },    /* R4026  - ANC Coefficient */
+       { 0x00000FBB, 0x0000 },    /* R4027  - ANC Coefficient */
+       { 0x00000FBC, 0x0000 },    /* R4028  - ANC Coefficient */
+       { 0x00000FBD, 0x0000 },    /* R4029  - ANC Coefficient */
+       { 0x00000FBE, 0x0000 },    /* R4030  - ANC Coefficient */
+       { 0x00000FBF, 0x0000 },    /* R4031  - ANC Coefficient */
+       { 0x00000FC0, 0x0000 },    /* R4032  - ANC Coefficient */
+       { 0x00000FC1, 0x0000 },    /* R4033  - ANC Coefficient */
+       { 0x00000FC2, 0x0000 },    /* R4034  - ANC Coefficient */
+       { 0x00000FC3, 0x0000 },    /* R4035  - ANC Coefficient */
+       { 0x00000FC4, 0x0000 },    /* R4036  - ANC Coefficient */
        { 0x00001100, 0x0010 },    /* R4352  - DSP1 Control 1 */
        { 0x00001200, 0x0010 },    /* R4608  - DSP2 Control 1 */
        { 0x00001300, 0x0010 },    /* R4864  - DSP3 Control 1 */
@@ -2710,6 +2889,13 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_CLOCK_CONTROL:
        case ARIZONA_ANC_SRC:
        case ARIZONA_DSP_STATUS:
+       case ARIZONA_ANC_COEFF_START ... ARIZONA_ANC_COEFF_END:
+       case ARIZONA_FCL_FILTER_CONTROL:
+       case ARIZONA_FCL_ADC_REFORMATTER_CONTROL:
+       case ARIZONA_FCL_COEFF_START ... ARIZONA_FCL_COEFF_END:
+       case ARIZONA_FCR_FILTER_CONTROL:
+       case ARIZONA_FCR_ADC_REFORMATTER_CONTROL:
+       case ARIZONA_FCR_COEFF_START ... ARIZONA_FCR_COEFF_END:
        case ARIZONA_DSP1_CONTROL_1:
        case ARIZONA_DSP1_CLOCKING_1:
        case ARIZONA_DSP1_STATUS_1:
index 28366a90e1adfbec14b5679244676b1077c9926e..3e0e99ec5836dafa758468351b000e76ad6b7dae 100644 (file)
@@ -1626,7 +1626,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        mutex_init(&wm831x->io_lock);
        mutex_init(&wm831x->key_lock);
        dev_set_drvdata(wm831x->dev, wm831x);
-       wm831x->soft_shutdown = pdata->soft_shutdown;
+
+       if (pdata)
+               wm831x->soft_shutdown = pdata->soft_shutdown;
 
        ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
        if (ret < 0) {
index e6de3cd8a9aacf0abdf45015bc8b850d584ffaa1..4c2dce77cdfc418c244b1231a3fee297fa0d175b 100644 (file)
@@ -21,7 +21,7 @@
 #define WM8998_NUM_AOD_ISR 2
 #define WM8998_NUM_ISR 5
 
-static const struct reg_default wm8998_rev_a_patch[] = {
+static const struct reg_sequence wm8998_rev_a_patch[] = {
        { 0x0212, 0x0000 },
        { 0x0211, 0x0014 },
        { 0x04E4, 0x0E0D },
@@ -199,8 +199,6 @@ static const struct reg_default wm8998_reg_default[] = {
        { 0x00000069, 0x01FF },    /* R105   - Always On Triggers Sequence Select 4 */
        { 0x0000006A, 0x01FF },    /* R106   - Always On Triggers Sequence Select 5 */
        { 0x0000006B, 0x01FF },    /* R107   - Always On Triggers Sequence Select 6 */
-       { 0x0000006E, 0x01FF },    /* R110   - Trigger Sequence Select 32 */
-       { 0x0000006F, 0x01FF },    /* R111   - Trigger Sequence Select 33 */
        { 0x00000090, 0x0000 },    /* R144   - Haptics Control 1 */
        { 0x00000091, 0x7FFF },    /* R145   - Haptics Control 2 */
        { 0x00000092, 0x0000 },    /* R146   - Haptics phase 1 intensity */
@@ -270,16 +268,13 @@ static const struct reg_default wm8998_reg_default[] = {
        { 0x0000021A, 0x01A6 },    /* R538   - Mic Bias Ctrl 3 */
        { 0x00000293, 0x0080 },    /* R659   - Accessory Detect Mode 1 */
        { 0x0000029B, 0x0000 },    /* R667   - Headphone Detect 1 */
-       { 0x0000029C, 0x0000 },    /* R668   - Headphone Detect 2 */
        { 0x000002A2, 0x0000 },    /* R674   - Micd Clamp control */
        { 0x000002A3, 0x1102 },    /* R675   - Mic Detect 1 */
        { 0x000002A4, 0x009F },    /* R676   - Mic Detect 2 */
-       { 0x000002A5, 0x0000 },    /* R677   - Mic Detect 3 */
        { 0x000002A6, 0x3737 },    /* R678   - Mic Detect Level 1 */
        { 0x000002A7, 0x2C37 },    /* R679   - Mic Detect Level 2 */
        { 0x000002A8, 0x1422 },    /* R680   - Mic Detect Level 3 */
        { 0x000002A9, 0x030A },    /* R681   - Mic Detect Level 4 */
-       { 0x000002AB, 0x0000 },    /* R683   - Mic Detect 4 */
        { 0x000002CB, 0x0000 },    /* R715   - Isolation control */
        { 0x000002D3, 0x0000 },    /* R723   - Jack detect analogue */
        { 0x00000300, 0x0000 },    /* R768   - Input Enables */
@@ -707,13 +702,11 @@ static const struct reg_default wm8998_reg_default[] = {
        { 0x00000D1A, 0xFFFF },    /* R3354  - IRQ2 Status 3 Mask */
        { 0x00000D1B, 0xFFFF },    /* R3355  - IRQ2 Status 4 Mask */
        { 0x00000D1C, 0xFEFF },    /* R3356  - IRQ2 Status 5 Mask */
-       { 0x00000D1D, 0xFFFF },    /* R3357  - IRQ2 Status 6 Mask */
        { 0x00000D1F, 0x0000 },    /* R3359  - IRQ2 Control */
        { 0x00000D53, 0xFFFF },    /* R3411  - AOD IRQ Mask IRQ1 */
        { 0x00000D54, 0xFFFF },    /* R3412  - AOD IRQ Mask IRQ2 */
        { 0x00000D56, 0x0000 },    /* R3414  - Jack detect debounce */
        { 0x00000E00, 0x0000 },    /* R3584  - FX_Ctrl1 */
-       { 0x00000E01, 0x0000 },    /* R3585  - FX_Ctrl2 */
        { 0x00000E10, 0x6318 },    /* R3600  - EQ1_1 */
        { 0x00000E11, 0x6300 },    /* R3601  - EQ1_2 */
        { 0x00000E12, 0x0FC8 },    /* R3602  - EQ1_3 */
@@ -833,7 +826,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg)
        switch (reg) {
        case ARIZONA_SOFTWARE_RESET:
        case ARIZONA_DEVICE_REVISION:
-       case ARIZONA_CTRL_IF_SPI_CFG_1:
        case ARIZONA_CTRL_IF_I2C1_CFG_1:
        case ARIZONA_CTRL_IF_I2C1_CFG_2:
        case ARIZONA_WRITE_SEQUENCER_CTRL_0:
index c6cb7f8f325e91c530656b4d1eac709c82f8212e..5d7c0900fa1b129c8bf103d3eddd03cbd92fe80d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 #include <linux/of.h>
+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/at24.h>
 
@@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, at24_ids);
 
+static const struct acpi_device_id at24_acpi_ids[] = {
+       { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client,
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct at24_platform_data chip;
+       kernel_ulong_t magic = 0;
        bool writable;
        int use_smbus = 0;
        int use_smbus_write = 0;
        struct at24_data *at24;
        int err;
        unsigned i, num_addresses;
-       kernel_ulong_t magic;
 
        if (client->dev.platform_data) {
                chip = *(struct at24_platform_data *)client->dev.platform_data;
        } else {
-               if (!id->driver_data)
+               if (id) {
+                       magic = id->driver_data;
+               } else {
+                       const struct acpi_device_id *aid;
+
+                       aid = acpi_match_device(at24_acpi_ids, &client->dev);
+                       if (aid)
+                               magic = aid->driver_data;
+               }
+               if (!magic)
                        return -ENODEV;
 
-               magic = id->driver_data;
                chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
                magic >>= AT24_SIZE_BYTELEN;
                chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
@@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client)
 static struct i2c_driver at24_driver = {
        .driver = {
                .name = "at24",
+               .acpi_match_table = ACPI_PTR(at24_acpi_ids),
        },
        .probe = at24_probe,
        .remove = at24_remove,
index 7b492d9b3ec4b9a79a8c14245db3d75a51528c2b..02bbc70c332dd8fb2d241974e5e41f140aa8a8c3 100644 (file)
@@ -932,6 +932,7 @@ config PVPANIC
 
 config INTEL_PMC_IPC
        tristate "Intel PMC IPC Driver"
+       depends on ACPI
        ---help---
        This driver provides support for PMC control on some Intel platforms.
        The PMC is an ARC processor which defines IPC commands for communication
index 02b3b313809ab5a1fd0fe79352d6b7f8ed424b93..237d7aa73e8c8e15d74560c97560fb0ebdfcfead 100644 (file)
@@ -203,6 +203,16 @@ config CHARGER_DA9150
          This driver can also be built as a module. If so, the module will be
          called da9150-charger.
 
+config BATTERY_DA9150
+       tristate "Dialog Semiconductor DA9150 Fuel Gauge support"
+       depends on MFD_DA9150
+       help
+         Say Y here to enable support for the Fuel-Gauge unit of the DA9150
+         Integrated Charger & Fuel-Gauge IC
+
+         This driver can also be built as a module. If so, the module will be
+         called da9150-fg.
+
 config AXP288_CHARGER
        tristate "X-Powers AXP288 Charger"
        depends on MFD_AXP20X && EXTCON_AXP288
index b0e1bf190e3d660f878fd593e2ace3b24ba1e118..b656638f8b3984ed41be4cb7bd26a57fb05d028c 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
 obj-$(CONFIG_BATTERY_DA9030)   += da9030_battery.o
 obj-$(CONFIG_BATTERY_DA9052)   += da9052-battery.o
 obj-$(CONFIG_CHARGER_DA9150)   += da9150-charger.o
+obj-$(CONFIG_BATTERY_DA9150)   += da9150-fg.o
 obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
 obj-$(CONFIG_BATTERY_Z2)       += z2_battery.o
diff --git a/drivers/power/da9150-fg.c b/drivers/power/da9150-fg.c
new file mode 100644 (file)
index 0000000..8b8ce97
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * DA9150 Fuel-Gauge Driver
+ *
+ * Copyright (c) 2015 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/power_supply.h>
+#include <linux/list.h>
+#include <asm/div64.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Core2Wire */
+#define DA9150_QIF_READ                (0x0 << 7)
+#define DA9150_QIF_WRITE       (0x1 << 7)
+#define DA9150_QIF_CODE_MASK   0x7F
+
+#define DA9150_QIF_BYTE_SIZE   8
+#define DA9150_QIF_BYTE_MASK   0xFF
+#define DA9150_QIF_SHORT_SIZE  2
+#define DA9150_QIF_LONG_SIZE   4
+
+/* QIF Codes */
+#define DA9150_QIF_UAVG                        6
+#define DA9150_QIF_UAVG_SIZE           DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_IAVG                        8
+#define DA9150_QIF_IAVG_SIZE           DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_NTCAVG              12
+#define DA9150_QIF_NTCAVG_SIZE         DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_SHUNT_VAL           36
+#define DA9150_QIF_SHUNT_VAL_SIZE      DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SD_GAIN             38
+#define DA9150_QIF_SD_GAIN_SIZE                DA9150_QIF_LONG_SIZE
+#define DA9150_QIF_FCC_MAH             40
+#define DA9150_QIF_FCC_MAH_SIZE                DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SOC_PCT             43
+#define DA9150_QIF_SOC_PCT_SIZE                DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_CHARGE_LIMIT                44
+#define DA9150_QIF_CHARGE_LIMIT_SIZE   DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_DISCHARGE_LIMIT     45
+#define DA9150_QIF_DISCHARGE_LIMIT_SIZE        DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_FW_MAIN_VER         118
+#define DA9150_QIF_FW_MAIN_VER_SIZE    DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_E_FG_STATUS         126
+#define DA9150_QIF_E_FG_STATUS_SIZE    DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_SYNC                        127
+#define DA9150_QIF_SYNC_SIZE           DA9150_QIF_SHORT_SIZE
+#define DA9150_QIF_MAX_CODES           128
+
+/* QIF Sync Timeout */
+#define DA9150_QIF_SYNC_TIMEOUT                1000
+#define DA9150_QIF_SYNC_RETRIES                10
+
+/* QIF E_FG_STATUS */
+#define DA9150_FG_IRQ_LOW_SOC_MASK     (1 << 0)
+#define DA9150_FG_IRQ_HIGH_SOC_MASK    (1 << 1)
+#define DA9150_FG_IRQ_SOC_MASK \
+       (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK)
+
+/* Private data */
+struct da9150_fg {
+       struct da9150 *da9150;
+       struct device *dev;
+
+       struct mutex io_lock;
+
+       struct power_supply *battery;
+       struct delayed_work work;
+       u32 interval;
+
+       int warn_soc;
+       int crit_soc;
+       int soc;
+};
+
+/* Battery Properties */
+static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size)
+
+{
+       u8 buf[size];
+       u8 read_addr;
+       u32 res = 0;
+       int i;
+
+       /* Set QIF code (READ mode) */
+       read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ;
+
+       da9150_read_qif(fg->da9150, read_addr, size, buf);
+       for (i = 0; i < size; ++i)
+               res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE));
+
+       return res;
+}
+
+static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size,
+                                u32 val)
+
+{
+       u8 buf[size];
+       u8 write_addr;
+       int i;
+
+       /* Set QIF code (WRITE mode) */
+       write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE;
+
+       for (i = 0; i < size; ++i) {
+               buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) &
+                        DA9150_QIF_BYTE_MASK;
+       }
+       da9150_write_qif(fg->da9150, write_addr, size, buf);
+}
+
+/* Trigger QIF Sync to update QIF readable data */
+static void da9150_fg_read_sync_start(struct da9150_fg *fg)
+{
+       int i = 0;
+       u32 res = 0;
+
+       mutex_lock(&fg->io_lock);
+
+       /* Check if QIF sync already requested, and write to sync if not */
+       res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+                                 DA9150_QIF_SYNC_SIZE);
+       if (res > 0)
+               da9150_fg_write_attr(fg, DA9150_QIF_SYNC,
+                                    DA9150_QIF_SYNC_SIZE, 0);
+
+       /* Wait for sync to complete */
+       res = 0;
+       while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+               usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+                            DA9150_QIF_SYNC_TIMEOUT * 2);
+               res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+                                         DA9150_QIF_SYNC_SIZE);
+       }
+
+       /* Check if sync completed */
+       if (res == 0)
+               dev_err(fg->dev, "Failed to perform QIF read sync!\n");
+}
+
+/*
+ * Should always be called after QIF sync read has been performed, and all
+ * attributes required have been accessed.
+ */
+static inline void da9150_fg_read_sync_end(struct da9150_fg *fg)
+{
+       mutex_unlock(&fg->io_lock);
+}
+
+/* Sync read of single QIF attribute */
+static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size)
+{
+       u32 val;
+
+       da9150_fg_read_sync_start(fg);
+       val = da9150_fg_read_attr(fg, code, size);
+       da9150_fg_read_sync_end(fg);
+
+       return val;
+}
+
+/* Wait for QIF Sync, write QIF data and wait for ack */
+static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size,
+                                     u32 val)
+{
+       int i = 0;
+       u32 res = 0, sync_val;
+
+       mutex_lock(&fg->io_lock);
+
+       /* Check if QIF sync already requested */
+       res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+                                 DA9150_QIF_SYNC_SIZE);
+
+       /* Wait for an existing sync to complete */
+       while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+               usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+                            DA9150_QIF_SYNC_TIMEOUT * 2);
+               res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+                                         DA9150_QIF_SYNC_SIZE);
+       }
+
+       if (res == 0) {
+               dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n");
+               mutex_unlock(&fg->io_lock);
+               return;
+       }
+
+       /* Write value for QIF code */
+       da9150_fg_write_attr(fg, code, size, val);
+
+       /* Wait for write acknowledgment */
+       i = 0;
+       sync_val = res;
+       while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
+               usleep_range(DA9150_QIF_SYNC_TIMEOUT,
+                            DA9150_QIF_SYNC_TIMEOUT * 2);
+               res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
+                                         DA9150_QIF_SYNC_SIZE);
+       }
+
+       mutex_unlock(&fg->io_lock);
+
+       /* Check write was actually successful */
+       if (res != (sync_val + 1))
+               dev_err(fg->dev, "Error performing QIF sync write for code %d\n",
+                       code);
+}
+
+/* Power Supply attributes */
+static int da9150_fg_capacity(struct da9150_fg *fg,
+                             union power_supply_propval *val)
+{
+       val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
+                                              DA9150_QIF_SOC_PCT_SIZE);
+
+       if (val->intval > 100)
+               val->intval = 100;
+
+       return 0;
+}
+
+static int da9150_fg_current_avg(struct da9150_fg *fg,
+                                union power_supply_propval *val)
+{
+       u32 iavg, sd_gain, shunt_val;
+       u64 div, res;
+
+       da9150_fg_read_sync_start(fg);
+       iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG,
+                                  DA9150_QIF_IAVG_SIZE);
+       shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL,
+                                       DA9150_QIF_SHUNT_VAL_SIZE);
+       sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN,
+                                     DA9150_QIF_SD_GAIN_SIZE);
+       da9150_fg_read_sync_end(fg);
+
+       div = (u64) (sd_gain * shunt_val * 65536ULL);
+       do_div(div, 1000000);
+       res = (u64) (iavg * 1000000ULL);
+       do_div(res, div);
+
+       val->intval = (int) res;
+
+       return 0;
+}
+
+static int da9150_fg_voltage_avg(struct da9150_fg *fg,
+                                union power_supply_propval *val)
+{
+       u64 res;
+
+       val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG,
+                                              DA9150_QIF_UAVG_SIZE);
+
+       res = (u64) (val->intval * 186ULL);
+       do_div(res, 10000);
+       val->intval = (int) res;
+
+       return 0;
+}
+
+static int da9150_fg_charge_full(struct da9150_fg *fg,
+                                union power_supply_propval *val)
+{
+       val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH,
+                                              DA9150_QIF_FCC_MAH_SIZE);
+
+       val->intval = val->intval * 1000;
+
+       return 0;
+}
+
+/*
+ * Temperature reading from device is only valid if battery/system provides
+ * valid NTC to associated pin of DA9150 chip.
+ */
+static int da9150_fg_temp(struct da9150_fg *fg,
+                         union power_supply_propval *val)
+{
+       val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG,
+                                              DA9150_QIF_NTCAVG_SIZE);
+
+       val->intval = (val->intval * 10) / 1048576;
+
+       return 0;
+}
+
+static enum power_supply_property da9150_fg_props[] = {
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_VOLTAGE_AVG,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_TEMP,
+};
+
+static int da9150_fg_get_prop(struct power_supply *psy,
+                             enum power_supply_property psp,
+                             union power_supply_propval *val)
+{
+       struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent);
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CAPACITY:
+               ret = da9150_fg_capacity(fg, val);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               ret = da9150_fg_current_avg(fg, val);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               ret = da9150_fg_voltage_avg(fg, val);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               ret = da9150_fg_charge_full(fg, val);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               ret = da9150_fg_temp(fg, val);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/* Repeated SOC check */
+static bool da9150_fg_soc_changed(struct da9150_fg *fg)
+{
+       union power_supply_propval val;
+
+       da9150_fg_capacity(fg, &val);
+       if (val.intval != fg->soc) {
+               fg->soc = val.intval;
+               return true;
+       }
+
+       return false;
+}
+
+static void da9150_fg_work(struct work_struct *work)
+{
+       struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work);
+
+       /* Report if SOC has changed */
+       if (da9150_fg_soc_changed(fg))
+               power_supply_changed(fg->battery);
+
+       schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval));
+}
+
+/* SOC level event configuration */
+static void da9150_fg_soc_event_config(struct da9150_fg *fg)
+{
+       int soc;
+
+       soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
+                                      DA9150_QIF_SOC_PCT_SIZE);
+
+       if (soc > fg->warn_soc) {
+               /* If SOC > warn level, set discharge warn level event */
+               da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
+                                         DA9150_QIF_DISCHARGE_LIMIT_SIZE,
+                                         fg->warn_soc + 1);
+       } else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) {
+               /*
+                * If SOC <= warn level, set discharge crit level event,
+                * and set charge warn level event.
+                */
+               da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
+                                         DA9150_QIF_DISCHARGE_LIMIT_SIZE,
+                                         fg->crit_soc + 1);
+
+               da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
+                                         DA9150_QIF_CHARGE_LIMIT_SIZE,
+                                         fg->warn_soc);
+       } else if (soc <= fg->crit_soc) {
+               /* If SOC <= crit level, set charge crit level event */
+               da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
+                                         DA9150_QIF_CHARGE_LIMIT_SIZE,
+                                         fg->crit_soc);
+       }
+}
+
+static irqreturn_t da9150_fg_irq(int irq, void *data)
+{
+       struct da9150_fg *fg = data;
+       u32 e_fg_status;
+
+       /* Read FG IRQ status info */
+       e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS,
+                                         DA9150_QIF_E_FG_STATUS_SIZE);
+
+       /* Handle warning/critical threhold events */
+       if (e_fg_status & DA9150_FG_IRQ_SOC_MASK)
+               da9150_fg_soc_event_config(fg);
+
+       /* Clear any FG IRQs */
+       da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS,
+                            DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status);
+
+       return IRQ_HANDLED;
+}
+
+static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev)
+{
+       struct device_node *fg_node = dev->of_node;
+       struct da9150_fg_pdata *pdata;
+
+       pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       of_property_read_u32(fg_node, "dlg,update-interval",
+                            &pdata->update_interval);
+       of_property_read_u8(fg_node, "dlg,warn-soc-level",
+                           &pdata->warn_soc_lvl);
+       of_property_read_u8(fg_node, "dlg,crit-soc-level",
+                           &pdata->crit_soc_lvl);
+
+       return pdata;
+}
+
+static const struct power_supply_desc fg_desc = {
+       .name           = "da9150-fg",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = da9150_fg_props,
+       .num_properties = ARRAY_SIZE(da9150_fg_props),
+       .get_property   = da9150_fg_get_prop,
+};
+
+static int da9150_fg_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+       struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev);
+       struct da9150_fg *fg;
+       int ver, irq, ret = 0;
+
+       fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
+       if (fg == NULL)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, fg);
+       fg->da9150 = da9150;
+       fg->dev = dev;
+
+       mutex_init(&fg->io_lock);
+
+       /* Enable QIF */
+       da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK,
+                       DA9150_FG_QIF_EN_MASK);
+
+       fg->battery = devm_power_supply_register(dev, &fg_desc, NULL);
+       if (IS_ERR(fg->battery)) {
+               ret = PTR_ERR(fg->battery);
+               return ret;
+       }
+
+       ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER,
+                                 DA9150_QIF_FW_MAIN_VER_SIZE);
+       dev_info(dev, "Version: 0x%x\n", ver);
+
+       /* Handle DT data if provided */
+       if (dev->of_node) {
+               fg_pdata = da9150_fg_dt_pdata(dev);
+               dev->platform_data = fg_pdata;
+       }
+
+       /* Handle any pdata provided */
+       if (fg_pdata) {
+               fg->interval = fg_pdata->update_interval;
+
+               if (fg_pdata->warn_soc_lvl > 100)
+                       dev_warn(dev, "Invalid SOC warning level provided, Ignoring");
+               else
+                       fg->warn_soc = fg_pdata->warn_soc_lvl;
+
+               if ((fg_pdata->crit_soc_lvl > 100) ||
+                   (fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl))
+                       dev_warn(dev, "Invalid SOC critical level provided, Ignoring");
+               else
+                       fg->crit_soc = fg_pdata->crit_soc_lvl;
+
+
+       }
+
+       /* Configure initial SOC level events */
+       da9150_fg_soc_event_config(fg);
+
+       /*
+        * If an interval period has been provided then setup repeating
+        * work for reporting data updates.
+        */
+       if (fg->interval) {
+               INIT_DELAYED_WORK(&fg->work, da9150_fg_work);
+               schedule_delayed_work(&fg->work,
+                                     msecs_to_jiffies(fg->interval));
+       }
+
+       /* Register IRQ */
+       irq = platform_get_irq_byname(pdev, "FG");
+       if (irq < 0) {
+               dev_err(dev, "Failed to get IRQ FG: %d\n", irq);
+               ret = irq;
+               goto irq_fail;
+       }
+
+       ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq,
+                                       IRQF_ONESHOT, "FG", fg);
+       if (ret) {
+               dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+               goto irq_fail;
+       }
+
+       return 0;
+
+irq_fail:
+       if (fg->interval)
+               cancel_delayed_work(&fg->work);
+
+       return ret;
+}
+
+static int da9150_fg_remove(struct platform_device *pdev)
+{
+       struct da9150_fg *fg = platform_get_drvdata(pdev);
+
+       if (fg->interval)
+               cancel_delayed_work(&fg->work);
+
+       return 0;
+}
+
+static int da9150_fg_resume(struct platform_device *pdev)
+{
+       struct da9150_fg *fg = platform_get_drvdata(pdev);
+
+       /*
+        * Trigger SOC check to happen now so as to indicate any value change
+        * since last check before suspend.
+        */
+       if (fg->interval)
+               flush_delayed_work(&fg->work);
+
+       return 0;
+}
+
+static struct platform_driver da9150_fg_driver = {
+       .driver = {
+               .name = "da9150-fuel-gauge",
+       },
+       .probe = da9150_fg_probe,
+       .remove = da9150_fg_remove,
+       .resume = da9150_fg_resume,
+};
+
+module_platform_driver(da9150_fg_driver);
+
+MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/mfd/atmel-flexcom.h b/include/dt-bindings/mfd/atmel-flexcom.h
new file mode 100644 (file)
index 0000000..a266fe4
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This header provides macros for Atmel Flexcom DT bindings.
+ *
+ * Copyright (C) 2015 Cyrille Pitchen <cyrille.pitchen@atmel.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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DT_BINDINGS_ATMEL_FLEXCOM_H__
+#define __DT_BINDINGS_ATMEL_FLEXCOM_H__
+
+#define ATMEL_FLEXCOM_MODE_USART       1
+#define ATMEL_FLEXCOM_MODE_SPI         2
+#define ATMEL_FLEXCOM_MODE_TWI         3
+
+#endif /* __DT_BINDINGS_ATMEL_FLEXCOM_H__ */
index 8fcad63fab5508a56b0a32e55acba6da68c52155..d409ceb2231ec1908842416a9de1ddb62bef2709 100644 (file)
@@ -21,6 +21,7 @@ enum {
        CHIP_INVALID = 0,
        CHIP_PM800,
        CHIP_PM805,
+       CHIP_PM860,
        CHIP_MAX,
 };
 
index c7c11c900196c59f22db80e7a3c202b2effcfa47..cd7e78eae0065e20fde8aed9e21e755fd5baf871 100644 (file)
 #define ARIZONA_CLOCK_CONTROL                    0xF00
 #define ARIZONA_ANC_SRC                          0xF01
 #define ARIZONA_DSP_STATUS                       0xF02
+#define ARIZONA_ANC_COEFF_START                  0xF08
+#define ARIZONA_ANC_COEFF_END                    0xF12
+#define ARIZONA_FCL_FILTER_CONTROL               0xF15
+#define ARIZONA_FCL_ADC_REFORMATTER_CONTROL      0xF17
+#define ARIZONA_FCL_COEFF_START                  0xF18
+#define ARIZONA_FCL_COEFF_END                    0xF69
+#define ARIZONA_FCR_FILTER_CONTROL               0xF70
+#define ARIZONA_FCR_ADC_REFORMATTER_CONTROL      0xF72
+#define ARIZONA_FCR_COEFF_START                  0xF73
+#define ARIZONA_FCR_COEFF_END                    0xFC4
 #define ARIZONA_DSP1_CONTROL_1                   0x1100
 #define ARIZONA_DSP1_CLOCKING_1                  0x1101
 #define ARIZONA_DSP1_STATUS_1                    0x1104
 #define ARIZONA_ISRC3_NOTCH_ENA_SHIFT                 0  /* ISRC3_NOTCH_ENA */
 #define ARIZONA_ISRC3_NOTCH_ENA_WIDTH                 1  /* ISRC3_NOTCH_ENA */
 
+/*
+ * R3840 (0xF00) - Clock Control
+ */
+#define ARIZONA_EXT_NG_SEL_CLR                   0x0080  /* EXT_NG_SEL_CLR */
+#define ARIZONA_EXT_NG_SEL_CLR_MASK              0x0080  /* EXT_NG_SEL_CLR */
+#define ARIZONA_EXT_NG_SEL_CLR_SHIFT                  7  /* EXT_NG_SEL_CLR */
+#define ARIZONA_EXT_NG_SEL_CLR_WIDTH                  1  /* EXT_NG_SEL_CLR */
+#define ARIZONA_EXT_NG_SEL_SET                   0x0040  /* EXT_NG_SEL_SET */
+#define ARIZONA_EXT_NG_SEL_SET_MASK              0x0040  /* EXT_NG_SEL_SET */
+#define ARIZONA_EXT_NG_SEL_SET_SHIFT                  6  /* EXT_NG_SEL_SET */
+#define ARIZONA_EXT_NG_SEL_SET_WIDTH                  1  /* EXT_NG_SEL_SET */
+#define ARIZONA_CLK_R_ENA_CLR                    0x0020  /* CLK_R_ENA_CLR */
+#define ARIZONA_CLK_R_ENA_CLR_MASK               0x0020  /* CLK_R_ENA_CLR */
+#define ARIZONA_CLK_R_ENA_CLR_SHIFT                   5  /* CLK_R_ENA_CLR */
+#define ARIZONA_CLK_R_ENA_CLR_WIDTH                   1  /* CLK_R_ENA_CLR */
+#define ARIZONA_CLK_R_ENA_SET                    0x0010  /* CLK_R_ENA_SET */
+#define ARIZONA_CLK_R_ENA_SET_MASK               0x0010  /* CLK_R_ENA_SET */
+#define ARIZONA_CLK_R_ENA_SET_SHIFT                   4  /* CLK_R_ENA_SET */
+#define ARIZONA_CLK_R_ENA_SET_WIDTH                   1  /* CLK_R_ENA_SET */
+#define ARIZONA_CLK_NG_ENA_CLR                   0x0008  /* CLK_NG_ENA_CLR */
+#define ARIZONA_CLK_NG_ENA_CLR_MASK              0x0008  /* CLK_NG_ENA_CLR */
+#define ARIZONA_CLK_NG_ENA_CLR_SHIFT                  3  /* CLK_NG_ENA_CLR */
+#define ARIZONA_CLK_NG_ENA_CLR_WIDTH                  1  /* CLK_NG_ENA_CLR */
+#define ARIZONA_CLK_NG_ENA_SET                   0x0004  /* CLK_NG_ENA_SET */
+#define ARIZONA_CLK_NG_ENA_SET_MASK              0x0004  /* CLK_NG_ENA_SET */
+#define ARIZONA_CLK_NG_ENA_SET_SHIFT                  2  /* CLK_NG_ENA_SET */
+#define ARIZONA_CLK_NG_ENA_SET_WIDTH                  1  /* CLK_NG_ENA_SET */
+#define ARIZONA_CLK_L_ENA_CLR                    0x0002  /* CLK_L_ENA_CLR */
+#define ARIZONA_CLK_L_ENA_CLR_MASK               0x0002  /* CLK_L_ENA_CLR */
+#define ARIZONA_CLK_L_ENA_CLR_SHIFT                   1  /* CLK_L_ENA_CLR */
+#define ARIZONA_CLK_L_ENA_CLR_WIDTH                   1  /* CLK_L_ENA_CLR */
+#define ARIZONA_CLK_L_ENA_SET                    0x0001  /* CLK_L_ENA_SET */
+#define ARIZONA_CLK_L_ENA_SET_MASK               0x0001  /* CLK_L_ENA_SET */
+#define ARIZONA_CLK_L_ENA_SET_SHIFT                   0  /* CLK_L_ENA_SET */
+#define ARIZONA_CLK_L_ENA_SET_WIDTH                   1  /* CLK_L_ENA_SET */
+
+/*
+ * R3841 (0xF01) - ANC SRC
+ */
+#define ARIZONA_IN_RXANCR_SEL_MASK               0x0070  /* IN_RXANCR_SEL - [4:6] */
+#define ARIZONA_IN_RXANCR_SEL_SHIFT                   4  /* IN_RXANCR_SEL - [4:6] */
+#define ARIZONA_IN_RXANCR_SEL_WIDTH                   3  /* IN_RXANCR_SEL - [4:6] */
+#define ARIZONA_IN_RXANCL_SEL_MASK               0x0007  /* IN_RXANCL_SEL - [0:2] */
+#define ARIZONA_IN_RXANCL_SEL_SHIFT                   0  /* IN_RXANCL_SEL - [0:2] */
+#define ARIZONA_IN_RXANCL_SEL_WIDTH                   3  /* IN_RXANCL_SEL - [0:2] */
+
+/*
+ * R3863 (0xF17) - FCL ADC Reformatter Control
+ */
+#define ARIZONA_FCL_MIC_MODE_SEL                 0x000C  /* FCL_MIC_MODE_SEL - [2:3] */
+#define ARIZONA_FCL_MIC_MODE_SEL_SHIFT                2  /* FCL_MIC_MODE_SEL - [2:3] */
+#define ARIZONA_FCL_MIC_MODE_SEL_WIDTH                2  /* FCL_MIC_MODE_SEL - [2:3] */
+
+/*
+ * R3954 (0xF72) - FCR ADC Reformatter Control
+ */
+#define ARIZONA_FCR_MIC_MODE_SEL                 0x000C  /* FCR_MIC_MODE_SEL - [2:3] */
+#define ARIZONA_FCR_MIC_MODE_SEL_SHIFT                2  /* FCR_MIC_MODE_SEL - [2:3] */
+#define ARIZONA_FCR_MIC_MODE_SEL_WIDTH                2  /* FCR_MIC_MODE_SEL - [2:3] */
+
 /*
  * R4352 (0x1100) - DSP1 Control 1
  */
index a76bc100bf974d667f64fec5dc4619297a8d71b7..27dac3ff18b949a0c32d508a3830f676992fc14c 100644 (file)
 
 struct irq_domain;
 
+/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
+struct mfd_cell_acpi_match {
+       const char                      *pnpid;
+       const unsigned long long        adr;
+};
+
 /*
  * This struct describes the MFD part ("cell").
  * After registration the copy of this structure will become the platform data
@@ -44,8 +50,8 @@ struct mfd_cell {
         */
        const char              *of_compatible;
 
-       /* Matches ACPI PNP id, either _HID or _CID */
-       const char              *acpi_pnpid;
+       /* Matches ACPI */
+       const struct mfd_cell_acpi_match        *acpi_match;
 
        /*
         * These resources can be specified relative to the parent device.
index c4dd3a8add21b94cc526843c117734c506cc5233..5010f978725c50c210128b50ba6b6934ec33f244 100644 (file)
@@ -65,6 +65,9 @@
 #define DA9052_GPIO_2_3_REG            22
 #define DA9052_GPIO_4_5_REG            23
 #define DA9052_GPIO_6_7_REG            24
+#define DA9052_GPIO_8_9_REG            25
+#define DA9052_GPIO_10_11_REG          26
+#define DA9052_GPIO_12_13_REG          27
 #define DA9052_GPIO_14_15_REG          28
 
 /* POWER SEQUENCER CONTROL REGISTERS */
index 76e668933a774624a6b28ec7aefe2983d27dfa0f..1bf50caeb9fa48427b2e2f5e3f1f0da7bbcddf5c 100644 (file)
@@ -15,6 +15,7 @@
 #define __DA9150_CORE_H
 
 #include <linux/device.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/regmap.h>
 
 #define DA9150_IRQ_GPADC       19
 #define DA9150_IRQ_WKUP                20
 
+/* I2C sub-device address */
+#define DA9150_QIF_I2C_ADDR_LSB                0x5
+
+struct da9150_fg_pdata {
+       u32 update_interval;    /* msecs */
+       u8 warn_soc_lvl;        /* % value */
+       u8 crit_soc_lvl;        /* % value */
+};
+
 struct da9150_pdata {
        int irq_base;
+       struct da9150_fg_pdata *fg_pdata;
 };
 
 struct da9150 {
        struct device *dev;
        struct regmap *regmap;
+       struct i2c_client *core_qif;
+
        struct regmap_irq_chip_data *regmap_irq_data;
        int irq;
        int irq_base;
 };
 
-/* Device I/O */
+/* Device I/O - Query Interface for FG and standard register access */
+void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf);
+void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
+
 u8 da9150_reg_read(struct da9150 *da9150, u16 reg);
 void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val);
 void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val);
 
 void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf);
 void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf);
+
 #endif /* __DA9150_CORE_H */
diff --git a/include/linux/mfd/intel_bxtwc.h b/include/linux/mfd/intel_bxtwc.h
new file mode 100644 (file)
index 0000000..1a0ee9d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * intel_bxtwc.h - Header file for Intel Broxton Whiskey Cove PMIC
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/mfd/intel_soc_pmic.h>
+
+#ifndef __INTEL_BXTWC_H__
+#define __INTEL_BXTWC_H__
+
+/* BXT WC devices */
+#define BXTWC_DEVICE1_ADDR             0x4E
+#define BXTWC_DEVICE2_ADDR             0x4F
+#define BXTWC_DEVICE3_ADDR             0x5E
+
+/* device1 Registers */
+#define BXTWC_CHIPID                   0x4E00
+#define BXTWC_CHIPVER                  0x4E01
+
+#define BXTWC_SCHGRIRQ0_ADDR           0x5E1A
+#define BXTWC_CHGRCTRL0_ADDR           0x5E16
+#define BXTWC_CHGRCTRL1_ADDR           0x5E17
+#define BXTWC_CHGRCTRL2_ADDR           0x5E18
+#define BXTWC_CHGRSTATUS_ADDR          0x5E19
+#define BXTWC_THRMBATZONE_ADDR         0x4F22
+
+#define BXTWC_USBPATH_ADDR             0x5E19
+#define BXTWC_USBPHYCTRL_ADDR          0x5E07
+#define BXTWC_USBIDCTRL_ADDR           0x5E05
+#define BXTWC_USBIDEN_MASK             0x01
+#define BXTWC_USBIDSTAT_ADDR           0x00FF
+#define BXTWC_USBSRCDETSTATUS_ADDR     0x5E29
+
+#define BXTWC_DBGUSBBC1_ADDR           0x5FE0
+#define BXTWC_DBGUSBBC2_ADDR           0x5FE1
+#define BXTWC_DBGUSBBCSTAT_ADDR                0x5FE2
+
+#define BXTWC_WAKESRC_ADDR             0x4E22
+#define BXTWC_WAKESRC2_ADDR            0x4EE5
+#define BXTWC_CHRTTADDR_ADDR           0x5E22
+#define BXTWC_CHRTTDATA_ADDR           0x5E23
+
+#define BXTWC_STHRMIRQ0_ADDR           0x4F19
+#define WC_MTHRMIRQ1_ADDR              0x4E12
+#define WC_STHRMIRQ1_ADDR              0x4F1A
+#define WC_STHRMIRQ2_ADDR              0x4F1B
+
+#define BXTWC_THRMZN0H_ADDR            0x4F44
+#define BXTWC_THRMZN0L_ADDR            0x4F45
+#define BXTWC_THRMZN1H_ADDR            0x4F46
+#define BXTWC_THRMZN1L_ADDR            0x4F47
+#define BXTWC_THRMZN2H_ADDR            0x4F48
+#define BXTWC_THRMZN2L_ADDR            0x4F49
+#define BXTWC_THRMZN3H_ADDR            0x4F4A
+#define BXTWC_THRMZN3L_ADDR            0x4F4B
+#define BXTWC_THRMZN4H_ADDR            0x4F4C
+#define BXTWC_THRMZN4L_ADDR            0x4F4D
+
+#endif
index abcbfcf32d10a41dbea56068a328ad42a3f525a4..cf619dbeace285ee0ad2b9fc3b5e479604e42174 100644 (file)
@@ -25,6 +25,8 @@ struct intel_soc_pmic {
        int irq;
        struct regmap *regmap;
        struct regmap_irq_chip_data *irq_chip_data;
+       struct regmap_irq_chip_data *irq_chip_data_level2;
+       struct device *dev;
 };
 
 #endif /* __INTEL_SOC_PMIC_H__ */
index ff843e7ca23ddf8fc17e6103986c348763290a48..7eb7cbac0a9a39b2d0906816ff6391cc260ab69a 100644 (file)
 #define   FORCE_ASPM_NO_ASPM           0x00
 #define PM_CLK_FORCE_CTL               0xFE58
 #define FUNC_FORCE_CTL                 0xFE59
+#define   FUNC_FORCE_UPME_XMT_DBG      0x02
 #define PERST_GLITCH_WIDTH             0xFE5C
 #define CHANGE_LINK_STATE              0xFE5B
 #define RESET_LOAD_REG                 0xFE5E
 #define PHY_RCR1                       0x02
 #define   PHY_RCR1_ADP_TIME_4          0x0400
 #define   PHY_RCR1_VCO_COARSE          0x001F
+#define   PHY_RCR1_INIT_27S            0x0A1F
 #define PHY_SSCCR2                     0x02
 #define   PHY_SSCCR2_PLL_NCODE         0x0A00
 #define   PHY_SSCCR2_TIME0             0x001C
 #define   PHY_RCR2_FREQSEL_12          0x0040
 #define   PHY_RCR2_CDR_SC_12P          0x0010
 #define   PHY_RCR2_CALIB_LATE          0x0002
+#define   PHY_RCR2_INIT_27S            0xC152
 #define PHY_SSCCR3                     0x03
 #define   PHY_SSCCR3_STEP_IN           0x2740
 #define   PHY_SSCCR3_CHECK_DELAY       0x0008
 #define   PHY_ANA1A_RXT_BIST           0x0500
 #define   PHY_ANA1A_TXR_BIST           0x0040
 #define   PHY_ANA1A_REV                        0x0006
+#define   PHY_FLD0_INIT_27S            0x2546
 #define PHY_FLD1                       0x1B
 #define PHY_FLD2                       0x1C
 #define PHY_FLD3                       0x1D
 #define   PHY_FLD3_TIMER_4             0x0800
 #define   PHY_FLD3_TIMER_6             0x0020
 #define   PHY_FLD3_RXDELINK            0x0004
+#define   PHY_FLD3_INIT_27S            0x0004
 #define PHY_ANA1D                      0x1D
 #define   PHY_ANA1D_DEBUG_ADDR         0x0004
 #define _PHY_FLD0                      0x1D
 #define   PHY_FLD4_BER_COUNT           0x00E0
 #define   PHY_FLD4_BER_TIMER           0x000A
 #define   PHY_FLD4_BER_CHK_EN          0x0001
+#define   PHY_FLD4_INIT_27S            0x5C7F
 #define PHY_DIG1E                      0x1E
 #define   PHY_DIG1E_REV                        0x4000
 #define   PHY_DIG1E_D0_X_D1            0x1000
index 75115384f3fcf7bdf2965317ca94baa372ad0e55..a0609863939912d4c5f9b3c47acc66c8ac2ee46f 100644 (file)
@@ -132,6 +132,10 @@ struct sec_platform_data {
        int                             buck2_init;
        int                             buck3_init;
        int                             buck4_init;
+       /* Whether or not manually set PWRHOLD to low during shutdown. */
+       bool                            manual_poweroff;
+       /* Disable the WRSTBI (buck voltage warm reset) when probing? */
+       bool                            disable_wrstbi;
 };
 
 /**
index 7981a9d77d3f853eed2ff36492aaa2591cde8a82..b288965e8101dc38f8a4cf4f13f55c0ba2dfbb7a 100644 (file)
@@ -179,6 +179,7 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1)
 #define S2MPS11_RAMP_DELAY     25000           /* uV/us */
 
+#define S2MPS11_CTRL1_PWRHOLD_MASK     BIT(4)
 
 #define S2MPS11_BUCK2_RAMP_SHIFT       6
 #define S2MPS11_BUCK34_RAMP_SHIFT      4
index b1fd675fa36f36a7ec5b68d2ba9d76684ad3bcfd..239e977ba45d97a83391092ed5065f1c0902188f 100644 (file)
@@ -184,5 +184,6 @@ enum s2mps13_regulators {
  * Let's assume that default value will be set.
  */
 #define S2MPS13_BUCK_RAMP_DELAY                12500
+#define S2MPS13_REG_WRSTBI_MASK                BIT(5)
 
 #endif /*  __LINUX_MFD_S2MPS13_H */