Merge remote-tracking branches 'regulator/topic/qcom-spmi', 'regulator/topic/rn5t618...
authorMark Brown <broonie@kernel.org>
Wed, 20 Jul 2016 17:02:08 +0000 (18:02 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 20 Jul 2016 17:02:08 +0000 (18:02 +0100)
14 files changed:
Documentation/devicetree/bindings/mfd/rn5t618.txt
Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
arch/arm/boot/dts/meson8-minix-neo-x8.dts
drivers/mfd/Kconfig
drivers/mfd/rn5t618.c
drivers/regulator/Kconfig
drivers/regulator/qcom_spmi-regulator.c
drivers/regulator/rn5t618-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps65218-regulator.c
drivers/regulator/twl-regulator.c
include/linux/mfd/rn5t618.h
include/linux/mfd/tps65217.h
include/linux/mfd/tps65218.h

index 937785a..9e6770b 100644 (file)
@@ -1,18 +1,21 @@
-* Ricoh RN5T618 PMIC
+* Ricoh RN5T567/RN5T618 PMIC
 
-Ricoh RN5T618 is a power management IC which integrates 3 step-down
-DCDC converters, 7 low-dropout regulators, a Li-ion battery charger,
-fuel gauge, ADC, GPIOs and a watchdog timer. It can be controlled
-through a I2C interface.
+Ricoh RN5T567/RN5T618 is a power management IC family which integrates
+3 to 4 step-down DCDC converters, 7 low-dropout regulators, GPIOs and
+a watchdog timer. The RN5T618 provides additionally a Li-ion battery
+charger, fuel gauge and an ADC. It can be controlled through an I2C
+interface.
 
 Required properties:
- - compatible: should be "ricoh,rn5t618"
+ - compatible: must be one of
+               "ricoh,rn5t567"
+               "ricoh,rn5t618"
  - reg: the I2C slave address of the device
 
 Sub-nodes:
  - regulators: the node is required if the regulator functionality is
-   needed. The valid regulator names are: DCDC1, DCDC2, DCDC3, LDO1,
-   LDO2, LDO3, LDO4, LDO5, LDORTC1 and LDORTC2.
+   needed. The valid regulator names are: DCDC1, DCDC2, DCDC3, DCDC4
+   (RN5T567), LDO1, LDO2, LDO3, LDO4, LDO5, LDORTC1 and LDORTC2.
    The common bindings for each individual regulator can be found in:
    Documentation/devicetree/bindings/regulator/regulator.txt
 
index 46c6f3e..0fa3b0f 100644 (file)
@@ -113,9 +113,9 @@ pm8916:
        l14, l15, l16, l17, l18
 
 pm8941:
-       s1, s2, s3, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14,
-       l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
-       mvs1, mvs2
+       s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
+       l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
+       5vs1, 5vs2
 
 pm8994:
        s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5,
index 4f536bb..8bceb8d 100644 (file)
@@ -80,6 +80,7 @@
        pmic@32 {
                compatible = "ricoh,rn5t618";
                reg = <0x32>;
+               system-power-controller;
 
                regulators {
                };
index 1bcf601..ff031a7 100644 (file)
@@ -852,13 +852,14 @@ config MFD_RK808
          including interrupts, RTC, LDO & DCDC regulators, and onkey.
 
 config MFD_RN5T618
-       tristate "Ricoh RN5T5618 PMIC"
+       tristate "Ricoh RN5T567/618 PMIC"
        depends on I2C
+       depends on OF
        select MFD_CORE
        select REGMAP_I2C
        help
-         Say yes here to add support for the Ricoh RN5T618 PMIC. This
-         driver provides common support for accessing the device,
+         Say yes here to add support for the Ricoh RN5T567 or R5T618 PMIC.
+         This driver provides common support for accessing the device,
          additional drivers must be enabled in order to use the
          functionality of the device.
 
index 0ad51d7..ee94080 100644 (file)
@@ -2,6 +2,7 @@
  * MFD core driver for Ricoh RN5T618 PMIC
  *
  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ * Copyright (C) 2016 Toradex AG
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/rn5t618.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reboot.h>
 #include <linux/regmap.h>
 
 static const struct mfd_cell rn5t618_cells[] = {
@@ -48,28 +52,64 @@ static const struct regmap_config rn5t618_regmap_config = {
 };
 
 static struct rn5t618 *rn5t618_pm_power_off;
+static struct notifier_block rn5t618_restart_handler;
 
-static void rn5t618_power_off(void)
+static void rn5t618_trigger_poweroff_sequence(bool repower)
 {
        /* disable automatic repower-on */
        regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_REPCNT,
-                          RN5T618_REPCNT_REPWRON, 0);
+                          RN5T618_REPCNT_REPWRON,
+                          repower ? RN5T618_REPCNT_REPWRON : 0);
        /* start power-off sequence */
        regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_SLPCNT,
                           RN5T618_SLPCNT_SWPWROFF, RN5T618_SLPCNT_SWPWROFF);
 }
 
