Merge remote-tracking branch 'mfd/for-mfd-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 01:27:26 +0000 (12:27 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 01:27:26 +0000 (12:27 +1100)
74 files changed:
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/extcon/extcon-arizona.c
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_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/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/platform/x86/Kconfig
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/da9150-fg.c [new file with mode: 0644]
drivers/regulator/tps6105x-regulator.c
include/dt-bindings/mfd/arizona.h
include/dt-bindings/mfd/atmel-flexcom.h [new file with mode: 0644]
include/linux/mfd/88pm80x.h
include/linux/mfd/arizona/pdata.h
include/linux/mfd/arizona/registers.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
include/linux/mfd/tps6105x.h

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 a8fee60..18be0cb 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 1777916..136e0c2 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 d0588ea..fd4dca7 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 90eaef3..890f0b0 100644 (file)
@@ -19,6 +19,9 @@ Optional properties:
   connected to the ground so the PMIC must manually set PWRHOLD bit in CTRL1
   register to turn off the power. Usually the ACOKB is pulled up to VBATT so
   when PWRHOLD pin goes low, the rising ACOKB will trigger power off.
+- 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
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 accfbfa..5d9e7fd 100644 (file)
@@ -7132,7 +7132,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
@@ -11545,6 +11544,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 4b9f09c..4479781 100644 (file)
 #define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
 #define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
 
+#define ARIZONA_TST_CAP_DEFAULT 0x3
+#define ARIZONA_TST_CAP_CLAMP   0x1
+
 #define ARIZONA_HPDET_MAX 10000
 
 #define HPDET_DEBOUNCE 500
 #define DEFAULT_MICD_TIMEOUT 2000
 
+#define QUICK_HEADPHONE_MAX_OHM 3
+#define MICROPHONE_MIN_OHM      1257
+#define MICROPHONE_MAX_OHM      30000
+
 #define MICD_DBTIME_TWO_READINGS 2
 #define MICD_DBTIME_FOUR_READINGS 4
 
@@ -117,12 +124,15 @@ static const struct arizona_micd_range micd_default_ranges[] = {
        { .max = 430, .key = BTN_5 },
 };
 
+/* The number of levels in arizona_micd_levels valid for button thresholds */
+#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
+
 static const int arizona_micd_levels[] = {
        3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
        49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
        105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
        270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
-       1257,
+       1257, 30000,
 };
 
 static const unsigned int arizona_cable[] = {
@@ -140,6 +150,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
 {
        struct arizona *arizona = info->arizona;
        unsigned int mask = 0, val = 0;
+       unsigned int cap_sel = 0;
        int ret;
 
        switch (arizona->type) {
@@ -147,10 +158,21 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
        case WM8280:
                mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
                       ARIZONA_HP1L_SHRTI;
-               if (clamp)
+               if (clamp) {
                        val = ARIZONA_HP1L_SHRTO;
-               else
+                       cap_sel = ARIZONA_TST_CAP_CLAMP;
+               } else {
                        val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
+                       cap_sel = ARIZONA_TST_CAP_DEFAULT;
+               }
+
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HP_TEST_CTRL_1,
+                                        ARIZONA_HP1_TST_CAP_SEL_MASK,
+                                        cap_sel);
+               if (ret != 0)
+                       dev_warn(arizona->dev,
+                                "Failed to set TST_CAP_SEL: %d\n", ret);
                break;
        default:
                mask = ARIZONA_RMV_SHRT_HP1L;
@@ -270,6 +292,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
        struct arizona *arizona = info->arizona;
        bool change;
        int ret;
+       unsigned int mode;
 
        /* Microphone detection can't use idle mode */
        pm_runtime_get(info->dev);
@@ -295,9 +318,14 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
                regmap_write(arizona->regmap, 0x80, 0x0);
        }
 
+       if (info->detecting && arizona->pdata.micd_software_compare)
+               mode = ARIZONA_ACCDET_MODE_ADC;
+       else
+               mode = ARIZONA_ACCDET_MODE_MIC;
+
        regmap_update_bits(arizona->regmap,
                           ARIZONA_ACCESSORY_DETECT_MODE_1,
-                          ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
+                          ARIZONA_ACCDET_MODE_MASK, mode);
 
        arizona_extcon_pulse_micbias(info);
 
@@ -804,6 +832,37 @@ static void arizona_micd_detect(struct work_struct *work)
                return;
        }
 
