]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branches 'ib-mfd-gpio-i2c-3.19', 'ib-mfd-iio-3.19' and 'ib-mfd-regulator-v3...
authorLee Jones <lee.jones@linaro.org>
Tue, 25 Nov 2014 16:18:03 +0000 (16:18 +0000)
committerLee Jones <lee.jones@linaro.org>
Tue, 25 Nov 2014 16:18:03 +0000 (16:18 +0000)
Immutable branch between MFD, Regulator and Clk, due for v3.19

15 files changed:
Documentation/devicetree/bindings/mfd/s2mps11.txt
drivers/clk/clk-s2mps11.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/axp288_adc.c [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/axp20x.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/regulator/Kconfig
drivers/regulator/s2mps11.c
include/linux/mfd/axp20x.h
include/linux/mfd/samsung/core.h
include/linux/mfd/samsung/s2mps13.h [new file with mode: 0644]
include/linux/of.h

index 0e4026a6cbbfc21bc40dd9e1f5596acc33416e2a..57a045016fca68b6408db6b13f472ba7c17c5e84 100644 (file)
@@ -1,5 +1,5 @@
 
-* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
+* Samsung S2MPS11, S2MPS13, S2MPS14 and S2MPU02 Voltage and Current Regulator
 
 The Samsung S2MPS11 is a multi-function device which includes voltage and
 current regulators, RTC, charger controller and other sub-blocks. It is
@@ -7,8 +7,8 @@ interfaced to the host controller using an I2C interface. Each sub-block is
 addressed by the host system using different I2C slave addresses.
 
 Required properties:
-- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic"
-              or "samsung,s2mpu02-pmic".
+- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps13-pmic"
+             or "samsung,s2mps14-pmic" or "samsung,s2mpu02-pmic".
 - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
 
 Optional properties:
@@ -17,8 +17,8 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
-- clocks: s2mps11 and s5m8767 provide three(AP/CP/BT) buffered 32.768 KHz
-  outputs, so to register these as clocks with common clock framework
+- clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768
+  KHz outputs, so to register these as clocks with common clock framework
   instantiate a sub-node named "clocks". It uses the common clock binding
   documented in :
   [Documentation/devicetree/bindings/clock/clock-bindings.txt]
@@ -30,12 +30,12 @@ Optional nodes:
     the clock which they consume.
     Clock               ID           Devices
     ----------------------------------------------------------
-    32KhzAP            0            S2MPS11, S2MPS14, S5M8767
-    32KhzCP            1            S2MPS11, S5M8767
-    32KhzBT            2            S2MPS11, S2MPS14, S5M8767
+    32KhzAP            0            S2MPS11, S2MPS13, S2MPS14, S5M8767
+    32KhzCP            1            S2MPS11, S2MPS13, S5M8767
+    32KhzBT            2            S2MPS11, S2MPS13, S2MPS14, S5M8767
 
-  - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps14-clk",
-               "samsung,s5m8767-clk"
+  - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk",
+               "samsung,s2mps14-clk", "samsung,s5m8767-clk"
 
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
@@ -81,12 +81,14 @@ as per the datasheet of s2mps11.
        - LDOn
                  - valid values for n are:
                        - S2MPS11: 1 to 38
+                       - S2MPS13: 1 to 40
                        - S2MPS14: 1 to 25
                        - S2MPU02: 1 to 28
                  - Example: LDO1, LDO2, LDO28
        - BUCKn
                  - valid values for n are:
                        - S2MPS11: 1 to 10
+                       - S2MPS13: 1 to 10
                        - S2MPS14: 1 to 5
                        - S2MPU02: 1 to 7
                  - Example: BUCK1, BUCK2, BUCK9
index b7797fb12e1254d5e9e8a2214b11286b21e991eb..7bb13af8e2148f1110b54db534476dbacdd80863 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/clk-provider.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/mfd/samsung/core.h>
@@ -120,6 +121,24 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
        },
 };
 