+static void rn5t618_power_off(void)
+{
+       rn5t618_trigger_poweroff_sequence(false);
+}
+
+static int rn5t618_restart(struct notifier_block *this,
+                           unsigned long mode, void *cmd)
+{
+       rn5t618_trigger_poweroff_sequence(true);
+
+       /*
+        * Re-power factor detection on PMIC side is not instant. 1ms
+        * proved to be enough time until reset takes effect.
+        */
+       mdelay(1);
+
+       return NOTIFY_DONE;
+}
+
+static const struct of_device_id rn5t618_of_match[] = {
+       { .compatible = "ricoh,rn5t567", .data = (void *)RN5T567 },
+       { .compatible = "ricoh,rn5t618", .data = (void *)RN5T618 },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rn5t618_of_match);
+
 static int rn5t618_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
+       const struct of_device_id *of_id;
        struct rn5t618 *priv;
        int ret;
 
+       of_id = of_match_device(rn5t618_of_match, &i2c->dev);
+       if (!of_id) {
+               dev_err(&i2c->dev, "Failed to find matching DT ID\n");
+               return -EINVAL;
+       }
+
        priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, priv);
+       priv->variant = (long)of_id->data;
 
        priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config);
        if (IS_ERR(priv->regmap)) {
@@ -85,9 +125,21 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       if (!pm_power_off) {
-               rn5t618_pm_power_off = priv;
-               pm_power_off = rn5t618_power_off;
+       rn5t618_pm_power_off = priv;
+       if (of_device_is_system_power_controller(i2c->dev.of_node)) {
+               if (!pm_power_off)
+                       pm_power_off = rn5t618_power_off;
+               else
+                       dev_warn(&i2c->dev, "Poweroff callback already assigned\n");
+       }
+
+       rn5t618_restart_handler.notifier_call = rn5t618_restart;
+       rn5t618_restart_handler.priority = 192;
+
+       ret = register_restart_handler(&rn5t618_restart_handler);
+       if (ret) {
+               dev_err(&i2c->dev, "cannot register restart handler, %d\n", ret);
+               return ret;
        }
 
        return 0;
@@ -105,12 +157,6 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
-static const struct of_device_id rn5t618_of_match[] = {
-       { .compatible = "ricoh,rn5t618" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rn5t618_of_match);
-
 static const struct i2c_device_id rn5t618_i2c_id[] = {
        { }
 };
@@ -129,5 +175,5 @@ static struct i2c_driver rn5t618_i2c_driver = {
 module_i2c_driver(rn5t618_i2c_driver);
 
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
-MODULE_DESCRIPTION("Ricoh RN5T618 MFD driver");
+MODULE_DESCRIPTION("Ricoh RN5T567/618 MFD driver");
 MODULE_LICENSE("GPL v2");
index c09c2b6..6c88e31 100644 (file)
@@ -645,10 +645,11 @@ config REGULATOR_RK808
          outputs which can be controlled by i2c communication.
 
 config REGULATOR_RN5T618
-       tristate "Ricoh RN5T618 voltage regulators"
+       tristate "Ricoh RN5T567/618 voltage regulators"
        depends on MFD_RN5T618
        help
-         Say y here to support the regulators found on Ricoh RN5T618 PMIC.
+         Say y here to support the regulators found on Ricoh RN5T567 or
+         RN5T618 PMIC.
 
 config REGULATOR_RT5033
        tristate "Richtek RT5033 Regulators"
index 84cce21..16c5f84 100644 (file)
@@ -1085,6 +1085,8 @@ static struct regulator_ops spmi_vs_ops = {
        .set_pull_down          = spmi_regulator_common_set_pull_down,
        .set_soft_start         = spmi_regulator_common_set_soft_start,
        .set_over_current_protection = spmi_regulator_vs_ocp,
+       .set_mode               = spmi_regulator_common_set_mode,
+       .get_mode               = spmi_regulator_common_get_mode,
 };
 
 static struct regulator_ops spmi_boost_ops = {
@@ -1496,6 +1498,7 @@ static const struct spmi_regulator_data pm8941_regulators[] = {
        { "s1", 0x1400, "vdd_s1", },
        { "s2", 0x1700, "vdd_s2", },
        { "s3", 0x1a00, "vdd_s3", },
+       { "s4", 0xa000, },
        { "l1", 0x4000, "vdd_l1_l3", },
        { "l2", 0x4100, "vdd_l2_lvs_1_2_3", },
        { "l3", 0x4200, "vdd_l1_l3", },
@@ -1523,8 +1526,8 @@ static const struct spmi_regulator_data pm8941_regulators[] = {
        { "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", },
        { "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", },
        { "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", },
-       { "mvs1", 0x8300, "vin_5vs", },
-       { "mvs2", 0x8400, "vin_5vs", },
+       { "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", },
+       { "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", },
        { }
 };
 
index b85ceb8..9c930eb 100644 (file)
@@ -46,6 +46,23 @@ static struct regulator_ops rn5t618_reg_ops = {
                .vsel_mask      = (vmask),                              \
        }
 
+static struct regulator_desc rn5t567_regulators[] = {
+       /* DCDC */
+       REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
+       REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
+       REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
+       REG(DCDC4, DC4CTL, BIT(0), DC4DAC, 0xff, 600000, 3500000, 12500),
+       /* LDO */
+       REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
+       REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
+       REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 600000, 3500000, 25000),
+       REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
+       REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 900000, 3500000, 25000),
+       /* LDO RTC */
+       REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1200000, 3500000, 25000),
+       REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
+};
+
 static struct regulator_desc rn5t618_regulators[] = {
        /* DCDC */
        REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
@@ -67,18 +84,33 @@ static int rn5t618_regulator_probe(struct platform_device *pdev)
        struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
        struct regulator_dev *rdev;
+       struct regulator_desc *regulators;
        int i;
 
+       switch (rn5t618->variant) {
+       case RN5T567:
+               regulators = rn5t567_regulators;
+               break;
+       case RN5T618:
+               regulators = rn5t618_regulators;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       config.dev = pdev->dev.parent;
+       config.regmap = rn5t618->regmap;
+
        for (i = 0; i < RN5T618_REG_NUM; i++) {
-               config.dev = pdev->dev.parent;
-               config.regmap = rn5t618->regmap;
+               if (!regulators[i].name)
+                       continue;
 
                rdev = devm_regulator_register(&pdev->dev,
-                                              &rn5t618_regulators[i],
+                                              &regulators[i],
                                               &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev, "failed to register %s regulator\n",
-                               rn5t618_regulators[i].name);
+                               regulators[i].name);
                        return PTR_ERR(rdev);
                }
        }
index adbe4fc..2d12b9a 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/mfd/tps65217.h>
 
 #define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \
-                           _t, _lr, _nlr) \
+                          _t, _lr, _nlr,  _sr, _sm)    \
        {                                               \
                .name           = _name,                \
                .id             = _id,                  \
@@ -45,6 +45,8 @@
                .volt_table     = _t,                   \
                .linear_ranges  = _lr,                  \
                .n_linear_ranges = _nlr,                \
+               .bypass_reg     = _sr,                  \
+               .bypass_mask    = _sm,                  \
        }                                               \
 
 static const unsigned int LDO1_VSEL_table[] = {
@@ -118,6 +120,35 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
        return ret;
 }
 
+static int tps65217_pmic_set_suspend_enable(struct regulator_dev *dev)
+{
+       struct tps65217 *tps = rdev_get_drvdata(dev);
+       unsigned int rid = rdev_get_id(dev);
+
+       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
+               return -EINVAL;
+
+       return tps65217_clear_bits(tps, dev->desc->bypass_reg,
+                                  dev->desc->bypass_mask,
+                                  TPS65217_PROTECT_L1);
+}
+
+static int tps65217_pmic_set_suspend_disable(struct regulator_dev *dev)
+{
+       struct tps65217 *tps = rdev_get_drvdata(dev);
+       unsigned int rid = rdev_get_id(dev);
+
+       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
+               return -EINVAL;
+
+       if (!tps->strobes[rid])
+               return -EINVAL;
+
+       return tps65217_set_bits(tps, dev->desc->bypass_reg,
+                                dev->desc->bypass_mask,
+                                tps->strobes[rid], TPS65217_PROTECT_L1);
+}
+
 /* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
 static struct regulator_ops tps65217_pmic_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
@@ -127,6 +158,8 @@ static struct regulator_ops tps65217_pmic_ops = {
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
+       .set_suspend_enable     = tps65217_pmic_set_suspend_enable,
+       .set_suspend_disable    = tps65217_pmic_set_suspend_disable,
 };
 
 /* Operations permitted on LDO1 */
@@ -138,41 +171,50 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = {
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
        .list_voltage           = regulator_list_voltage_table,
        .map_voltage            = regulator_map_voltage_ascend,
+       .set_suspend_enable     = tps65217_pmic_set_suspend_enable,
+       .set_suspend_disable    = tps65217_pmic_set_suspend_disable,
 };
 
 static const struct regulator_desc regulators[] = {
        TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1",
                           tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1,
                           TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN,
-                          NULL, tps65217_uv1_ranges, 2),
+                          NULL, tps65217_uv1_ranges, 2, TPS65217_REG_SEQ1,
+                          TPS65217_SEQ1_DC1_SEQ_MASK),
        TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2",
                           tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2,
                           TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN,
                           NULL, tps65217_uv1_ranges,