+       if (info->detecting && arizona->pdata.micd_software_compare) {
+               /* Must disable MICD before we read the ADCVAL */
+               regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+                                  ARIZONA_MICD_ENA, 0);
+               ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
+               if (ret != 0) {
+                       dev_err(arizona->dev,
+                               "Failed to read MICDET_ADCVAL: %d\n",
+                               ret);
+                       mutex_unlock(&info->lock);
+                       return;
+               }
+
+               dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
+
+               val &= ARIZONA_MICDET_ADCVAL_MASK;
+               if (val < ARRAY_SIZE(arizona_micd_levels))
+                       val = arizona_micd_levels[val];
+               else
+                       val = INT_MAX;
+
+               if (val <= QUICK_HEADPHONE_MAX_OHM)
+                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
+               else if (val <= MICROPHONE_MIN_OHM)
+                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
+               else if (val <= MICROPHONE_MAX_OHM)
+                       val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
+               else
+                       val = ARIZONA_MICD_LVL_8;
+       }
+
        for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
                ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
                if (ret != 0) {
@@ -932,10 +991,17 @@ static void arizona_micd_detect(struct work_struct *work)
        }
 
 handled:
-       if (info->detecting)
+       if (info->detecting) {
+               if (arizona->pdata.micd_software_compare)
+                       regmap_update_bits(arizona->regmap,
+                                          ARIZONA_MIC_DETECT_1,
+                                          ARIZONA_MICD_ENA,
+                                          ARIZONA_MICD_ENA);
+
                queue_delayed_work(system_power_efficient_wq,
                                   &info->micd_timeout_work,
                                   msecs_to_jiffies(info->micd_timeout));
+       }
 
        pm_runtime_mark_last_busy(info->dev);
        mutex_unlock(&info->lock);
@@ -991,12 +1057,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 
        mutex_lock(&info->lock);
 
-       if (arizona->pdata.jd_gpio5) {
+       if (info->micd_clamp) {
                mask = ARIZONA_MICD_CLAMP_STS;
-               if (arizona->pdata.jd_invert)
-                       present = ARIZONA_MICD_CLAMP_STS;
-               else
-                       present = 0;
+               present = 0;
        } else {
                mask = ARIZONA_JD1_STS;
                if (arizona->pdata.jd_invert)
@@ -1055,9 +1118,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
                                           msecs_to_jiffies(HPDET_DEBOUNCE));
                }
 
-               regmap_update_bits(arizona->regmap,
-                                  ARIZONA_JACK_DETECT_DEBOUNCE,
-                                  ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB, 0);
+               if (info->micd_clamp || !arizona->pdata.jd_invert)
+                       regmap_update_bits(arizona->regmap,
+                                          ARIZONA_JACK_DETECT_DEBOUNCE,
+                                          ARIZONA_MICD_CLAMP_DB |
+                                          ARIZONA_JD1_DB, 0);
        } else {
                dev_dbg(arizona->dev, "Detected jack removal\n");
 
@@ -1259,6 +1324,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
        }
 
+       if (arizona->pdata.gpsw > 0)
+               regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
+                               ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
+
        if (arizona->pdata.micd_pol_gpio > 0) {
                if (info->micd_modes[0].gpio)
                        mode = GPIOF_OUT_INIT_HIGH;
@@ -1335,7 +1404,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                break;
        }
 