+static struct clk_init_data s2mps13_clks_init[S2MPS11_CLKS_NUM] = {
+       [S2MPS11_CLK_AP] = {
+               .name = "s2mps13_ap",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_CP] = {
+               .name = "s2mps13_cp",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_BT] = {
+               .name = "s2mps13_bt",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+};
+
 static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
        [S2MPS11_CLK_AP] = {
                .name = "s2mps14_ap",
@@ -184,6 +203,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                s2mps11_reg = S2MPS11_REG_RTC_CTRL;
                clks_init = s2mps11_clks_init;
                break;
+       case S2MPS13X:
+               s2mps11_reg = S2MPS13_REG_RTCCTRL;
+               clks_init = s2mps13_clks_init;
+               break;
        case S2MPS14X:
                s2mps11_reg = S2MPS14_REG_RTCCTRL;
                clks_init = s2mps14_clks_init;
@@ -279,6 +302,7 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
 
 static const struct platform_device_id s2mps11_clk_id[] = {
        { "s2mps11-clk", S2MPS11X},
+       { "s2mps13-clk", S2MPS13X},
        { "s2mps14-clk", S2MPS14X},
        { "s5m8767-clk", S5M8767X},
        { },
index 88bdc8f612e2ccf299550fa8367fb2ad251b29b1..bc4e787096e84c41ec04d3343a0a087f5620935f 100644 (file)
@@ -127,6 +127,14 @@ config AT91_ADC
        help
          Say yes here to build support for Atmel AT91 ADC.
 
+config AXP288_ADC
+       tristate "X-Powers AXP288 ADC driver"
+       depends on MFD_AXP20X
+       help
+         Say yes here to have support for X-Powers power management IC (PMIC) ADC
+         device. Depending on platform configuration, this general purpose ADC can
+         be used for sampling sensors such as thermal resistors.
+
 config EXYNOS_ADC
        tristate "Exynos ADC driver support"
        depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
index cb88a6a23b8fde707a9bd941b689132ddd4a4f1c..f30093f5b67a406cd17512b048d2e37e8e44c6e7 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
new file mode 100644 (file)
index 0000000..08bcfb0
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * axp288_adc.c - X-Powers AXP288 PMIC ADC Driver
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/platform_device.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+#define AXP288_ADC_EN_MASK             0xF1
+#define AXP288_ADC_TS_PIN_GPADC                0xF2
+#define AXP288_ADC_TS_PIN_ON           0xF3
+
+enum axp288_adc_id {
+       AXP288_ADC_TS,
+       AXP288_ADC_PMIC,
+       AXP288_ADC_GP,
+       AXP288_ADC_BATT_CHRG_I,
+       AXP288_ADC_BATT_DISCHRG_I,
+       AXP288_ADC_BATT_V,
+       AXP288_ADC_NR_CHAN,
+};
+
+struct axp288_adc_info {
+       int irq;
+       struct regmap *regmap;
+};
+
+static const struct iio_chan_spec const axp288_adc_channels[] = {
+       {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 0,
+               .address = AXP288_TS_ADC_H,
+               .datasheet_name = "TS_PIN",
+       }, {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 1,
+               .address = AXP288_PMIC_ADC_H,
+               .datasheet_name = "PMIC_TEMP",
+       }, {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 2,
+               .address = AXP288_GP_ADC_H,
+               .datasheet_name = "GPADC",
+       }, {
+               .indexed = 1,
+               .type = IIO_CURRENT,
+               .channel = 3,
+               .address = AXP20X_BATT_CHRG_I_H,
+               .datasheet_name = "BATT_CHG_I",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       }, {
+               .indexed = 1,
+               .type = IIO_CURRENT,
+               .channel = 4,
+               .address = AXP20X_BATT_DISCHRG_I_H,
+               .datasheet_name = "BATT_DISCHRG_I",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       }, {
+               .indexed = 1,
+               .type = IIO_VOLTAGE,
+               .channel = 5,
+               .address = AXP20X_BATT_V_H,
+               .datasheet_name = "BATT_V",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       },
+};
+
+#define AXP288_ADC_MAP(_adc_channel_label, _consumer_dev_name, \
+               _consumer_channel)                              \
+       {                                                       \
+               .adc_channel_label = _adc_channel_label,        \
+               .consumer_dev_name = _consumer_dev_name,        \
+               .consumer_channel = _consumer_channel,          \
+       }
+
+/* for consumer drivers */
+static struct iio_map axp288_adc_default_maps[] = {
+       AXP288_ADC_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
+       AXP288_ADC_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
+       AXP288_ADC_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
+       AXP288_ADC_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"),
+       AXP288_ADC_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"),
+       AXP288_ADC_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"),
+       {},
+};
+
+static int axp288_adc_read_channel(int *val, unsigned long address,
+                               struct regmap *regmap)
+{
+       u8 buf[2];
+
+       if (regmap_bulk_read(regmap, address, buf, 2))
+               return -EIO;
+       *val = (buf[0] << 4) + ((buf[1] >> 4) & 0x0F);
+
+       return IIO_VAL_INT;
+}
+
+static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
+                               unsigned long address)
+{
+       /* channels other than GPADC do not need to switch TS pin */
+       if (address != AXP288_GP_ADC_H)
+               return 0;
+
+       return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+}
+
+static int axp288_adc_read_raw(struct iio_dev *indio_dev,
+                       struct iio_chan_spec const *chan,
+                       int *val, int *val2, long mask)
+{
+       int ret;
+       struct axp288_adc_info *info = iio_priv(indio_dev);
+
+       mutex_lock(&indio_dev->mlock);
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+                                       chan->address)) {
+                       dev_err(&indio_dev->dev, "GPADC mode\n");
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = axp288_adc_read_channel(val, chan->address, info->regmap);
+               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+                                               chan->address))
+                       dev_err(&indio_dev->dev, "TS pin restore\n");
+               break;
+       case IIO_CHAN_INFO_PROCESSED:
+               ret = axp288_adc_read_channel(val, chan->address, info->regmap);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret;
+}
+
+static int axp288_adc_set_state(struct regmap *regmap)
+{
+       /* ADC should be always enabled for internal FG to function */
+       if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
+               return -EIO;
+
+       return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+}
+
+static const struct iio_info axp288_adc_iio_info = {
+       .read_raw = &axp288_adc_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int axp288_adc_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct axp288_adc_info *info;
+       struct iio_dev *indio_dev;
+       struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       info = iio_priv(indio_dev);
+       info->irq = platform_get_irq(pdev, 0);
+       if (info->irq < 0) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return info->irq;
+       }
+       platform_set_drvdata(pdev, indio_dev);
+       info->regmap = axp20x->regmap;
+       /*
+        * Set ADC to enabled state at all time, including system suspend.
+        * otherwise internal fuel gauge functionality may be affected.
+        */
+       ret = axp288_adc_set_state(axp20x->regmap);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable ADC device\n");
+               return ret;
+       }
+
+       indio_dev->dev.parent = &pdev->dev;
+       indio_dev->name = pdev->name;
+       indio_dev->channels = axp288_adc_channels;
+       indio_dev->num_channels = ARRAY_SIZE(axp288_adc_channels);
+       indio_dev->info = &axp288_adc_iio_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       ret = iio_map_array_register(indio_dev, axp288_adc_default_maps);
+       if (ret < 0)
+               return ret;
+
+       ret = iio_device_register(indio_dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to register iio device\n");
+               goto err_array_unregister;
+       }
+       return 0;
+
+err_array_unregister:
+       iio_map_array_unregister(indio_dev);
+
+       return ret;
+}
+
+static int axp288_adc_remove(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+       iio_device_unregister(indio_dev);
+       iio_map_array_unregister(indio_dev);
+
+       return 0;
+}
+
+static struct platform_device_id axp288_adc_id_table[] = {
+       { .name = "axp288_adc" },
+       {},
+};
+
+static struct platform_driver axp288_adc_driver = {
+       .probe = axp288_adc_probe,
+       .remove = axp288_adc_remove,
+       .id_table = axp288_adc_id_table,
+       .driver = {
+               .name = "axp288_adc",
+       },
+};
+
+MODULE_DEVICE_TABLE(platform, axp288_adc_id_table);
+
+module_platform_driver(axp288_adc_driver);
+
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@linux.intel.com>");
+MODULE_DESCRIPTION("X-Powers AXP288 ADC Driver");
+MODULE_LICENSE("GPL");
index c1acc76a519fadea7a58bf0573f018515b10458e..fdbb40181834fa985a7b9d9153978e5bf580d092 100644 (file)
@@ -74,7 +74,8 @@ config MFD_AXP20X
        select REGMAP_IRQ
        depends on I2C=y
        help
-         If you say Y here you get support for the X-Powers AXP202 and AXP209.
+         If you say Y here you get support for the X-Powers AXP202, AXP209 and
+         AXP288 power management IC (PMIC).
          This driver include only the core APIs. You have to select individual
          components like regulators or the PEK (Power Enable Key) under the
          corresponding menus.