-                          ARRAY_SIZE(tps65217_uv1_ranges)),
+                          ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ1,
+                          TPS65217_SEQ1_DC2_SEQ_MASK),
        TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3",
                           tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3,
                           TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN,
-                          NULL, tps65217_uv1_ranges, 1),
+                          NULL, tps65217_uv1_ranges, 1, TPS65217_REG_SEQ2,
+                          TPS65217_SEQ2_DC3_SEQ_MASK),
        TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1",
                           tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1,
                           TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN,
-                          LDO1_VSEL_table, NULL, 0),
+                          LDO1_VSEL_table, NULL, 0, TPS65217_REG_SEQ2,
+                          TPS65217_SEQ2_LDO1_SEQ_MASK),
        TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops,
                           64, TPS65217_REG_DEFLDO2,
                           TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN,
                           NULL, tps65217_uv1_ranges,
-                          ARRAY_SIZE(tps65217_uv1_ranges)),
+                          ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ3,
+                          TPS65217_SEQ3_LDO2_SEQ_MASK),
        TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops,
                           32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
                           TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
                           NULL, tps65217_uv2_ranges,
-                          ARRAY_SIZE(tps65217_uv2_ranges)),
+                          ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ3,
+                          TPS65217_SEQ3_LDO3_SEQ_MASK),
        TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops,
                           32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
                           TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
                           NULL, tps65217_uv2_ranges,