-       BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
+       BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
+                    ARIZONA_NUM_MICD_BUTTON_LEVELS);
 
        if (arizona->pdata.num_micd_ranges) {
                info->micd_ranges = pdata->micd_ranges;
@@ -1368,11 +1438,11 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 
        /* Set up all the buttons the user specified */
        for (i = 0; i < info->num_micd_ranges; i++) {
-               for (j = 0; j < ARRAY_SIZE(arizona_micd_levels); j++)
+               for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
                        if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
                                break;
 
-               if (j == ARRAY_SIZE(arizona_micd_levels)) {
+               if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
                        dev_err(arizona->dev, "Unsupported MICD level %d\n",
                                info->micd_ranges[i].max);
                        ret = -EINVAL;
@@ -1436,7 +1506,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        pm_runtime_idle(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
 
-       if (arizona->pdata.jd_gpio5) {
+       if (info->micd_clamp) {
                jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
                jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
        } else {
@@ -1541,7 +1611,7 @@ static int arizona_extcon_remove(struct platform_device *pdev)
                           ARIZONA_MICD_CLAMP_CONTROL,
                           ARIZONA_MICD_CLAMP_MODE_MASK, 0);
 
-       if (arizona->pdata.jd_gpio5) {
+       if (info->micd_clamp) {
                jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
                jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
        } else {
index 5e72f65..63445ea 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 99d6367..4d92df6 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 a59e3fc..a8b76b8 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 44cfdbb..d474732 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 cea1b40..4e3afd1 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 2cac4f4..3d425e9 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 1e845f6..8cffb1c 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 3fff6b5..06c2058 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 3f576b7..9842199 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 da2af5b..320aaef 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 d06e4b4..56a4664 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 ef7fe2a..37e4426 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 46e3840..c0bf68a 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 0288700..2697ffb 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 b5de8a6..0f5e2c2 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 f80d947..a9ad024 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 94b9bbd..195fdcf 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 95b2ff8..f9ded45 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 1bd5b04..0c6ff72 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 0d92d73..b6fd904 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 9236dff..5bfdfcc 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 fdf4d5c..001a7d7 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)
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 463f4ea..05b9245 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 643f375..5abcbb2 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 c5a9a08..b514f3c 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 d3cfa9c..156ed6f 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 498286c..71d43ed 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 6afc9fa..207a3bd 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 d60f916..2b95485 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 373e253..b95beec 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 ce012d7..ff296a4 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 ace4538..9ed9dc8 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 eb2d586..40f8bb1 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 a66540a..f3820d0 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 ce48842..931d1ae 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 d206a3e..989076d 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 91077ef..c646784 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 e971af8..8222e37 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 5de95c2..51c5495 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/mutex.h>
+#include <linux/regmap.h>
 #include <linux/gpio.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6105x.h>
 
-int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value)
-{
-       int ret;
-
-       ret = mutex_lock_interruptible(&tps6105x->lock);
-       if (ret)
-               return ret;
-       ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value);
-       mutex_unlock(&tps6105x->lock);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL(tps6105x_set);
-
-int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf)
-{
-       int ret;
-
-       ret = mutex_lock_interruptible(&tps6105x->lock);
-       if (ret)
-               return ret;
-       ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
-       mutex_unlock(&tps6105x->lock);
-       if (ret < 0)
-               return ret;
-
-       *buf = ret;
-       return 0;
-}
-EXPORT_SYMBOL(tps6105x_get);
-
-/*
- * Masks off the bits in the mask and sets the bits in the bitvalues
- * parameter in one atomic operation
- */
-int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
-                         u8 bitmask, u8 bitvalues)
-{
-       int ret;
-       u8 regval;
-
-       ret = mutex_lock_interruptible(&tps6105x->lock);
-       if (ret)
-               return ret;
-       ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
-       if (ret < 0)
-               goto fail;
-       regval = ret;
-       regval = (~bitmask & regval) | (bitmask & bitvalues);
-       ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval);
-fail:
-       mutex_unlock(&tps6105x->lock);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL(tps6105x_mask_and_set);
+static struct regmap_config tps6105x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TPS6105X_REG_3,
+};
 
 static int tps6105x_startup(struct tps6105x *tps6105x)
 {
        int ret;
-       u8 regval;
+       unsigned int regval;
 
-       ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+       ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
        if (ret)
                return ret;
        switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
@@ -119,37 +64,59 @@ 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)
                return -ENOMEM;
 
+       tps6105x->regmap = devm_regmap_init_i2c(client, &tps6105x_regmap_config);
+       if (IS_ERR(tps6105x->regmap))
+               return PTR_ERR(tps6105x->regmap);
+
        i2c_set_clientdata(client, tps6105x);
        tps6105x->client = client;
-       pdata = dev_get_platdata(&client->dev);
        tps6105x->pdata = pdata;
-       mutex_init(&tps6105x->lock);
 
        ret = tps6105x_startup(tps6105x);
        if (ret) {
@@ -157,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)
@@ -198,7 +160,7 @@ static int tps6105x_remove(struct i2c_client *client)
        mfd_remove_devices(&client->dev);
 
        /* Put chip in shutdown mode */
-       tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+       regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
                TPS6105X_REG0_MODE_MASK,
                TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
 
index 55add04..d32b544 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 a151ee2..08a693c 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 c4b9374..2bb2d04 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 },
@@ -1481,6 +1481,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000C04, 0xA101 },    /* R3076  - GPIO5 CTRL */
        { 0x00000C0F, 0x0400 },    /* R3087  - IRQ CTRL 1 */
        { 0x00000C10, 0x1000 },    /* R3088  - GPIO Debounce Config */