index 6231adbb295d6afd876de989db2a97f314a96cb8..971b0eb8d82103f37729b379a170f93553affde4 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209
+ * axp20x.c - MFD core driver for the X-Powers' Power Management ICs
  *
- * AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC
- * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
- * as well as configurable GPIOs.
+ * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
+ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
+ * as well as configurable GPIOs.
  *
  * Author: Carlo Caione <carlo@caione.org>
  *
 #include <linux/mfd/core.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/acpi.h>
 
 #define AXP20X_OFF     0x80
 
+static const char const *axp20x_model_names[] = {
+       "AXP202",
+       "AXP209",
+       "AXP288",
+};
+
 static const struct regmap_range axp20x_writeable_ranges[] = {
        regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
        regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
@@ -47,6 +54,25 @@ static const struct regmap_access_table axp20x_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
 };
 
+static const struct regmap_range axp288_writeable_ranges[] = {
+       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
+       regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
+};
+
+static const struct regmap_range axp288_volatile_ranges[] = {
+       regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
+};
+
+static const struct regmap_access_table axp288_writeable_table = {
+       .yes_ranges     = axp288_writeable_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(axp288_writeable_ranges),
+};
+
+static const struct regmap_access_table axp288_volatile_table = {
+       .yes_ranges     = axp288_volatile_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(axp288_volatile_ranges),
+};
+
 static struct resource axp20x_pek_resources[] = {
        {
                .name   = "PEK_DBR",
@@ -61,6 +87,39 @@ static struct resource axp20x_pek_resources[] = {
        },
 };
 
+static struct resource axp288_battery_resources[] = {
+       {
+               .start = AXP288_IRQ_QWBTU,
+               .end   = AXP288_IRQ_QWBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WBTU,
+               .end   = AXP288_IRQ_WBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QWBTO,
+               .end   = AXP288_IRQ_QWBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WBTO,
+               .end   = AXP288_IRQ_WBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WL2,
+               .end   = AXP288_IRQ_WL2,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WL1,
+               .end   = AXP288_IRQ_WL1,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
 static const struct regmap_config axp20x_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
@@ -70,47 +129,96 @@ static const struct regmap_config axp20x_regmap_config = {
        .cache_type     = REGCACHE_RBTREE,
 };
 
-#define AXP20X_IRQ(_irq, _off, _mask) \
-       [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
+static const struct regmap_config axp288_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .wr_table       = &axp288_writeable_table,
+       .volatile_table = &axp288_volatile_table,
+       .max_register   = AXP288_FG_TUNE5,
+       .cache_type     = REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                   \
+       [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
 
 static const struct regmap_irq axp20x_regmap_irqs[] = {
-       AXP20X_IRQ(ACIN_OVER_V,         0, 7),
-       AXP20X_IRQ(ACIN_PLUGIN,         0, 6),
-       AXP20X_IRQ(ACIN_REMOVAL,        0, 5),
-       AXP20X_IRQ(VBUS_OVER_V,         0, 4),
-       AXP20X_IRQ(VBUS_PLUGIN,         0, 3),
-       AXP20X_IRQ(VBUS_REMOVAL,        0, 2),
-       AXP20X_IRQ(VBUS_V_LOW,          0, 1),
-       AXP20X_IRQ(BATT_PLUGIN,         1, 7),
-       AXP20X_IRQ(BATT_REMOVAL,        1, 6),
-       AXP20X_IRQ(BATT_ENT_ACT_MODE,   1, 5),
-       AXP20X_IRQ(BATT_EXIT_ACT_MODE,  1, 4),
-       AXP20X_IRQ(CHARG,               1, 3),
-       AXP20X_IRQ(CHARG_DONE,          1, 2),
-       AXP20X_IRQ(BATT_TEMP_HIGH,      1, 1),
-       AXP20X_IRQ(BATT_TEMP_LOW,       1, 0),
-       AXP20X_IRQ(DIE_TEMP_HIGH,       2, 7),
-       AXP20X_IRQ(CHARG_I_LOW,         2, 6),
-       AXP20X_IRQ(DCDC1_V_LONG,        2, 5),
-       AXP20X_IRQ(DCDC2_V_LONG,        2, 4),
-       AXP20X_IRQ(DCDC3_V_LONG,        2, 3),
-       AXP20X_IRQ(PEK_SHORT,           2, 1),
-       AXP20X_IRQ(PEK_LONG,            2, 0),
-       AXP20X_IRQ(N_OE_PWR_ON,         3, 7),
-       AXP20X_IRQ(N_OE_PWR_OFF,        3, 6),
-       AXP20X_IRQ(VBUS_VALID,          3, 5),
-       AXP20X_IRQ(VBUS_NOT_VALID,      3, 4),
-       AXP20X_IRQ(VBUS_SESS_VALID,     3, 3),
-       AXP20X_IRQ(VBUS_SESS_END,       3, 2),
-       AXP20X_IRQ(LOW_PWR_LVL1,        3, 1),
-       AXP20X_IRQ(LOW_PWR_LVL2,        3, 0),
-       AXP20X_IRQ(TIMER,               4, 7),
-       AXP20X_IRQ(PEK_RIS_EDGE,        4, 6),
-       AXP20X_IRQ(PEK_FAL_EDGE,        4, 5),
-       AXP20X_IRQ(GPIO3_INPUT,         4, 3),
-       AXP20X_IRQ(GPIO2_INPUT,         4, 2),
-       AXP20X_IRQ(GPIO1_INPUT,         4, 1),
-       AXP20X_IRQ(GPIO0_INPUT,         4, 0),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,            0, 7),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,            0, 6),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL,           0, 5),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V,            0, 4),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN,            0, 3),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL,           0, 2),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW,             0, 1),
+       INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN,            1, 7),
+       INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL,           1, 6),
+       INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE,      1, 5),
+       INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE,     1, 4),
+       INIT_REGMAP_IRQ(AXP20X, CHARG,                  1, 3),
+       INIT_REGMAP_IRQ(AXP20X, CHARG_DONE,             1, 2),
+       INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH,         1, 1),
+       INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW,          1, 0),
+       INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH,          2, 7),
+       INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW,            2, 6),
+       INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG,           2, 5),
+       INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG,           2, 4),
+       INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG,           2, 3),
+       INIT_REGMAP_IRQ(AXP20X, PEK_SHORT,              2, 1),
+       INIT_REGMAP_IRQ(AXP20X, PEK_LONG,               2, 0),
+       INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON,            3, 7),
+       INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF,           3, 6),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_VALID,             3, 5),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID,         3, 4),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID,        3, 3),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END,          3, 2),
+       INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1,           3, 1),
+       INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2,           3, 0),
+       INIT_REGMAP_IRQ(AXP20X, TIMER,                  4, 7),
+       INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE,           4, 6),
+       INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE,           4, 5),
+       INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT,            4, 3),
+       INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT,            4, 2),
+       INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT,            4, 1),
+       INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT,            4, 0),
+};
+
+/* some IRQs are compatible with axp20x models */
+static const struct regmap_irq axp288_regmap_irqs[] = {
+       INIT_REGMAP_IRQ(AXP288, VBUS_FALL,              0, 2),
+       INIT_REGMAP_IRQ(AXP288, VBUS_RISE,              0, 3),
+       INIT_REGMAP_IRQ(AXP288, OV,                     0, 4),
+
+       INIT_REGMAP_IRQ(AXP288, DONE,                   1, 2),
+       INIT_REGMAP_IRQ(AXP288, CHARGING,               1, 3),
+       INIT_REGMAP_IRQ(AXP288, SAFE_QUIT,              1, 4),
+       INIT_REGMAP_IRQ(AXP288, SAFE_ENTER,             1, 5),
+       INIT_REGMAP_IRQ(AXP288, ABSENT,                 1, 6),
+       INIT_REGMAP_IRQ(AXP288, APPEND,                 1, 7),
+
+       INIT_REGMAP_IRQ(AXP288, QWBTU,                  2, 0),
+       INIT_REGMAP_IRQ(AXP288, WBTU,                   2, 1),
+       INIT_REGMAP_IRQ(AXP288, QWBTO,                  2, 2),
+       INIT_REGMAP_IRQ(AXP288, WBTO,                   2, 3),
+       INIT_REGMAP_IRQ(AXP288, QCBTU,                  2, 4),
+       INIT_REGMAP_IRQ(AXP288, CBTU,                   2, 5),
+       INIT_REGMAP_IRQ(AXP288, QCBTO,                  2, 6),
+       INIT_REGMAP_IRQ(AXP288, CBTO,                   2, 7),
+
+       INIT_REGMAP_IRQ(AXP288, WL2,                    3, 0),
+       INIT_REGMAP_IRQ(AXP288, WL1,                    3, 1),
+       INIT_REGMAP_IRQ(AXP288, GPADC,                  3, 2),
+       INIT_REGMAP_IRQ(AXP288, OT,                     3, 7),
+
+       INIT_REGMAP_IRQ(AXP288, GPIO0,                  4, 0),
+       INIT_REGMAP_IRQ(AXP288, GPIO1,                  4, 1),
+       INIT_REGMAP_IRQ(AXP288, POKO,                   4, 2),
+       INIT_REGMAP_IRQ(AXP288, POKL,                   4, 3),
+       INIT_REGMAP_IRQ(AXP288, POKS,                   4, 4),
+       INIT_REGMAP_IRQ(AXP288, POKN,                   4, 5),
+       INIT_REGMAP_IRQ(AXP288, POKP,                   4, 6),
+       INIT_REGMAP_IRQ(AXP288, TIMER,                  4, 7),
+
+       INIT_REGMAP_IRQ(AXP288, MV_CHNG,                5, 0),
+       INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
 };
 
 static const struct of_device_id axp20x_of_match[] = {
@@ -128,16 +236,39 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
 
+static struct acpi_device_id axp20x_acpi_match[] = {
+       {
+               .id = "INT33F4",
+               .driver_data = AXP288_ID,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match);
+
 static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
        .name                   = "axp20x_irq_chip",
        .status_base            = AXP20X_IRQ1_STATE,
        .ack_base               = AXP20X_IRQ1_STATE,
        .mask_base              = AXP20X_IRQ1_EN,
-       .num_regs               = 5,
+       .mask_invert            = true,
+       .init_ack_masked        = true,
        .irqs                   = axp20x_regmap_irqs,
        .num_irqs               = ARRAY_SIZE(axp20x_regmap_irqs),
+       .num_regs               = 5,
+
+};
+
+static const struct regmap_irq_chip axp288_regmap_irq_chip = {
+       .name                   = "axp288_irq_chip",
+       .status_base            = AXP20X_IRQ1_STATE,
+       .ack_base               = AXP20X_IRQ1_STATE,
+       .mask_base              = AXP20X_IRQ1_EN,
        .mask_invert            = true,
        .init_ack_masked        = true,
+       .irqs                   = axp288_regmap_irqs,
+       .num_irqs               = ARRAY_SIZE(axp288_regmap_irqs),
+       .num_regs               = 6,
+
 };
 
 static struct mfd_cell axp20x_cells[] = {
@@ -150,36 +281,155 @@ static struct mfd_cell axp20x_cells[] = {
        },
 };
 
+static struct resource axp288_adc_resources[] = {
+       {
+               .name  = "GPADC",
+               .start = AXP288_IRQ_GPADC,
+               .end   = AXP288_IRQ_GPADC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource axp288_charger_resources[] = {
+       {
+               .start = AXP288_IRQ_OV,
+               .end   = AXP288_IRQ_OV,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_DONE,
+               .end   = AXP288_IRQ_DONE,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CHARGING,
+               .end   = AXP288_IRQ_CHARGING,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_SAFE_QUIT,
+               .end   = AXP288_IRQ_SAFE_QUIT,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_SAFE_ENTER,
+               .end   = AXP288_IRQ_SAFE_ENTER,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QCBTU,
+               .end   = AXP288_IRQ_QCBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CBTU,
+               .end   = AXP288_IRQ_CBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QCBTO,
+               .end   = AXP288_IRQ_QCBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CBTO,
+               .end   = AXP288_IRQ_CBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct mfd_cell axp288_cells[] = {
+       {
+               .name = "axp288_adc",
+               .num_resources = ARRAY_SIZE(axp288_adc_resources),
+               .resources = axp288_adc_resources,
+       },
+       {
+               .name = "axp288_charger",
+               .num_resources = ARRAY_SIZE(axp288_charger_resources),
+               .resources = axp288_charger_resources,
+       },
+       {
+               .name = "axp288_battery",
+               .num_resources = ARRAY_SIZE(axp288_battery_resources),
+               .resources = axp288_battery_resources,
+       },
+};
+
 static struct axp20x_dev *axp20x_pm_power_off;
 static void axp20x_power_off(void)
 {
+       if (axp20x_pm_power_off->variant == AXP288_ID)
+               return;
+
        regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
                     AXP20X_OFF);
 }
 
+static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
+{
+       const struct acpi_device_id *acpi_id;
+       const struct of_device_id *of_id;
+
+       if (dev->of_node) {
+               of_id = of_match_device(axp20x_of_match, dev);
+               if (!of_id) {
+                       dev_err(dev, "Unable to match OF ID\n");
+                       return -ENODEV;
+               }
+               axp20x->variant = (long) of_id->data;
+       } else {
+               acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+               if (!acpi_id || !acpi_id->driver_data) {
+                       dev_err(dev, "Unable to match ACPI ID and data\n");
+                       return -ENODEV;
+               }
+               axp20x->variant = (long) acpi_id->driver_data;
+       }
+
+       switch (axp20x->variant) {
+       case AXP202_ID:
+       case AXP209_ID:
+               axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
+               axp20x->cells = axp20x_cells;
+               axp20x->regmap_cfg = &axp20x_regmap_config;
+               axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
+               break;
+       case AXP288_ID:
+               axp20x->cells = axp288_cells;
+               axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
+               axp20x->regmap_cfg = &axp288_regmap_config;
+               axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
+               break;
+       default:
+               dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
+               return -EINVAL;
+       }
+       dev_info(dev, "AXP20x variant %s found\n",
+               axp20x_model_names[axp20x->variant]);
+
+       return 0;
+}
+
 static int axp20x_i2c_probe(struct i2c_client *i2c,
                         const struct i2c_device_id *id)
 {
        struct axp20x_dev *axp20x;
-       const struct of_device_id *of_id;
        int ret;
 
        axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
        if (!axp20x)
                return -ENOMEM;
 
-       of_id = of_match_device(axp20x_of_match, &i2c->dev);
-       if (!of_id) {
-               dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
-               return -ENODEV;
-       }
-       axp20x->variant = (long) of_id->data;
+       ret = axp20x_match_device(axp20x, &i2c->dev);
+       if (ret)
+               return ret;
 
        axp20x->i2c_client = i2c;
        axp20x->dev = &i2c->dev;
        dev_set_drvdata(axp20x->dev, axp20x);
 
-       axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
+       axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
        if (IS_ERR(axp20x->regmap)) {
                ret = PTR_ERR(axp20x->regmap);
                dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
@@ -188,15 +438,15 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
 
        ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
                                  IRQF_ONESHOT | IRQF_SHARED, -1,
-                                 &axp20x_regmap_irq_chip,
+                                 axp20x->regmap_irq_chip,
                                  &axp20x->regmap_irqc);
        if (ret) {
                dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
                return ret;
        }
 
-       ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
-                             ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+       ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
+                       axp20x->nr_cells, NULL, 0, NULL);
 
        if (ret) {
                dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
@@ -234,6 +484,7 @@ static struct i2c_driver axp20x_i2c_driver = {
                .name   = "axp20x",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(axp20x_of_match),
+               .acpi_match_table = ACPI_PTR(axp20x_acpi_match),
        },
        .probe          = axp20x_i2c_probe,
        .remove         = axp20x_i2c_remove,
index dba7e2b6f8e9d949c7c3de18299625448ecd86d8..b39960532f766f440fe99ac86d7662fe6050bc9e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mpa01.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8763.h>
@@ -74,6 +75,15 @@ static const struct mfd_cell s2mps11_devs[] = {
        }
 };
 
+static const struct mfd_cell s2mps13_devs[] = {
+       { .name = "s2mps13-pmic", },
+       { .name = "s2mps13-rtc", },
+       {
+               .name = "s2mps13-clk",
+               .of_compatible = "samsung,s2mps13-clk",
+       },
+};
+
 static const struct mfd_cell s2mps14_devs[] = {
        {
                .name = "s2mps14-pmic",
@@ -107,6 +117,9 @@ static const struct of_device_id sec_dt_match[] = {
        }, {
                .compatible = "samsung,s2mps11-pmic",
                .data = (void *)S2MPS11X,
+       }, {
+               .compatible = "samsung,s2mps13-pmic",
+               .data = (void *)S2MPS13X,
        }, {
                .compatible = "samsung,s2mps14-pmic",
                .data = (void *)S2MPS14X,
@@ -194,6 +207,15 @@ static const struct regmap_config s2mps11_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config s2mps13_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = S2MPS13_REG_LDODSCH5,
+       .volatile_reg = s2mps11_volatile,
+       .cache_type = REGCACHE_FLAT,
+};
+
 static const struct regmap_config s2mps14_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -325,6 +347,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        case S2MPS11X:
                regmap = &s2mps11_regmap_config;
                break;
+       case S2MPS13X:
+               regmap = &s2mps13_regmap_config;
+               break;
        case S2MPS14X:
                regmap = &s2mps14_regmap_config;
                break;
@@ -378,6 +403,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                sec_devs = s2mps11_devs;
                num_sec_devs = ARRAY_SIZE(s2mps11_devs);
                break;
+       case S2MPS13X:
+               sec_devs = s2mps13_devs;
+               num_sec_devs = ARRAY_SIZE(s2mps13_devs);
+               break;
        case S2MPS14X:
                sec_devs = s2mps14_devs;
                num_sec_devs = ARRAY_SIZE(s2mps14_devs);
index f9a57869e3ece6f842ce7f99fd176d1cfea796b7..ba86a918c2dace19be14235f484f380a970d667e 100644 (file)
@@ -389,14 +389,22 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
        .ack_base = S2MPS11_REG_INT1,
 };
 
+#define S2MPS1X_IRQ_CHIP_COMMON_DATA           \
+       .irqs = s2mps14_irqs,                   \
+       .num_irqs = ARRAY_SIZE(s2mps14_irqs),   \
+       .num_regs = 3,                          \
+       .status_base = S2MPS14_REG_INT1,        \
+       .mask_base = S2MPS14_REG_INT1M,         \
+       .ack_base = S2MPS14_REG_INT1            \
+
+static const struct regmap_irq_chip s2mps13_irq_chip = {
+       .name = "s2mps13",
+       S2MPS1X_IRQ_CHIP_COMMON_DATA,
+};
+
 static const struct regmap_irq_chip s2mps14_irq_chip = {
        .name = "s2mps14",
-       .irqs = s2mps14_irqs,
-       .num_irqs = ARRAY_SIZE(s2mps14_irqs),
-       .num_regs = 3,
-       .status_base = S2MPS14_REG_INT1,
-       .mask_base = S2MPS14_REG_INT1M,
-       .ack_base = S2MPS14_REG_INT1,
+       S2MPS1X_IRQ_CHIP_COMMON_DATA,
 };
 
 static const struct regmap_irq_chip s2mpu02_irq_chip = {
@@ -452,6 +460,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
        case S2MPS11X:
                sec_irq_chip = &s2mps11_irq_chip;
                break;
+       case S2MPS13X:
+               sec_irq_chip = &s2mps13_irq_chip;
+               break;
        case S2MPS14X:
                sec_irq_chip = &s2mps14_irq_chip;
                break;
index 55d7b7b0f2e011d036826111f5064c600b639d23..5e061347be930d8d77e78edb9a23d5d28af652c9 100644 (file)
@@ -529,13 +529,13 @@ config REGULATOR_S2MPA01
         via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
 
 config REGULATOR_S2MPS11
-       tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
+       tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator"
        depends on MFD_SEC_CORE
        help
-        This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
-        regulator via I2C bus. The chip is comprised of high efficient Buck
-        converters including Dual-Phase Buck converter, Buck-Boost converter,
-        various LDOs.
+        This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage
+        output regulator via I2C bus. The chip is comprised of high efficient
+        Buck converters including Dual-Phase Buck converter, Buck-Boost
+        converter, various LDOs.
 
 config REGULATOR_S5M8767
        tristate "Samsung S5M8767A voltage regulator"
index adab82d5279f0696319f53d04e30b07615121dbb..738dc7763d471324dd3a9c9afd58798658bdae7c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/of_gpio.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 
@@ -45,10 +46,10 @@ struct s2mps11_info {
        enum sec_device_type dev_type;
 
        /*
-        * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
-        * was enabled.
+        * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
+        * the suspend mode was enabled.
         */
-       unsigned long long s2mps14_suspend_state:35;
+       unsigned long long s2mps14_suspend_state:50;
 
        /* Array of size rdev_num with GPIO-s for external sleep control */
        int *ext_control_gpio;
@@ -369,12 +370,101 @@ static const struct regulator_desc s2mps11_regulators[] = {
        regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
 };
 
+static struct regulator_ops s2mps14_reg_ops;
+
+#define regulator_desc_s2mps13_ldo(num, min, step, min_sel) {  \
+       .name           = "LDO"#num,                            \
+       .id             = S2MPS13_LDO##num,                     \
+       .ops            = &s2mps14_reg_ops,                     \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = min,                                  \
+       .uV_step        = step,                                 \
+       .linear_min_sel = min_sel,                              \
+       .n_voltages     = S2MPS14_LDO_N_VOLTAGES,               \
+       .vsel_reg       = S2MPS13_REG_L1CTRL + num - 1,         \
+       .vsel_mask      = S2MPS14_LDO_VSEL_MASK,                \
+       .enable_reg     = S2MPS13_REG_L1CTRL + num - 1,         \
+       .enable_mask    = S2MPS14_ENABLE_MASK                   \
+}
+
+#define regulator_desc_s2mps13_buck(num, min, step, min_sel) { \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS13_BUCK##num,                    \
+       .ops            = &s2mps14_reg_ops,                     \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = min,                                  \
+       .uV_step        = step,                                 \
+       .linear_min_sel = min_sel,                              \
+       .n_voltages     = S2MPS14_BUCK_N_VOLTAGES,              \
+       .ramp_delay     = S2MPS13_BUCK_RAMP_DELAY,              \
+       .vsel_reg       = S2MPS13_REG_B1OUT + (num - 1) * 2,    \
+       .vsel_mask      = S2MPS14_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS13_REG_B1CTRL + (num - 1) * 2,   \
+       .enable_mask    = S2MPS14_ENABLE_MASK                   \
+}
+
+static const struct regulator_desc s2mps13_regulators[] = {
+       regulator_desc_s2mps13_ldo(1,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(2,  MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(3,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(4,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(5,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(6,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(7,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(8,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(9,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(10, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(11, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(12, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(13, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(14, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(15, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(16, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(17, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(18, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(19, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(20, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(21, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(22, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(23, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(24, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(25, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(26, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(27, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(28, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(29, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(30, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(31, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(32, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(33, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(34, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(35, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(36, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(37, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(38, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(39, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(40, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_buck(1,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(2,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(3,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(4,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(5,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(6,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(7,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(8,  MIN_1000_MV, STEP_12_5_MV, 0x20),
+       regulator_desc_s2mps13_buck(9,  MIN_1000_MV, STEP_12_5_MV, 0x20),
+       regulator_desc_s2mps13_buck(10, MIN_500_MV,  STEP_6_25_MV, 0x10),
+};
+
 static int s2mps14_regulator_enable(struct regulator_dev *rdev)
 {
        struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
        unsigned int val;
 
        switch (s2mps11->dev_type) {
+       case S2MPS13X:
        case S2MPS14X:
                if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
                        val = S2MPS14_ENABLE_SUSPEND;
@@ -406,6 +496,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
 
        /* Below LDO should be always on or does not support suspend mode. */
        switch (s2mps11->dev_type) {
+       case S2MPS13X:
        case S2MPS14X:
                switch (rdev_id) {
                case S2MPS14_LDO3:
@@ -831,6 +922,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
                s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
                regulators = s2mps11_regulators;
                break;
+       case S2MPS13X:
+               s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
+               regulators = s2mps13_regulators;
+               break;
        case S2MPS14X:
                s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
                regulators = s2mps14_regulators;
@@ -927,6 +1022,7 @@ out:
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
        { "s2mps11-pmic", S2MPS11X},
+       { "s2mps13-pmic", S2MPS13X},
        { "s2mps14-pmic", S2MPS14X},
        { "s2mpu02-pmic", S2MPU02},
        { },
index d0e31a2287ac1b95996225be09c01f5b826dadb9..81589d176ae873c3dbd9cec1c27bdfcadb3679fb 100644 (file)
@@ -14,6 +14,8 @@
 enum {
        AXP202_ID = 0,
        AXP209_ID,
+       AXP288_ID,
+       NR_AXP20X_VARIANTS,
 };
 
 #define AXP20X_DATACACHE(m)            (0x04 + (m))
@@ -49,11 +51,13 @@ enum {
 #define AXP20X_IRQ3_EN                 0x42
 #define AXP20X_IRQ4_EN                 0x43
 #define AXP20X_IRQ5_EN                 0x44
+#define AXP20X_IRQ6_EN                 0x45
 #define AXP20X_IRQ1_STATE              0x48
 #define AXP20X_IRQ2_STATE              0x49
 #define AXP20X_IRQ3_STATE              0x4a
 #define AXP20X_IRQ4_STATE              0x4b
 #define AXP20X_IRQ5_STATE              0x4c
+#define AXP20X_IRQ6_STATE              0x4d
 
 /* ADC */
 #define AXP20X_ACIN_V_ADC_H            0x56
@@ -116,6 +120,15 @@ enum {
 #define AXP20X_CC_CTRL                 0xb8
 #define AXP20X_FG_RES                  0xb9
 
+/* AXP288 specific registers */
+#define AXP288_PMIC_ADC_H               0x56
+#define AXP288_PMIC_ADC_L               0x57
+#define AXP288_ADC_TS_PIN_CTRL          0x84
+
+#define AXP288_PMIC_ADC_EN              0x84
+#define AXP288_FG_TUNE5                        0xed
+
+
 /* Regulators IDs */
 enum {
        AXP20X_LDO1 = 0,
@@ -169,12 +182,58 @@ enum {
        AXP20X_IRQ_GPIO0_INPUT,
 };
 
+enum axp288_irqs {
+       AXP288_IRQ_VBUS_FALL     = 2,
+       AXP288_IRQ_VBUS_RISE,
+       AXP288_IRQ_OV,
+       AXP288_IRQ_FALLING_ALT,
+       AXP288_IRQ_RISING_ALT,
+       AXP288_IRQ_OV_ALT,
+       AXP288_IRQ_DONE          = 10,
+       AXP288_IRQ_CHARGING,
+       AXP288_IRQ_SAFE_QUIT,
+       AXP288_IRQ_SAFE_ENTER,
+       AXP288_IRQ_ABSENT,
+       AXP288_IRQ_APPEND,
+       AXP288_IRQ_QWBTU,
+       AXP288_IRQ_WBTU,
+       AXP288_IRQ_QWBTO,
+       AXP288_IRQ_WBTO,
+       AXP288_IRQ_QCBTU,
+       AXP288_IRQ_CBTU,
+       AXP288_IRQ_QCBTO,
+       AXP288_IRQ_CBTO,
+       AXP288_IRQ_WL2,
+       AXP288_IRQ_WL1,
+       AXP288_IRQ_GPADC,
+       AXP288_IRQ_OT            = 31,
+       AXP288_IRQ_GPIO0,
+       AXP288_IRQ_GPIO1,
+       AXP288_IRQ_POKO,
+       AXP288_IRQ_POKL,
+       AXP288_IRQ_POKS,
+       AXP288_IRQ_POKN,
+       AXP288_IRQ_POKP,
+       AXP288_IRQ_TIMER,
+       AXP288_IRQ_MV_CHNG,
+       AXP288_IRQ_BC_USB_CHNG,
+};
+
+#define AXP288_TS_ADC_H                0x58
+#define AXP288_TS_ADC_L                0x59
+#define AXP288_GP_ADC_H                0x5a
+#define AXP288_GP_ADC_L                0x5b
+
 struct axp20x_dev {
        struct device                   *dev;
        struct i2c_client               *i2c_client;
        struct regmap                   *regmap;
        struct regmap_irq_chip_data     *regmap_irqc;
        long                            variant;
+       int                             nr_cells;
+       struct mfd_cell                 *cells;
+       const struct regmap_config      *regmap_cfg;
+       const struct regmap_irq_chip    *regmap_irq_chip;
 };
 
 #endif /* __LINUX_MFD_AXP20X_H */
index 1825edacbda7aa57fa53792bf513fe058d61110a..3fdb7cfbffb3acf09b133f97f42cf248fb65ee8a 100644 (file)
@@ -28,6 +28,7 @@
 #define MIN_800_MV             800000
 #define MIN_750_MV             750000
 #define MIN_600_MV             600000
+#define MIN_500_MV             500000
 
 /* Macros to represent steps for LDO/BUCK */
 #define STEP_50_MV             50000
@@ -41,6 +42,7 @@ enum sec_device_type {
        S5M8767X,
        S2MPA01,
        S2MPS11X,
+       S2MPS13X,
        S2MPS14X,
        S2MPU02,
 };
diff --git a/include/linux/mfd/samsung/s2mps13.h b/include/linux/mfd/samsung/s2mps13.h
new file mode 100644 (file)
index 0000000..ce5dda8
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * s2mps13.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *              http://www.samsung.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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_MFD_S2MPS13_H
+#define __LINUX_MFD_S2MPS13_H
+
+/* S2MPS13 registers */
+enum s2mps13_reg {
+       S2MPS13_REG_ID,
+       S2MPS13_REG_INT1,
+       S2MPS13_REG_INT2,
+       S2MPS13_REG_INT3,
+       S2MPS13_REG_INT1M,
+       S2MPS13_REG_INT2M,
+       S2MPS13_REG_INT3M,
+       S2MPS13_REG_ST1,
+       S2MPS13_REG_ST2,
+       S2MPS13_REG_PWRONSRC,
+       S2MPS13_REG_OFFSRC,
+       S2MPS13_REG_BU_CHG,
+       S2MPS13_REG_RTCCTRL,
+       S2MPS13_REG_CTRL1,
+       S2MPS13_REG_CTRL2,
+       S2MPS13_REG_RSVD1,
+       S2MPS13_REG_RSVD2,
+       S2MPS13_REG_RSVD3,
+       S2MPS13_REG_RSVD4,
+       S2MPS13_REG_RSVD5,
+       S2MPS13_REG_RSVD6,
+       S2MPS13_REG_CTRL3,
+       S2MPS13_REG_RSVD7,
+       S2MPS13_REG_RSVD8,
+       S2MPS13_REG_WRSTBI,
+       S2MPS13_REG_B1CTRL,
+       S2MPS13_REG_B1OUT,
+       S2MPS13_REG_B2CTRL,
+       S2MPS13_REG_B2OUT,
+       S2MPS13_REG_B3CTRL,
+       S2MPS13_REG_B3OUT,
+       S2MPS13_REG_B4CTRL,
+       S2MPS13_REG_B4OUT,
+       S2MPS13_REG_B5CTRL,
+       S2MPS13_REG_B5OUT,
+       S2MPS13_REG_B6CTRL,
+       S2MPS13_REG_B6OUT,
+       S2MPS13_REG_B7CTRL,
+       S2MPS13_REG_B7OUT,
+       S2MPS13_REG_B8CTRL,
+       S2MPS13_REG_B8OUT,
+       S2MPS13_REG_B9CTRL,
+       S2MPS13_REG_B9OUT,
+       S2MPS13_REG_B10CTRL,
+       S2MPS13_REG_B10OUT,
+       S2MPS13_REG_BB1CTRL,
+       S2MPS13_REG_BB1OUT,
+       S2MPS13_REG_BUCK_RAMP1,
+       S2MPS13_REG_BUCK_RAMP2,
+       S2MPS13_REG_LDO_DVS1,
+       S2MPS13_REG_LDO_DVS2,
+       S2MPS13_REG_LDO_DVS3,
+       S2MPS13_REG_B6OUT2,
+       S2MPS13_REG_L1CTRL,
+       S2MPS13_REG_L2CTRL,
+       S2MPS13_REG_L3CTRL,
+       S2MPS13_REG_L4CTRL,
+       S2MPS13_REG_L5CTRL,
+       S2MPS13_REG_L6CTRL,
+       S2MPS13_REG_L7CTRL,
+       S2MPS13_REG_L8CTRL,
+       S2MPS13_REG_L9CTRL,
+       S2MPS13_REG_L10CTRL,
+       S2MPS13_REG_L11CTRL,
+       S2MPS13_REG_L12CTRL,
+       S2MPS13_REG_L13CTRL,
+       S2MPS13_REG_L14CTRL,
+       S2MPS13_REG_L15CTRL,
+       S2MPS13_REG_L16CTRL,
+       S2MPS13_REG_L17CTRL,
+       S2MPS13_REG_L18CTRL,
+       S2MPS13_REG_L19CTRL,
+       S2MPS13_REG_L20CTRL,
+       S2MPS13_REG_L21CTRL,
+       S2MPS13_REG_L22CTRL,
+       S2MPS13_REG_L23CTRL,
+       S2MPS13_REG_L24CTRL,
+       S2MPS13_REG_L25CTRL,
+       S2MPS13_REG_L26CTRL,
+       S2MPS13_REG_L27CTRL,
+       S2MPS13_REG_L28CTRL,
+       S2MPS13_REG_L30CTRL,
+       S2MPS13_REG_L31CTRL,
+       S2MPS13_REG_L32CTRL,
+       S2MPS13_REG_L33CTRL,
+       S2MPS13_REG_L34CTRL,
+       S2MPS13_REG_L35CTRL,
+       S2MPS13_REG_L36CTRL,
+       S2MPS13_REG_L37CTRL,
+       S2MPS13_REG_L38CTRL,
+       S2MPS13_REG_L39CTRL,
+       S2MPS13_REG_L40CTRL,
+       S2MPS13_REG_LDODSCH1,
+       S2MPS13_REG_LDODSCH2,
+       S2MPS13_REG_LDODSCH3,
+       S2MPS13_REG_LDODSCH4,
+       S2MPS13_REG_LDODSCH5,
+};
+
+/*  regulator ids */
+enum s2mps13_regulators {
+       S2MPS13_LDO1,
+       S2MPS13_LDO2,
+       S2MPS13_LDO3,
+       S2MPS13_LDO4,
+       S2MPS13_LDO5,
+       S2MPS13_LDO6,
+       S2MPS13_LDO7,
+       S2MPS13_LDO8,
+       S2MPS13_LDO9,
+       S2MPS13_LDO10,
+       S2MPS13_LDO11,
+       S2MPS13_LDO12,
+       S2MPS13_LDO13,
+       S2MPS13_LDO14,
+       S2MPS13_LDO15,
+       S2MPS13_LDO16,
+       S2MPS13_LDO17,
+       S2MPS13_LDO18,
+       S2MPS13_LDO19,
+       S2MPS13_LDO20,
+       S2MPS13_LDO21,
+       S2MPS13_LDO22,
+       S2MPS13_LDO23,
+       S2MPS13_LDO24,
+       S2MPS13_LDO25,
+       S2MPS13_LDO26,
+       S2MPS13_LDO27,
+       S2MPS13_LDO28,
+       S2MPS13_LDO29,
+       S2MPS13_LDO30,
+       S2MPS13_LDO31,
+       S2MPS13_LDO32,
+       S2MPS13_LDO33,
+       S2MPS13_LDO34,
+       S2MPS13_LDO35,
+       S2MPS13_LDO36,
+       S2MPS13_LDO37,
+       S2MPS13_LDO38,
+       S2MPS13_LDO39,
+       S2MPS13_LDO40,
+       S2MPS13_BUCK1,
+       S2MPS13_BUCK2,
+       S2MPS13_BUCK3,
+       S2MPS13_BUCK4,
+       S2MPS13_BUCK5,
+       S2MPS13_BUCK6,
+       S2MPS13_BUCK7,
+       S2MPS13_BUCK8,
+       S2MPS13_BUCK9,
+       S2MPS13_BUCK10,
+
+       S2MPS13_REGULATOR_MAX,
+};
+
+/*
+ * Default ramp delay in uv/us. Datasheet says that ramp delay can be
+ * controlled however it does not specify which register is used for that.
+ * Let's assume that default value will be set.
+ */
+#define S2MPS13_BUCK_RAMP_DELAY                12500
+
+#endif /*  __LINUX_MFD_S2MPS13_H */
index 6545e7aec7bb95dc41ad6225050cb19e7038287a..27b3ba1e9e59b3dc5cbeb126a3eb641f78c81641 100644 (file)
@@ -866,4 +866,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
 /* CONFIG_OF_RESOLVE api */
 extern int of_resolve_phandles(struct device_node *tree);
 
+/**
+ * of_system_has_poweroff_source - Tells if poweroff-source is found for device_node
+ * @np: Pointer to the given device_node
+ *
+ * return true if present false otherwise
+ */
+static inline bool of_system_has_poweroff_source(const struct device_node *np)
+{
+       return of_property_read_bool(np, "poweroff-source");
+}
+
 #endif /* _LINUX_OF_H */