-                          ARRAY_SIZE(tps65217_uv2_ranges)),
+                          ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ4,
+                          TPS65217_SEQ4_LDO4_SEQ_MASK),
 };
 
 static int tps65217_regulator_probe(struct platform_device *pdev)
@@ -181,13 +223,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
        struct tps65217_board *pdata = dev_get_platdata(tps->dev);
        struct regulator_dev *rdev;
        struct regulator_config config = { };
-       int i;
+       int i, ret;
+       unsigned int val;
 
        if (tps65217_chip_id(tps) != TPS65217) {
                dev_err(&pdev->dev, "Invalid tps chip version\n");
                return -ENODEV;
        }
 
+       /* Allocate memory for strobes */
+       tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
+                                   TPS65217_NUM_REGULATOR, GFP_KERNEL);
+
        platform_set_drvdata(pdev, tps);
 
        for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
@@ -205,6 +252,10 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
                                pdev->name);
                        return PTR_ERR(rdev);
                }
+
+               /* Store default strobe info */
+               ret = tps65217_reg_read(tps, regulators[i].bypass_reg, &val);
+               tps->strobes[i] = val & regulators[i].bypass_mask;
        }
 
        return 0;
index a5e5634..d1e631d 100644 (file)
@@ -31,7 +31,7 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
                           DCDC5, DCDC6, LDO1, LS3 };
 
 #define TPS65218_REGULATOR(_name, _id, _type, _ops, _n, _vr, _vm, _er, _em, \