+       { 0x00000C18, 0x0000 },    /* R3096  - GP Switch 1 */
        { 0x00000C20, 0x8002 },    /* R3104  - Misc Pad Ctrl 1 */
        { 0x00000C21, 0x8001 },    /* R3105  - Misc Pad Ctrl 2 */
        { 0x00000C22, 0x0000 },    /* R3106  - Misc Pad Ctrl 3 */
@@ -1632,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 */
@@ -1811,6 +1991,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_MIC_DETECT_1:
        case ARIZONA_MIC_DETECT_2:
        case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_MIC_DETECT_4:
        case ARIZONA_MIC_DETECT_LEVEL_1:
        case ARIZONA_MIC_DETECT_LEVEL_2:
        case ARIZONA_MIC_DETECT_LEVEL_3:
@@ -1910,6 +2091,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_HP1_SHORT_CIRCUIT_CTRL:
        case ARIZONA_HP2_SHORT_CIRCUIT_CTRL:
        case ARIZONA_HP3_SHORT_CIRCUIT_CTRL:
+       case ARIZONA_HP_TEST_CTRL_1:
        case ARIZONA_AIF1_BCLK_CTRL:
        case ARIZONA_AIF1_TX_PIN_CTRL:
        case ARIZONA_AIF1_RX_PIN_CTRL:
@@ -2527,6 +2709,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_GPIO5_CTRL:
        case ARIZONA_IRQ_CTRL_1:
        case ARIZONA_GPIO_DEBOUNCE_CONFIG:
+       case ARIZONA_GP_SWITCH_1:
        case ARIZONA_MISC_PAD_CTRL_1:
        case ARIZONA_MISC_PAD_CTRL_2:
        case ARIZONA_MISC_PAD_CTRL_3:
@@ -2706,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:
@@ -2847,12 +3037,14 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
        case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
        case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_MIC_DETECT_4:
        case ARIZONA_HP_CTRL_1L:
        case ARIZONA_HP_CTRL_1R:
        case ARIZONA_HEADPHONE_DETECT_2:
        case ARIZONA_INPUT_ENABLES_STATUS:
        case ARIZONA_OUTPUT_STATUS_1:
        case ARIZONA_RAW_OUTPUT_STATUS_1:
+       case ARIZONA_HP_TEST_CTRL_1:
        case ARIZONA_SLIMBUS_RX_PORT_STATUS:
        case ARIZONA_SLIMBUS_TX_PORT_STATUS:
        case ARIZONA_INTERRUPT_STATUS_1:
index 28366a9..3e0e99e 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 e6de3cd..4c2dce7 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 c69bb70..744cb80 100644 (file)
@@ -914,6 +914,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 f8758d6..8d53f58 100644 (file)
@@ -204,6 +204,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 5752ce8..cbdf89d 100644 (file)
@@ -33,6 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_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");
index 3510b3e..ddc4f10 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/mfd/core.h>
@@ -33,7 +33,7 @@ static int tps6105x_regulator_enable(struct regulator_dev *rdev)
        int ret;
 
        /* Activate voltage mode */
-       ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+       ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
                TPS6105X_REG0_MODE_MASK,
                TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT);
        if (ret)
@@ -48,7 +48,7 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev)
        int ret;
 
        /* Set into shutdown mode */
-       ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+       ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
                TPS6105X_REG0_MODE_MASK,
                TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
        if (ret)
@@ -60,10 +60,10 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev)
 static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
 {
        struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
-       u8 regval;
+       unsigned int regval;
        int ret;
 
-       ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+       ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
        if (ret)
                return ret;
        regval &= TPS6105X_REG0_MODE_MASK;
@@ -78,10 +78,10 @@ static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
 static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
-       u8 regval;
+       unsigned int regval;
        int ret;
 
-       ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+       ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);
        if (ret)
                return ret;
 
@@ -96,7 +96,7 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
        struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
        int ret;
 
-       ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+       ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
                                    TPS6105X_REG0_VOLTAGE_MASK,
                                    selector << TPS6105X_REG0_VOLTAGE_SHIFT);
        if (ret)
index 7b2000c..c40f665 100644 (file)
 #define ARIZONA_ACCDET_MODE_MIC 0
 #define ARIZONA_ACCDET_MODE_HPL 1
 #define ARIZONA_ACCDET_MODE_HPR 2
+#define ARIZONA_ACCDET_MODE_HPM 4
+#define ARIZONA_ACCDET_MODE_ADC 7
 
 #endif
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 8fcad63..d409ceb 100644 (file)
@@ -21,6 +21,7 @@ enum {
        CHIP_INVALID = 0,
        CHIP_PM800,
        CHIP_PM805,
+       CHIP_PM860,
        CHIP_MAX,
 };
 