-                           _cr, _cm, _lr, _nlr, _delay, _fuv)          \
+                          _cr, _cm, _lr, _nlr, _delay, _fuv, _sr, _sm) \
        {                                                       \
                .name                   = _name,                \
                .id                     = _id,                  \
@@ -49,7 +49,9 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
                .linear_ranges          = _lr,                  \
                .n_linear_ranges        = _nlr,                 \
                .ramp_delay             = _delay,               \
-               .fixed_uV               = _fuv                  \
+               .fixed_uV               = _fuv,                 \
+               .bypass_reg     = _sr,                          \
+               .bypass_mask    = _sm,                          \
        }                                                       \
 
 #define TPS65218_INFO(_id, _nm, _min, _max)    \
@@ -157,6 +159,40 @@ static int tps65218_pmic_disable(struct regulator_dev *dev)
                                   dev->desc->enable_mask, TPS65218_PROTECT_L1);
 }
 
+static int tps65218_pmic_set_suspend_enable(struct regulator_dev *dev)
+{
+       struct tps65218 *tps = rdev_get_drvdata(dev);
+       unsigned int rid = rdev_get_id(dev);
+
+       if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+               return -EINVAL;
+
+       return tps65218_clear_bits(tps, dev->desc->bypass_reg,
+                                  dev->desc->bypass_mask,
+                                  TPS65218_PROTECT_L1);
+}
+
+static int tps65218_pmic_set_suspend_disable(struct regulator_dev *dev)
+{
+       struct tps65218 *tps = rdev_get_drvdata(dev);
+       unsigned int rid = rdev_get_id(dev);
+
+       if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
+               return -EINVAL;
+
+       if (!tps->info[rid]->strobe) {
+               if (rid == TPS65218_DCDC_3)
+                       tps->info[rid]->strobe = 3;
+               else
+                       return -EINVAL;
+       }
+
+       return tps65218_set_bits(tps, dev->desc->bypass_reg,
+                                dev->desc->bypass_mask,
+                                tps->info[rid]->strobe,
+                                TPS65218_PROTECT_L1);
+}
+
 /* Operations permitted on DCDC1, DCDC2 */
 static struct regulator_ops tps65218_dcdc12_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
@@ -167,6 +203,8 @@ static struct regulator_ops tps65218_dcdc12_ops = {
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_enable     = tps65218_pmic_set_suspend_enable,
+       .set_suspend_disable    = tps65218_pmic_set_suspend_disable,
 };
 
 /* Operations permitted on DCDC3, DCDC4 and LDO1 */
@@ -178,6 +216,8 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
        .set_voltage_sel        = tps65218_pmic_set_voltage_sel,
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
+       .set_suspend_enable     = tps65218_pmic_set_suspend_enable,
+       .set_suspend_disable    = tps65218_pmic_set_suspend_disable,
 };
 
 static const int ls3_currents[] = { 100, 200, 500, 1000 };
@@ -247,6 +287,8 @@ static struct regulator_ops tps65218_dcdc56_pmic_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = tps65218_pmic_enable,
        .disable                = tps65218_pmic_disable,
+       .set_suspend_enable     = tps65218_pmic_set_suspend_enable,
+       .set_suspend_disable    = tps65218_pmic_set_suspend_disable,
 };
 
 static const struct regulator_desc regulators[] = {
@@ -254,42 +296,47 @@ static const struct regulator_desc regulators[] = {
                           tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC1,
                           TPS65218_CONTROL_DCDC1_MASK, TPS65218_REG_ENABLE1,
                           TPS65218_ENABLE1_DC1_EN, 0, 0, dcdc1_dcdc2_ranges,
-                          2, 4000, 0),
+                          2, 4000, 0, TPS65218_REG_SEQ3,
+                          TPS65218_SEQ3_DC1_SEQ_MASK),
        TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, REGULATOR_VOLTAGE,
                           tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC2,
                           TPS65218_CONTROL_DCDC2_MASK, TPS65218_REG_ENABLE1,
                           TPS65218_ENABLE1_DC2_EN, 0, 0, dcdc1_dcdc2_ranges,
-                          2, 4000, 0),
+                          2, 4000, 0, TPS65218_REG_SEQ3,
+                          TPS65218_SEQ3_DC2_SEQ_MASK),
        TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, REGULATOR_VOLTAGE,
                           tps65218_ldo1_dcdc34_ops, 64,
                           TPS65218_REG_CONTROL_DCDC3,
                           TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
                           TPS65218_ENABLE1_DC3_EN, 0, 0, ldo1_dcdc3_ranges, 2,
-                          0, 0),
+                          0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC3_SEQ_MASK),
        TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, REGULATOR_VOLTAGE,
                           tps65218_ldo1_dcdc34_ops, 53,
                           TPS65218_REG_CONTROL_DCDC4,
                           TPS65218_CONTROL_DCDC4_MASK, TPS65218_REG_ENABLE1,
                           TPS65218_ENABLE1_DC4_EN, 0, 0, dcdc4_ranges, 2,
-                          0, 0),
+                          0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC4_SEQ_MASK),
        TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, REGULATOR_VOLTAGE,
                           tps65218_dcdc56_pmic_ops, 1, -1, -1,
                           TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, 0,
-                          NULL, 0, 0, 1000000),
+                          NULL, 0, 0, 1000000, TPS65218_REG_SEQ5,
+                          TPS65218_SEQ5_DC5_SEQ_MASK),
        TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, REGULATOR_VOLTAGE,
                           tps65218_dcdc56_pmic_ops, 1, -1, -1,
                           TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, 0,
-                          NULL, 0, 0, 1800000),
+                          NULL, 0, 0, 1800000, TPS65218_REG_SEQ5,
+                          TPS65218_SEQ5_DC6_SEQ_MASK),
        TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, REGULATOR_VOLTAGE,
                           tps65218_ldo1_dcdc34_ops, 64,
                           TPS65218_REG_CONTROL_LDO1,
                           TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
                           TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
-                          2, 0, 0),
+                          2, 0, 0, TPS65218_REG_SEQ6,
+                          TPS65218_SEQ6_LDO1_SEQ_MASK),
        TPS65218_REGULATOR("LS3", TPS65218_LS_3, REGULATOR_CURRENT,
                           tps65218_ls3_ops, 0, 0, 0, TPS65218_REG_ENABLE2,
                           TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2,
-                          TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0),
+                          TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0, 0, 0),
 };
 
 static int tps65218_regulator_probe(struct platform_device *pdev)
@@ -300,7 +347,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
        struct regulator_dev *rdev;
        const struct of_device_id       *match;
        struct regulator_config config = { };
-       int id;
+       int id, ret;
+       unsigned int val;
 
        match = of_match_device(tps65218_of_match, &pdev->dev);
        if (!match)