index 1dc3858..57b45ca 100644 (file)
@@ -124,6 +124,9 @@ struct arizona_pdata {
        /** Channel to use for headphone detection */
        unsigned int hpdet_channel;
 
+       /** Use software comparison to determine mic presence */
+       bool micd_software_compare;
+
        /** Extra debounce timeout used during initial mic detection (ms) */
        unsigned int micd_detect_debounce;
 
@@ -181,6 +184,9 @@ struct arizona_pdata {
 
        /** GPIO for primary IRQ (used for edge triggered emulation) */
        int irq_gpio;
+
+       /** General purpose switch control */
+       unsigned int gpsw;
 };
 
 #endif
index fdd70b3..cd7e78e 100644 (file)
 #define ARIZONA_HP1_SHORT_CIRCUIT_CTRL           0x4A0
 #define ARIZONA_HP2_SHORT_CIRCUIT_CTRL           0x4A1
 #define ARIZONA_HP3_SHORT_CIRCUIT_CTRL           0x4A2
+#define ARIZONA_HP_TEST_CTRL_1                   0x4A4
 #define ARIZONA_SPK_CTRL_2                       0x4B5
 #define ARIZONA_SPK_CTRL_3                       0x4B6
 #define ARIZONA_DAC_COMP_1                       0x4DC
 #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_ACCDET_SRC_MASK                  0x2000  /* ACCDET_SRC */
 #define ARIZONA_ACCDET_SRC_SHIFT                     13  /* ACCDET_SRC */
 #define ARIZONA_ACCDET_SRC_WIDTH                      1  /* ACCDET_SRC */
-#define ARIZONA_ACCDET_MODE_MASK                 0x0003  /* ACCDET_MODE - [1:0] */
-#define ARIZONA_ACCDET_MODE_SHIFT                     0  /* ACCDET_MODE - [1:0] */
-#define ARIZONA_ACCDET_MODE_WIDTH                     2  /* ACCDET_MODE - [1:0] */
+#define ARIZONA_ACCDET_MODE_MASK                 0x0007  /* ACCDET_MODE - [2:0] */
+#define ARIZONA_ACCDET_MODE_SHIFT                     0  /* ACCDET_MODE - [2:0] */
+#define ARIZONA_ACCDET_MODE_WIDTH                     3  /* ACCDET_MODE - [2:0] */
 
 /*
  * R667 (0x29B) - Headphone Detect 1
 #define ARIZONA_HP3_SC_ENA_SHIFT                     12  /* HP3_SC_ENA */
 #define ARIZONA_HP3_SC_ENA_WIDTH                      1  /* HP3_SC_ENA */
 
+/*
+ * R1188 (0x4A4) HP Test Ctrl 1
+ */
+#define ARIZONA_HP1_TST_CAP_SEL_MASK             0x0003  /* HP1_TST_CAP_SEL - [1:0] */
+#define ARIZONA_HP1_TST_CAP_SEL_SHIFT                 0  /* HP1_TST_CAP_SEL - [1:0] */
+#define ARIZONA_HP1_TST_CAP_SEL_WIDTH                 2  /* HP1_TST_CAP_SEL - [1:0] */
+
 /*
  * R1244 (0x4DC) - DAC comp 1
  */
 #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 c4dd3a8..5010f97 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 76e6689..1bf50ca 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 abcbfcf..cf619db 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 ff843e7..7eb7cba 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 7511538..a060986 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 7981a9d..b288965 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 b1fd675..239e977 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 */
index 386743d..8bc5118 100644 (file)
@@ -10,6 +10,7 @@
 #define MFD_TPS6105X_H
 
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/machine.h>
 
 /*
@@ -82,20 +83,15 @@ struct tps6105x_platform_data {
 
 /**
  * struct tps6105x - state holder for the TPS6105x drivers
- * @mutex: mutex to serialize I2C accesses
  * @i2c_client: corresponding I2C client
  * @regulator: regulator device if used in voltage mode
+ * @regmap: used for i2c communcation on accessing registers
  */
 struct tps6105x {
        struct tps6105x_platform_data *pdata;
-       struct mutex            lock;
        struct i2c_client       *client;
        struct regulator_dev    *regulator;
+       struct regmap           *regmap;
 };
 
-extern int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value);
-extern int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf);
-extern int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
-                                u8 bitmask, u8 bitvalues);
-
 #endif