@@ -327,6 +375,12 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
                return PTR_ERR(rdev);
        }
 
+       ret = tps65218_reg_read(tps, regulators[id].bypass_reg, &val);
+       if (ret)
+               return ret;
+
+       tps->info[id]->strobe = val & regulators[id].bypass_mask;
+
        return 0;
 }
 
index faeb5ee..210681d 100644 (file)
@@ -905,7 +905,7 @@ static struct regulator_ops twlsmps_ops = {
                        twl4030reg_map_mode)
 #define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
                TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
-                       0x0, TWL6030, twl6030fixed_ops, 0x0)
+                       0x0, TWL6030, twl6030fixed_ops, NULL)
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
 static const struct twlreg_info TWL4030_INFO_##label = { \
index c72d534..cadc654 100644 (file)
@@ -20,6 +20,7 @@
 #define RN5T618_OTPVER                 0x01
 #define RN5T618_IODAC                  0x02
 #define RN5T618_VINDAC                 0x03
+#define RN5T618_OUT32KEN               0x05
 #define RN5T618_CPUCNT                 0x06
 #define RN5T618_PSWR                   0x07
 #define RN5T618_PONHIS                 0x09
@@ -38,6 +39,7 @@
 #define RN5T618_DC1_SLOT               0x16
 #define RN5T618_DC2_SLOT               0x17
 #define RN5T618_DC3_SLOT               0x18
+#define RN5T618_DC4_SLOT               0x19
 #define RN5T618_LDO1_SLOT              0x1b
 #define RN5T618_LDO2_SLOT              0x1c
 #define RN5T618_LDO3_SLOT              0x1d
 #define RN5T618_DC2CTL2                        0x2f
 #define RN5T618_DC3CTL                 0x30
 #define RN5T618_DC3CTL2                        0x31
+#define RN5T618_DC4CTL                 0x32
+#define RN5T618_DC4CTL2                        0x33
 #define RN5T618_DC1DAC                 0x36
 #define RN5T618_DC2DAC                 0x37
 #define RN5T618_DC3DAC                 0x38
+#define RN5T618_DC4DAC                 0x39
 #define RN5T618_DC1DAC_SLP             0x3b
 #define RN5T618_DC2DAC_SLP             0x3c
 #define RN5T618_DC3DAC_SLP             0x3d
+#define RN5T618_DC4DAC_SLP             0x3e
 #define RN5T618_DCIREN                 0x40
 #define RN5T618_DCIRQ                  0x41
 #define RN5T618_DCIRMON                        0x42
@@ -211,6 +217,7 @@ enum {
        RN5T618_DCDC1,
        RN5T618_DCDC2,
        RN5T618_DCDC3,
+       RN5T618_DCDC4,
        RN5T618_LDO1,
        RN5T618_LDO2,
        RN5T618_LDO3,
@@ -221,8 +228,14 @@ enum {
        RN5T618_REG_NUM,
 };
 
+enum {
+       RN5T567 = 0,
+       RN5T618,
+};
+
 struct rn5t618 {
        struct regmap *regmap;
+       long variant;
 };
 
 #endif /* __LINUX_MFD_RN5T618_H */
index ac7fba4..1c88231 100644 (file)
@@ -257,6 +257,7 @@ struct tps65217 {
        unsigned long id;
        struct regulator_desc desc[TPS65217_NUM_REGULATOR];
        struct regmap *regmap;
+       u8 *strobes;
 };
 
 static inline struct tps65217 *dev_to_tps65217(struct device *dev)
index d58f3b5..7fdf532 100644 (file)
@@ -246,6 +246,7 @@ enum tps65218_irqs {
  * @name:              Voltage regulator name
  * @min_uV:            minimum micro volts
  * @max_uV:            minimum micro volts
+ * @strobe:            sequencing strobe value for the regulator
  *
  * This data is used to check the regualtor voltage limits while setting.
  */
@@ -254,6 +255,7 @@ struct tps_info {
        const char *name;
        int min_uV;
        int max_uV;
+       int strobe;
 };
 
 /**