]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge tag 'regulator-v4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Apr 2015 22:13:25 +0000 (15:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Apr 2015 22:13:25 +0000 (15:13 -0700)
Pull regulator updates from Mark Brown:
 "Another release, another set of regulator updates.  Not much of it is
  showing up in the code yet but there's been a lot of discussion going
  on about how to enhance the regulator API to work better with modern
  SoCs which have a microcontroller sitting between Linux and the
  hardware.

  I'm hopeful that'll start to come through into mainline for v4.2 but
  it's not quite there for v4.1 - what we do have (along with the usual
  small updates is) is:

   - work from Bjorn Andersson on refactoring the configuration of
     regulator loading interfaces to be useful for use with
     microcontrollers, the existing interfaces were never actually
     useful for anything as-is since nobody was willing to put enough
     data into public code.

   - a summary tree display in debugfs from Heiko Stübner.

   - support for act6000 regulators"

* tag 'regulator-v4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (34 commits)
  regulator: max8660: Handle empty regulator data
  regulator: output current-limit for all regulators in summary
  regulator: add a summary tree in debugfs
  regulator: qcom: Tidy up probe()
  regulator: qcom: Rework to single platform device
  regulator: qcom: Refactor of-parsing code
  regulator: qcom: Don't enable DRMS in driver
  regulator: max8660: fix assignment of pdata to data that becomes dead
  regulator: Defer lookup of supply to regulator_get
  mfd: max77693: Remove unused structures
  regulator: max77693: Let core parse DT and drop board files support
  regulator: Ensure unique regulator debugfs directory names
  regulator: stw481x: Remove unused fields from struct stw481x
  regulator: palmas: Add has_regen3 check for TPS659038
  regulator: constify of_device_id array
  regulator: fixes for regulator_set_optimum_mode name change
  regulator: Drop temporary regulator_set_optimum_mode wrapper
  usb: phy: phy-msm-usb: Rename regulator_set_optimum_mode
  usb: phy: ab8500-usb: Rename regulator_set_optimum_mode
  ufs: Rename of regulator_set_optimum_mode
  ...

26 files changed:
Documentation/devicetree/bindings/regulator/act8865-regulator.txt
Documentation/power/regulator/consumer.txt
drivers/gpu/drm/msm/edp/edp_ctrl.c
drivers/phy/phy-qcom-ufs.c
drivers/regulator/act8865-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/core.c
drivers/regulator/da9211-regulator.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/devres.c
drivers/regulator/max77693.c
drivers/regulator/max8660.c
drivers/regulator/palmas-regulator.c
drivers/regulator/qcom_rpm-regulator.c
drivers/regulator/stw481x-vmmc.c
drivers/regulator/wm8350-regulator.c
drivers/scsi/ufs/ufshcd.c
drivers/usb/phy/phy-ab8500-usb.c
drivers/usb/phy/phy-msm-usb.c
include/linux/mfd/max77693.h
include/linux/mfd/palmas.h
include/linux/mfd/stw481x.h
include/linux/regulator/act8865.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h

index dad6358074ac51bbd4d73b102650d038053b9cf3..e91485d1124175b807c1930b87a3d1237fe42a33 100644 (file)
@@ -2,13 +2,35 @@ ACT88xx regulators
 -------------------
 
 Required properties:
-- compatible: "active-semi,act8846" or "active-semi,act8865"
+- compatible: "active-semi,act8846" or "active-semi,act8865" or "active-semi,act8600"
 - reg: I2C slave address
 
 Optional properties:
 - system-power-controller: Telling whether or not this pmic is controlling
   the system power. See Documentation/devicetree/bindings/power/power-controller.txt .
 
+Optional input supply properties:
+- for act8600:
+  - vp1-supply: The input supply for DCDC_REG1
+  - vp2-supply: The input supply for DCDC_REG2
+  - vp3-supply: The input supply for DCDC_REG3
+  - inl-supply: The input supply for LDO_REG5, LDO_REG6, LDO_REG7 and LDO_REG8
+  SUDCDC_REG4, LDO_REG9 and LDO_REG10 do not have separate supplies.
+- for act8846:
+  - vp1-supply: The input supply for REG1
+  - vp2-supply: The input supply for REG2
+  - vp3-supply: The input supply for REG3
+  - vp4-supply: The input supply for REG4
+  - inl1-supply: The input supply for REG5, REG6 and REG7
+  - inl2-supply: The input supply for REG8 and LDO_REG9
+  - inl3-supply: The input supply for REG10, REG11 and REG12
+- for act8865:
+  - vp1-supply: The input supply for DCDC_REG1
+  - vp2-supply: The input supply for DCDC_REG2
+  - vp3-supply: The input supply for DCDC_REG3
+  - inl45-supply: The input supply for LDO_REG1 and LDO_REG2
+  - inl67-supply: The input supply for LDO_REG3 and LDO_REG4
+
 Any standard regulator properties can be used to configure the single regulator.
 
 The valid names for regulators are:
@@ -16,6 +38,9 @@ The valid names for regulators are:
        REG1, REG2, REG3, REG4, REG5, REG6, REG7, REG8, REG9, REG10, REG11, REG12
        - for act8865:
        DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4.
+       - for act8600:
+       DCDC_REG1, DCDC_REG2, DCDC_REG3, SUDCDC_REG4, LDO_REG5, LDO_REG6, LDO_REG7,
+       LDO_REG8, LDO_REG9, LDO_REG10,
 
 Example:
 --------
index 8afb236ca7653ed694af2b35e49eadbabd496152..e51564c1a140915c0646c81f8aae562f8d4baf68 100644 (file)
@@ -137,7 +137,7 @@ Indirect operating mode control.
 Consumer drivers can request a change in their supply regulator operating mode
 by calling :-
 
-int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
+int regulator_set_load(struct regulator *regulator, int load_uA);
 
 This will cause the core to recalculate the total load on the regulator (based
 on all its consumers) and change operating mode (if necessary and permitted)
index 3e246210c46f543d23e3d8b6e04560a3fe4cac74..0ec5abdba5c421b4a7604c4fa1b70ff8e3c129f9 100644 (file)
@@ -332,7 +332,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
                goto vdda_set_fail;
        }
 
-       ret = regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
+       ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
        if (ret < 0) {
                pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
                goto vdda_set_fail;
@@ -356,7 +356,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
 lvl_enable_fail:
        regulator_disable(ctrl->vdda_vreg);
 vdda_enable_fail:
-       regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
+       regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
 vdda_set_fail:
        return ret;
 }
@@ -365,7 +365,7 @@ static void edp_regulator_disable(struct edp_ctrl *ctrl)
 {
        regulator_disable(ctrl->lvl_vreg);
        regulator_disable(ctrl->vdda_vreg);
-       regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
+       regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
 }
 
 static int edp_gpio_config(struct edp_ctrl *ctrl)
index 44ee983d57fe5a2de86945606a4c63a64b88d11b..86665e9dc39993184ba2d51c6a22108a27bd7e41 100644 (file)
@@ -346,10 +346,10 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy,
                        goto out;
                }
                uA_load = on ? vreg->max_uA : 0;
-               ret = regulator_set_optimum_mode(reg, uA_load);
+               ret = regulator_set_load(reg, uA_load);
                if (ret >= 0) {
                        /*
-                        * regulator_set_optimum_mode() returns new regulator
+                        * regulator_set_load() returns new regulator
                         * mode upon success.
                         */
                        ret = 0;
index 9eec453b745d87facf2bb339194f0b6f32d80feb..2ff73d72ca34aca4d332fa1c7967d35f24471de0 100644 (file)
 #include <linux/regulator/of_regulator.h>
 #include <linux/regmap.h>
 
+/*
+ * ACT8600 Global Register Map.
+ */
+#define ACT8600_SYS_MODE       0x00
+#define ACT8600_SYS_CTRL       0x01
+#define ACT8600_DCDC1_VSET     0x10
+#define ACT8600_DCDC1_CTRL     0x12
+#define ACT8600_DCDC2_VSET     0x20
+#define ACT8600_DCDC2_CTRL     0x22
+#define ACT8600_DCDC3_VSET     0x30
+#define ACT8600_DCDC3_CTRL     0x32
+#define ACT8600_SUDCDC4_VSET   0x40
+#define ACT8600_SUDCDC4_CTRL   0x41
+#define ACT8600_LDO5_VSET      0x50
+#define ACT8600_LDO5_CTRL      0x51
+#define ACT8600_LDO6_VSET      0x60
+#define ACT8600_LDO6_CTRL      0x61
+#define ACT8600_LDO7_VSET      0x70
+#define ACT8600_LDO7_CTRL      0x71
+#define ACT8600_LDO8_VSET      0x80
+#define ACT8600_LDO8_CTRL      0x81
+#define ACT8600_LDO910_CTRL    0x91
+#define ACT8600_APCH0          0xA1
+#define ACT8600_APCH1          0xA8
+#define ACT8600_APCH2          0xA9
+#define ACT8600_APCH_STAT      0xAA
+#define ACT8600_OTG0           0xB0
+#define ACT8600_OTG1           0xB2
+
 /*
  * ACT8846 Global Register Map.
  */
 #define        ACT8865_ENA             0x80    /* ON - [7] */
 #define        ACT8865_VSEL_MASK       0x3F    /* VSET - [5:0] */
 
+
+#define ACT8600_LDO10_ENA              0x40    /* ON - [6] */
+#define ACT8600_SUDCDC_VSEL_MASK       0xFF    /* SUDCDC VSET - [7:0] */
+
 /*
  * ACT8865 voltage number
  */
 #define        ACT8865_VOLTAGE_NUM     64
+#define ACT8600_SUDCDC_VOLTAGE_NUM     255
 
 struct act8865 {
        struct regmap *regmap;
@@ -116,6 +150,13 @@ static const struct regulator_linear_range act8865_voltage_ranges[] = {
        REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
 };
 
+static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
+       REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
+       REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
+       REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
+       REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000),
+};
+
 static struct regulator_ops act8865_ops = {
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
@@ -126,9 +167,16 @@ static struct regulator_ops act8865_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
 };
 
-#define ACT88xx_REG(_name, _family, _id, _vsel_reg)                    \
+static struct regulator_ops act8865_ldo_ops = {
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+};
+
+#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply)           \
        [_family##_ID_##_id] = {                                        \
                .name                   = _name,                        \
+               .supply_name            = _supply,                      \
                .id                     = _family##_ID_##_id,           \
                .type                   = REGULATOR_VOLTAGE,            \
                .ops                    = &act8865_ops,                 \
@@ -142,33 +190,80 @@ static struct regulator_ops act8865_ops = {
                .owner                  = THIS_MODULE,                  \
        }
 
+static const struct regulator_desc act8600_regulators[] = {
+       ACT88xx_REG("DCDC1", ACT8600, DCDC1, VSET, "vp1"),
+       ACT88xx_REG("DCDC2", ACT8600, DCDC2, VSET, "vp2"),
+       ACT88xx_REG("DCDC3", ACT8600, DCDC3, VSET, "vp3"),
+       {
+               .name = "SUDCDC_REG4",
+               .id = ACT8600_ID_SUDCDC4,
+               .ops = &act8865_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = ACT8600_SUDCDC_VOLTAGE_NUM,
+               .linear_ranges = act8600_sudcdc_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(act8600_sudcdc_voltage_ranges),
+               .vsel_reg = ACT8600_SUDCDC4_VSET,
+               .vsel_mask = ACT8600_SUDCDC_VSEL_MASK,
+               .enable_reg = ACT8600_SUDCDC4_CTRL,
+               .enable_mask = ACT8865_ENA,
+               .owner = THIS_MODULE,
+       },
+       ACT88xx_REG("LDO5", ACT8600, LDO5, VSET, "inl"),
+       ACT88xx_REG("LDO6", ACT8600, LDO6, VSET, "inl"),
+       ACT88xx_REG("LDO7", ACT8600, LDO7, VSET, "inl"),
+       ACT88xx_REG("LDO8", ACT8600, LDO8, VSET, "inl"),
+       {
+               .name = "LDO_REG9",
+               .id = ACT8600_ID_LDO9,
+               .ops = &act8865_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 1,
+               .fixed_uV = 1800000,
+               .enable_reg = ACT8600_LDO910_CTRL,
+               .enable_mask = ACT8865_ENA,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO_REG10",
+               .id = ACT8600_ID_LDO10,
+               .ops = &act8865_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 1,
+               .fixed_uV = 1200000,
+               .enable_reg = ACT8600_LDO910_CTRL,
+               .enable_mask = ACT8600_LDO10_ENA,
+               .owner = THIS_MODULE,
+       },
+};
+
 static const struct regulator_desc act8846_regulators[] = {
-       ACT88xx_REG("REG1", ACT8846, REG1, VSET),
-       ACT88xx_REG("REG2", ACT8846, REG2, VSET0),
-       ACT88xx_REG("REG3", ACT8846, REG3, VSET0),
-       ACT88xx_REG("REG4", ACT8846, REG4, VSET0),
-       ACT88xx_REG("REG5", ACT8846, REG5, VSET),
-       ACT88xx_REG("REG6", ACT8846, REG6, VSET),
-       ACT88xx_REG("REG7", ACT8846, REG7, VSET),
-       ACT88xx_REG("REG8", ACT8846, REG8, VSET),
-       ACT88xx_REG("REG9", ACT8846, REG9, VSET),
-       ACT88xx_REG("REG10", ACT8846, REG10, VSET),
-       ACT88xx_REG("REG11", ACT8846, REG11, VSET),
-       ACT88xx_REG("REG12", ACT8846, REG12, VSET),
+       ACT88xx_REG("REG1", ACT8846, REG1, VSET, "vp1"),
+       ACT88xx_REG("REG2", ACT8846, REG2, VSET0, "vp2"),
+       ACT88xx_REG("REG3", ACT8846, REG3, VSET0, "vp3"),
+       ACT88xx_REG("REG4", ACT8846, REG4, VSET0, "vp4"),
+       ACT88xx_REG("REG5", ACT8846, REG5, VSET, "inl1"),
+       ACT88xx_REG("REG6", ACT8846, REG6, VSET, "inl1"),
+       ACT88xx_REG("REG7", ACT8846, REG7, VSET, "inl1"),
+       ACT88xx_REG("REG8", ACT8846, REG8, VSET, "inl2"),
+       ACT88xx_REG("REG9", ACT8846, REG9, VSET, "inl2"),
+       ACT88xx_REG("REG10", ACT8846, REG10, VSET, "inl3"),
+       ACT88xx_REG("REG11", ACT8846, REG11, VSET, "inl3"),
+       ACT88xx_REG("REG12", ACT8846, REG12, VSET, "inl3"),
 };
 
 static const struct regulator_desc act8865_regulators[] = {
-       ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1),
-       ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1),
-       ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1),
-       ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET),
-       ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET),
-       ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET),
-       ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET),
+       ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"),
+       ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"),
+       ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"),
+       ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
+       ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
+       ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
+       ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
 };
 
 #ifdef CONFIG_OF
 static const struct of_device_id act8865_dt_ids[] = {
+       { .compatible = "active-semi,act8600", .data = (void *)ACT8600 },
        { .compatible = "active-semi,act8846", .data = (void *)ACT8846 },
        { .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
        { }
@@ -200,6 +295,19 @@ static struct of_regulator_match act8865_matches[] = {
        [ACT8865_ID_LDO4]       = { .name = "LDO_REG4"},
 };
 
+static struct of_regulator_match act8600_matches[] = {
+       [ACT8600_ID_DCDC1]      = { .name = "DCDC_REG1"},
+       [ACT8600_ID_DCDC2]      = { .name = "DCDC_REG2"},
+       [ACT8600_ID_DCDC3]      = { .name = "DCDC_REG3"},
+       [ACT8600_ID_SUDCDC4]    = { .name = "SUDCDC_REG4"},
+       [ACT8600_ID_LDO5]       = { .name = "LDO_REG5"},
+       [ACT8600_ID_LDO6]       = { .name = "LDO_REG6"},
+       [ACT8600_ID_LDO7]       = { .name = "LDO_REG7"},
+       [ACT8600_ID_LDO8]       = { .name = "LDO_REG8"},
+       [ACT8600_ID_LDO9]       = { .name = "LDO_REG9"},
+       [ACT8600_ID_LDO10]      = { .name = "LDO_REG10"},
+};
+
 static int act8865_pdata_from_dt(struct device *dev,
                                 struct device_node **of_node,
                                 struct act8865_platform_data *pdata,
@@ -217,6 +325,10 @@ static int act8865_pdata_from_dt(struct device *dev,
        }
 
        switch (type) {
+       case ACT8600:
+               matches = act8600_matches;
+               num_matches = ARRAY_SIZE(act8600_matches);
+               break;
        case ACT8846:
                matches = act8846_matches;
                num_matches = ARRAY_SIZE(act8846_matches);
@@ -317,6 +429,12 @@ static int act8865_pmic_probe(struct i2c_client *client,
        }
 
        switch (type) {
+       case ACT8600:
+               regulators = act8600_regulators;
+               num_regulators = ARRAY_SIZE(act8600_regulators);
+               off_reg = -1;
+               off_mask = -1;
+               break;
        case ACT8846:
                regulators = act8846_regulators;
                num_regulators = ARRAY_SIZE(act8846_regulators);
@@ -366,7 +484,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
        }
 
        if (of_device_is_system_power_controller(dev->of_node)) {
-               if (!pm_power_off) {
+               if (!pm_power_off && (off_reg > 0)) {
                        act8865_i2c_client = client;
                        act8865->off_reg = off_reg;
                        act8865->off_mask = off_mask;
@@ -402,6 +520,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
 }
 
 static const struct i2c_device_id act8865_ids[] = {
+       { .name = "act8600", .driver_data = ACT8600 },
        { .name = "act8846", .driver_data = ACT8846 },
        { .name = "act8865", .driver_data = ACT8865 },
        { },
index 8169165904c0c67f0c04089121dee074bc8f49fa..a1d07d347c20e30af065d204d94a314d18c408e3 100644 (file)
@@ -282,6 +282,9 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
                arizona->external_dcvdd = true;
 
        ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
+
+       of_node_put(config.of_node);
+
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -289,8 +292,6 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
                return ret;
        }
 
-       of_node_put(config.of_node);
-
        platform_set_drvdata(pdev, ldo1);
 
        return 0;
index 20079006459af5a89e324e9e595e67d1df5a40d7..4116e74effa4e5a5f371c9a579bb0c97dee9d55f 100644 (file)
@@ -284,6 +284,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
        micsupp->regulator = devm_regulator_register(&pdev->dev,
                                                     desc,
                                                     &config);
+
+       of_node_put(config.of_node);
+
        if (IS_ERR(micsupp->regulator)) {
                ret = PTR_ERR(micsupp->regulator);
                dev_err(arizona->dev, "Failed to register mic supply: %d\n",
@@ -291,8 +294,6 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
                return ret;
        }
 
-       of_node_put(config.of_node);
-
        platform_set_drvdata(pdev, micsupp);
 
        return 0;
index a4a8a6dc60c470bf6911632a8b14f790cc415ef4..443eaab933fcfe680d5e402f72bbe7c55c3ae391 100644 (file)
@@ -648,10 +648,12 @@ static int drms_uA_update(struct regulator_dev *rdev)
        if (err < 0)
                return 0;
 
-       if (!rdev->desc->ops->get_optimum_mode)
+       if (!rdev->desc->ops->get_optimum_mode &&
+           !rdev->desc->ops->set_load)
                return 0;
 
-       if (!rdev->desc->ops->set_mode)
+       if (!rdev->desc->ops->set_mode &&
+           !rdev->desc->ops->set_load)
                return -EINVAL;
 
        /* get output voltage */
@@ -676,22 +678,29 @@ static int drms_uA_update(struct regulator_dev *rdev)
        list_for_each_entry(sibling, &rdev->consumer_list, list)
                current_uA += sibling->uA_load;
 
-       /* now get the optimum mode for our new total regulator load */
-       mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
-                                                 output_uV, current_uA);
+       if (rdev->desc->ops->set_load) {
+               /* set the optimum mode for our new total regulator load */
+               err = rdev->desc->ops->set_load(rdev, current_uA);
+               if (err < 0)
+                       rdev_err(rdev, "failed to set load %d\n", current_uA);
+       } else {
+               /* now get the optimum mode for our new total regulator load */
+               mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
+                                                        output_uV, current_uA);
+
+               /* check the new mode is allowed */
+               err = regulator_mode_constrain(rdev, &mode);
+               if (err < 0) {
+                       rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
+                                current_uA, input_uV, output_uV);
+                       return err;
+               }
 
-       /* check the new mode is allowed */
-       err = regulator_mode_constrain(rdev, &mode);
-       if (err < 0) {
-               rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
-                        current_uA, input_uV, output_uV);
-               return err;
+               err = rdev->desc->ops->set_mode(rdev, mode);
+               if (err < 0)
+                       rdev_err(rdev, "failed to set optimum mode %x\n", mode);
        }
 
-       err = rdev->desc->ops->set_mode(rdev, mode);
-       if (err < 0)
-               rdev_err(rdev, "failed to set optimum mode %x\n", mode);
-
        return err;
 }
 
@@ -1316,6 +1325,54 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
        return NULL;
 }
 
+static int regulator_resolve_supply(struct regulator_dev *rdev)
+{
+       struct regulator_dev *r;
+       struct device *dev = rdev->dev.parent;
+       int ret;
+
+       /* No supply to resovle? */
+       if (!rdev->supply_name)
+               return 0;
+
+       /* Supply already resolved? */
+       if (rdev->supply)
+               return 0;
+
+       r = regulator_dev_lookup(dev, rdev->supply_name, &ret);
+       if (ret == -ENODEV) {
+               /*
+                * No supply was specified for this regulator and
+                * there will never be one.
+                */
+               return 0;
+       }
+
+       if (!r) {
+               dev_err(dev, "Failed to resolve %s-supply for %s\n",
+                       rdev->supply_name, rdev->desc->name);
+               return -EPROBE_DEFER;
+       }
+
+       /* Recursively resolve the supply of the supply */
+       ret = regulator_resolve_supply(r);
+       if (ret < 0)
+               return ret;
+
+       ret = set_supply(rdev, r);
+       if (ret < 0)
+               return ret;
+
+       /* Cascade always-on state to supply */
+       if (_regulator_is_enabled(rdev)) {
+               ret = regulator_enable(rdev->supply);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
                                        bool exclusive, bool allow_dummy)
@@ -1385,6 +1442,12 @@ found:
                goto out;
        }
 
+       ret = regulator_resolve_supply(rdev);
+       if (ret < 0) {
+               regulator = ERR_PTR(ret);
+               goto out;
+       }
+
        if (!try_module_get(rdev->owner))
                goto out;
 
@@ -2998,7 +3061,7 @@ unsigned int regulator_get_mode(struct regulator *regulator)
 EXPORT_SYMBOL_GPL(regulator_get_mode);
 
 /**
- * regulator_set_optimum_mode - set regulator optimum operating mode
+ * regulator_set_load - set regulator load
  * @regulator: regulator source
  * @uA_load: load current
  *
@@ -3021,9 +3084,9 @@ EXPORT_SYMBOL_GPL(regulator_get_mode);
  * DRMS will sum the total requested load on the regulator and change
  * to the most efficient operating mode if platform constraints allow.
  *
- * Returns the new regulator mode or error.
+ * On error a negative errno is returned.
  */
-int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
+int regulator_set_load(struct regulator *regulator, int uA_load)
 {
        struct regulator_dev *rdev = regulator->rdev;
        int ret;
@@ -3035,7 +3098,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
+EXPORT_SYMBOL_GPL(regulator_set_load);
 
 /**
  * regulator_allow_bypass - allow the regulator to go into bypass mode
@@ -3499,7 +3562,18 @@ static struct class regulator_class = {
 
 static void rdev_init_debugfs(struct regulator_dev *rdev)
 {
-       rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
+       struct device *parent = rdev->dev.parent;
+       const char *rname = rdev_get_name(rdev);
+       char name[NAME_MAX];
+
+       /* Avoid duplicate debugfs directory names */
+       if (parent && rname == rdev->desc->name) {
+               snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
+                        rname);
+               rname = name;
+       }
+
+       rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
        if (!rdev->debugfs) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
                return;
@@ -3533,7 +3607,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
        struct regulator_dev *rdev;
        struct device *dev;
        int ret, i;
-       const char *supply = NULL;
 
        if (regulator_desc == NULL || cfg == NULL)
                return ERR_PTR(-EINVAL);
@@ -3641,41 +3714,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
                goto scrub;
 
        if (init_data && init_data->supply_regulator)
-               supply = init_data->supply_regulator;
+               rdev->supply_name = init_data->supply_regulator;
        else if (regulator_desc->supply_name)
-               supply = regulator_desc->supply_name;
-
-       if (supply) {
-               struct regulator_dev *r;
+               rdev->supply_name = regulator_desc->supply_name;
 
-               r = regulator_dev_lookup(dev, supply, &ret);
-
-               if (ret == -ENODEV) {
-                       /*
-                        * No supply was specified for this regulator and
-                        * there will never be one.
-                        */
-                       ret = 0;
-                       goto add_dev;
-               } else if (!r) {
-                       dev_err(dev, "Failed to find supply %s\n", supply);
-                       ret = -EPROBE_DEFER;
-                       goto scrub;
-               }
-
-               ret = set_supply(rdev, r);
-               if (ret < 0)
-                       goto scrub;
-
-               /* Enable supply if rail is enabled */
-               if (_regulator_is_enabled(rdev)) {
-                       ret = regulator_enable(rdev->supply);
-                       if (ret < 0)
-                               goto scrub;
-               }
-       }
-
-add_dev:
        /* add consumers devices */
        if (init_data) {
                for (i = 0; i < init_data->num_consumer_supplies; i++) {
@@ -3702,8 +3744,6 @@ unset_supplies:
        unset_regulator_supplies(rdev);
 
 scrub:
-       if (rdev->supply)
-               _regulator_put(rdev->supply);
        regulator_ena_gpio_free(rdev);
        kfree(rdev->constraints);
 wash:
@@ -3936,6 +3976,110 @@ static const struct file_operations supply_map_fops = {
 #endif
 };
 
+#ifdef CONFIG_DEBUG_FS
+static void regulator_summary_show_subtree(struct seq_file *s,
+                                          struct regulator_dev *rdev,
+                                          int level)
+{
+       struct list_head *list = s->private;
+       struct regulator_dev *child;
+       struct regulation_constraints *c;
+       struct regulator *consumer;
+
+       if (!rdev)
+               return;
+
+       seq_printf(s, "%*s%-*s %3d %4d %6d ",
+                  level * 3 + 1, "",
+                  30 - level * 3, rdev_get_name(rdev),
+                  rdev->use_count, rdev->open_count, rdev->bypass_count);
+
+       seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000);
+       seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000);
+
+       c = rdev->constraints;
+       if (c) {
+               switch (rdev->desc->type) {
+               case REGULATOR_VOLTAGE:
+                       seq_printf(s, "%5dmV %5dmV ",
+                                  c->min_uV / 1000, c->max_uV / 1000);
+                       break;
+               case REGULATOR_CURRENT:
+                       seq_printf(s, "%5dmA %5dmA ",
+                                  c->min_uA / 1000, c->max_uA / 1000);
+                       break;
+               }
+       }
+
+       seq_puts(s, "\n");
+
+       list_for_each_entry(consumer, &rdev->consumer_list, list) {
+               if (consumer->dev->class == &regulator_class)
+                       continue;
+
+               seq_printf(s, "%*s%-*s ",
+                          (level + 1) * 3 + 1, "",
+                          30 - (level + 1) * 3, dev_name(consumer->dev));
+
+               switch (rdev->desc->type) {
+               case REGULATOR_VOLTAGE:
+                       seq_printf(s, "%37dmV %5dmV",
+                                  consumer->min_uV / 1000,
+                                  consumer->max_uV / 1000);
+                       break;
+               case REGULATOR_CURRENT:
+                       break;
+               }
+
+               seq_puts(s, "\n");
+       }
+
+       list_for_each_entry(child, list, list) {
+               /* handle only non-root regulators supplied by current rdev */
+               if (!child->supply || child->supply->rdev != rdev)
+                       continue;
+
+               regulator_summary_show_subtree(s, child, level + 1);
+       }
+}
+
+static int regulator_summary_show(struct seq_file *s, void *data)
+{
+       struct list_head *list = s->private;
+       struct regulator_dev *rdev;
+
+       seq_puts(s, " regulator                      use open bypass voltage current     min     max\n");
+       seq_puts(s, "-------------------------------------------------------------------------------\n");
+
+       mutex_lock(&regulator_list_mutex);
+
+       list_for_each_entry(rdev, list, list) {
+               if (rdev->supply)
+                       continue;
+
+               regulator_summary_show_subtree(s, rdev, 0);
+       }
+
+       mutex_unlock(&regulator_list_mutex);
+
+       return 0;
+}
+
+static int regulator_summary_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, regulator_summary_show, inode->i_private);
+}
+#endif
+
+static const struct file_operations regulator_summary_fops = {
+#ifdef CONFIG_DEBUG_FS
+       .open           = regulator_summary_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+#endif
+};
+
 static int __init regulator_init(void)
 {
        int ret;
@@ -3949,6 +4093,9 @@ static int __init regulator_init(void)
        debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
                            &supply_map_fops);
 
+       debugfs_create_file("regulator_summary", 0444, debugfs_root,
+                           &regulator_list, &regulator_summary_fops);
+
        regulator_dummy_init();
 
        return ret;
index 01343419555ee3363d7bc0d3c10df731fbd74587..df79e4b1946e7d6e966e5759e323f67fbacfb021 100644 (file)
@@ -305,8 +305,7 @@ static irqreturn_t da9211_irq_handler(int irq, void *data)
 
        if (reg_val & DA9211_E_OV_CURR_A) {
                regulator_notifier_call_chain(chip->rdev[0],
-                       REGULATOR_EVENT_OVER_CURRENT,
-                       rdev_get_drvdata(chip->rdev[0]));
+                       REGULATOR_EVENT_OVER_CURRENT, NULL);
 
                err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
                        DA9211_E_OV_CURR_A);
@@ -318,8 +317,7 @@ static irqreturn_t da9211_irq_handler(int irq, void *data)
 
        if (reg_val & DA9211_E_OV_CURR_B) {
                regulator_notifier_call_chain(chip->rdev[1],
-                       REGULATOR_EVENT_OVER_CURRENT,
-                       rdev_get_drvdata(chip->rdev[1]));
+                       REGULATOR_EVENT_OVER_CURRENT, NULL);
 
                err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
                        DA9211_E_OV_CURR_B);
@@ -344,7 +342,7 @@ static int da9211_regulator_init(struct da9211 *chip)
 
        ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
        if (ret < 0) {
-               dev_err(chip->dev, "Failed to read CONTROL_E reg: %d\n", ret);
+               dev_err(chip->dev, "Failed to read CONFIG_E reg: %d\n", ret);
                return ret;
        }
 
index 2d16b9f16de73f5ce42ffb2370bba98c9bccf20b..3963dfad766c78a5c564927487fe20117898ab97 100644 (file)
@@ -95,14 +95,9 @@ void ux500_regulator_resume_debug(void)
 
 static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       int err;
-
        /* print power state count */
-       err = seq_printf(s, "ux500-regulator power state count: %i\n",
-               power_state_active_get());
-       if (err < 0)
-               dev_err(dev, "seq_printf overflow\n");
+       seq_printf(s, "ux500-regulator power state count: %i\n",
+                  power_state_active_get());
 
        return 0;
 }
@@ -124,19 +119,11 @@ static const struct file_operations ux500_regulator_power_state_cnt_fops = {
 
 static int ux500_regulator_status_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       int err;
        int i;
 
        /* print dump header */
-       err = seq_puts(s, "ux500-regulator status:\n");
-       if (err < 0)
-               dev_err(dev, "seq_puts overflow\n");
-
-       err = seq_printf(s, "%31s : %8s : %8s\n", "current",
-               "before", "after");
-       if (err < 0)
-               dev_err(dev, "seq_printf overflow\n");
+       seq_puts(s, "ux500-regulator status:\n");
+       seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
 
        for (i = 0; i < rdebug.num_regulators; i++) {
                struct dbx500_regulator_info *info;
@@ -144,12 +131,11 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
                info = &rdebug.regulator_array[i];
 
                /* print status */
-               err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name,
-                       info->is_enabled ? "enabled" : "disabled",
-                       rdebug.state_before_suspend[i] ? "enabled" : "disabled",
-                       rdebug.state_after_suspend[i] ? "enabled" : "disabled");
-               if (err < 0)
-                       dev_err(dev, "seq_printf overflow\n");
+               seq_printf(s, "%20s : %8s : %8s : %8s\n",
+                          info->desc.name,
+                          info->is_enabled ? "enabled" : "disabled",
+                          rdebug.state_before_suspend[i] ? "enabled" : "disabled",
+                          rdebug.state_after_suspend[i] ? "enabled" : "disabled");
        }
 
        return 0;
index 8f785bc9e5108519525f0908b3d3e3d097b67816..6ec1d400adae7e444102266385171c5d787110a3 100644 (file)
@@ -413,3 +413,88 @@ void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
                devm_regulator_unregister_supply_alias(dev, id[i]);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
+
+struct regulator_notifier_match {
+       struct regulator *regulator;
+       struct notifier_block *nb;
+};
+
+static int devm_regulator_match_notifier(struct device *dev, void *res,
+                                        void *data)
+{
+       struct regulator_notifier_match *match = res;
+       struct regulator_notifier_match *target = data;
+
+       return match->regulator == target->regulator && match->nb == target->nb;
+}
+
+static void devm_regulator_destroy_notifier(struct device *dev, void *res)
+{
+       struct regulator_notifier_match *match = res;
+
+       regulator_unregister_notifier(match->regulator, match->nb);
+}
+
+/**
+ * devm_regulator_register_notifier - Resource managed
+ * regulator_register_notifier
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * The notifier will be registers under the consumer device and be
+ * automatically be unregistered when the source device is unbound.
+ */
+int devm_regulator_register_notifier(struct regulator *regulator,
+                                    struct notifier_block *nb)
+{
+       struct regulator_notifier_match *match;
+       int ret;
+
+       match = devres_alloc(devm_regulator_destroy_notifier,
+                            sizeof(struct regulator_notifier_match),
+                            GFP_KERNEL);
+       if (!match)
+               return -ENOMEM;
+
+       match->regulator = regulator;
+       match->nb = nb;
+
+       ret = regulator_register_notifier(regulator, nb);
+       if (ret < 0) {
+               devres_free(match);
+               return ret;
+       }
+
+       devres_add(regulator->dev, match);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
+
+/**
+ * devm_regulator_unregister_notifier - Resource managed
+ * regulator_unregister_notifier()
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * Unregister a notifier registered with devm_regulator_register_notifier().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_notifier(struct regulator *regulator,
+                                       struct notifier_block *nb)
+{
+       struct regulator_notifier_match match;
+       int rc;
+
+       match.regulator = regulator;
+       match.nb = nb;
+
+       rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
+                           devm_regulator_match_notifier, &match);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
index 07b313e51b2184dc706c754d16ddd48fdba08031..9665a488e2f16e7ffde015d9682521b63f822f62 100644 (file)
@@ -128,6 +128,8 @@ static struct regulator_ops max77693_charger_ops = {
 #define regulator_desc_esafeout(_num)  {                       \
        .name           = "ESAFEOUT"#_num,                      \
        .id             = MAX77693_ESAFEOUT##_num,              \
+       .of_match       = of_match_ptr("ESAFEOUT"#_num),        \
+       .regulators_node        = of_match_ptr("regulators"),   \
        .n_voltages     = 4,                                    \
        .ops            = &max77693_safeout_ops,                \
        .type           = REGULATOR_VOLTAGE,                    \
@@ -145,6 +147,8 @@ static const struct regulator_desc regulators[] = {
        {
                .name = "CHARGER",
                .id = MAX77693_CHARGER,
+               .of_match = of_match_ptr("CHARGER"),
+               .regulators_node = of_match_ptr("regulators"),
                .ops = &max77693_charger_ops,
                .type = REGULATOR_CURRENT,
                .owner = THIS_MODULE,
@@ -154,102 +158,23 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
-#ifdef CONFIG_OF
-static int max77693_pmic_dt_parse_rdata(struct device *dev,
-                                       struct max77693_regulator_data **rdata)
-{
-       struct device_node *np;
-       struct of_regulator_match *rmatch;
-       struct max77693_regulator_data *tmp;
-       int i, matched = 0;
-
-       np = of_get_child_by_name(dev->parent->of_node, "regulators");
-       if (!np)
-               return -EINVAL;
-
-       rmatch = devm_kzalloc(dev,
-                sizeof(*rmatch) * ARRAY_SIZE(regulators), GFP_KERNEL);
-       if (!rmatch) {
-               of_node_put(np);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(regulators); i++)
-               rmatch[i].name = regulators[i].name;
-
-       matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(regulators));
-       of_node_put(np);
-       if (matched <= 0)
-               return matched;
-       *rdata = devm_kzalloc(dev, sizeof(**rdata) * matched, GFP_KERNEL);
-       if (!(*rdata))
-               return -ENOMEM;
-
-       tmp = *rdata;
-
-       for (i = 0; i < matched; i++) {
-               tmp->initdata = rmatch[i].init_data;
-               tmp->of_node = rmatch[i].of_node;
-               tmp->id = regulators[i].id;
-               tmp++;
-       }
-
-       return matched;
-}
-#else
-static int max77693_pmic_dt_parse_rdata(struct device *dev,
-                                       struct max77693_regulator_data **rdata)
-{
-       return 0;
-}
-#endif /* CONFIG_OF */
-
-static int max77693_pmic_init_rdata(struct device *dev,
-                                   struct max77693_regulator_data **rdata)
-{
-       struct max77693_platform_data *pdata;
-       int num_regulators = 0;
-
-       pdata = dev_get_platdata(dev->parent);
-       if (pdata) {
-               *rdata = pdata->regulators;
-               num_regulators = pdata->num_regulators;
-       }
-
-       if (!(*rdata) && dev->parent->of_node)
-               num_regulators = max77693_pmic_dt_parse_rdata(dev, rdata);
-
-       return num_regulators;
-}
-
 static int max77693_pmic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77693_regulator_data *rdata = NULL;
-       int num_rdata, i;
+       int i;
        struct regulator_config config = { };
 
-       num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
-       if (!rdata || num_rdata <= 0) {
-               dev_err(&pdev->dev, "No init data supplied.\n");
-               return -ENODEV;
-       }
-
-       config.dev = &pdev->dev;
+       config.dev = iodev->dev;
        config.regmap = iodev->regmap;
 
-       for (i = 0; i < num_rdata; i++) {
-               int id = rdata[i].id;
+       for (i = 0; i < ARRAY_SIZE(regulators); i++) {
                struct regulator_dev *rdev;
 
-               config.init_data = rdata[i].initdata;
-               config.of_node = rdata[i].of_node;
-
                rdev = devm_regulator_register(&pdev->dev,
-                                               &regulators[id], &config);
+                                               &regulators[i], &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
-                               "Failed to initialize regulator-%d\n", id);
+                               "Failed to initialize regulator-%d\n", i);
                        return PTR_ERR(rdev);
                }
        }
index 7eee2ca1854183b05e4d4b08180020afc7337033..4071d74fa8288ce27d2cdd34505c006474e2f869 100644 (file)
@@ -382,7 +382,7 @@ static int max8660_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
 {
        struct device *dev = &client->dev;
-       struct max8660_platform_data *pdata = dev_get_platdata(dev);
+       struct max8660_platform_data pdata_of, *pdata = dev_get_platdata(dev);
        struct regulator_config config = { };
        struct max8660 *max8660;
        int boot_on, i, id, ret = -EINVAL;
@@ -391,7 +391,6 @@ static int max8660_probe(struct i2c_client *client,
 
        if (dev->of_node && !pdata) {
                const struct of_device_id *id;
-               struct max8660_platform_data pdata_of;
 
                id = of_match_device(of_match_ptr(max8660_dt_ids), dev);
                if (!id)
@@ -443,9 +442,9 @@ static int max8660_probe(struct i2c_client *client,
        for (i = 0; i < pdata->num_subdevs; i++) {
 
                if (!pdata->subdevs[i].platform_data)
-                       return ret;
-
-               boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
+                       boot_on = false;
+               else
+                       boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
 
                switch (pdata->subdevs[i].id) {
                case MAX8660_V3:
index 18198316b6cf15c406c6f9eb243bc39601b97979..8217613807d37f3dfa2f90f796a394094fdebe16 100644 (file)
@@ -916,6 +916,9 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic,
                            (id == PALMAS_REG_LDO6))
                                desc->enable_time = 2000;
                } else {
+                       if (!ddata->has_regen3 && id == PALMAS_REG_REGEN3)
+                               continue;
+
                        desc->n_voltages = 1;
                        if (reg_init && reg_init->roof_floor)
                                desc->ops = &palmas_ops_ext_control_extreg;
@@ -1398,6 +1401,7 @@ static struct palmas_pmic_driver_data palmas_ddata = {
        .ldo_begin = PALMAS_REG_LDO1,
        .ldo_end = PALMAS_REG_LDOUSB,
        .max_reg = PALMAS_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = palmas_generic_regs_info,
        .palmas_matches = palmas_matches,
        .sleep_req_info = palma_sleep_req_info,
@@ -1411,6 +1415,7 @@ static struct palmas_pmic_driver_data tps65917_ddata = {
        .ldo_begin = TPS65917_REG_LDO1,
        .ldo_end = TPS65917_REG_LDO5,
        .max_reg = TPS65917_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = tps65917_regs_info,
        .palmas_matches = tps65917_matches,
        .sleep_req_info = tps65917_sleep_req_info,
@@ -1505,7 +1510,7 @@ static void palmas_dt_to_pdata(struct device *dev,
        pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
-static struct of_device_id of_palmas_match_tbl[] = {
+static const struct of_device_id of_palmas_match_tbl[] = {
        {
                .compatible = "ti,palmas-pmic",
                .data = &palmas_ddata,
@@ -1572,9 +1577,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
        if (!pmic)
                return -ENOMEM;
 
-       if (of_device_is_compatible(node, "ti,tps659038-pmic"))
+       if (of_device_is_compatible(node, "ti,tps659038-pmic")) {
                palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
                                                        TPS659038_REGEN2_CTRL;
+               palmas_ddata.has_regen3 = false;
+       }
 
        pmic->dev = &pdev->dev;
        pmic->palmas = palmas;
index 00c5cc3d954636784a14f5d3c03c7ffcff7896b5..e254272585b24f26b90382121de44ee8e7695565 100644 (file)
@@ -393,6 +393,28 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
        return vreg->is_enabled;
 }
 
+static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       const struct rpm_reg_parts *parts = vreg->parts;
+       const struct request_member *req = &parts->ia;
+       int load_mA = load_uA / 1000;
+       int max_mA = req->mask >> req->shift;
+       int ret;
+
+       if (req->mask == 0)
+               return -EINVAL;
+
+       if (load_mA > max_mA)
+               load_mA = max_mA;
+
+       mutex_lock(&vreg->lock);
+       ret = rpm_reg_write(vreg, req, load_mA);
+       mutex_unlock(&vreg->lock);
+
+       return ret;
+}
+
 static struct regulator_ops uV_ops = {
        .list_voltage = regulator_list_voltage_linear_range,
 
@@ -402,6 +424,8 @@ static struct regulator_ops uV_ops = {
        .enable = rpm_reg_uV_enable,
        .disable = rpm_reg_uV_disable,
        .is_enabled = rpm_reg_is_enabled,
+
+       .set_load = rpm_reg_set_load,
 };
 
 static struct regulator_ops mV_ops = {
@@ -413,6 +437,8 @@ static struct regulator_ops mV_ops = {
        .enable = rpm_reg_mV_enable,
        .disable = rpm_reg_mV_disable,
        .is_enabled = rpm_reg_is_enabled,
+
+       .set_load = rpm_reg_set_load,
 };
 
 static struct regulator_ops switch_ops = {
@@ -581,31 +607,6 @@ static const struct qcom_rpm_reg smb208_smps = {
        .supports_force_mode_bypass = false,
 };
 
-static const struct of_device_id rpm_of_match[] = {
-       { .compatible = "qcom,rpm-pm8058-pldo",     .data = &pm8058_pldo },
-       { .compatible = "qcom,rpm-pm8058-nldo",     .data = &pm8058_nldo },
-       { .compatible = "qcom,rpm-pm8058-smps",     .data = &pm8058_smps },
-       { .compatible = "qcom,rpm-pm8058-ncp",      .data = &pm8058_ncp },
-       { .compatible = "qcom,rpm-pm8058-switch",   .data = &pm8058_switch },
-
-       { .compatible = "qcom,rpm-pm8901-pldo",     .data = &pm8901_pldo },
-       { .compatible = "qcom,rpm-pm8901-nldo",     .data = &pm8901_nldo },
-       { .compatible = "qcom,rpm-pm8901-ftsmps",   .data = &pm8901_ftsmps },
-       { .compatible = "qcom,rpm-pm8901-switch",   .data = &pm8901_switch },
-
-       { .compatible = "qcom,rpm-pm8921-pldo",     .data = &pm8921_pldo },
-       { .compatible = "qcom,rpm-pm8921-nldo",     .data = &pm8921_nldo },
-       { .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 },
-       { .compatible = "qcom,rpm-pm8921-smps",     .data = &pm8921_smps },
-       { .compatible = "qcom,rpm-pm8921-ftsmps",   .data = &pm8921_ftsmps },
-       { .compatible = "qcom,rpm-pm8921-ncp",      .data = &pm8921_ncp },
-       { .compatible = "qcom,rpm-pm8921-switch",   .data = &pm8921_switch },
-
-       { .compatible = "qcom,rpm-smb208", .data = &smb208_smps },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rpm_of_match);
-
 static int rpm_reg_set(struct qcom_rpm_reg *vreg,
                       const struct request_member *req,
                       const int value)
@@ -619,7 +620,9 @@ static int rpm_reg_set(struct qcom_rpm_reg *vreg,
        return 0;
 }
 
-static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
+static int rpm_reg_of_parse_freq(struct device *dev,
+                                struct device_node *node,
+                                struct qcom_rpm_reg *vreg)
 {
        static const int freq_table[] = {
                19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
@@ -633,7 +636,7 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
        int i;
 
        key = "qcom,switch-mode-frequency";
-       ret = of_property_read_u32(dev->of_node, key, &freq);
+       ret = of_property_read_u32(node, key, &freq);
        if (ret) {
                dev_err(dev, "regulator requires %s property\n", key);
                return -EINVAL;
@@ -650,84 +653,40 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
        return -EINVAL;
 }
 
-static int rpm_reg_probe(struct platform_device *pdev)
+static int rpm_reg_of_parse(struct device_node *node,
+                           const struct regulator_desc *desc,
+                           struct regulator_config *config)
 {
-       struct regulator_init_data *initdata;
-       const struct qcom_rpm_reg *template;
-       const struct of_device_id *match;
-       struct regulator_config config = { };
-       struct regulator_dev *rdev;
-       struct qcom_rpm_reg *vreg;
+       struct qcom_rpm_reg *vreg = config->driver_data;
+       struct device *dev = config->dev;
        const char *key;
        u32 force_mode;
        bool pwm;
        u32 val;
        int ret;
 
-       match = of_match_device(rpm_of_match, &pdev->dev);
-       template = match->data;
-
-       vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
-       if (!vreg) {
-               dev_err(&pdev->dev, "failed to allocate vreg\n");
-               return -ENOMEM;
-       }
-       memcpy(vreg, template, sizeof(*vreg));
-       mutex_init(&vreg->lock);
-       vreg->dev = &pdev->dev;
-       vreg->desc.id = -1;
-       vreg->desc.owner = THIS_MODULE;
-       vreg->desc.type = REGULATOR_VOLTAGE;
-       vreg->desc.name = pdev->dev.of_node->name;
-       vreg->desc.supply_name = "vin";
-
-       vreg->rpm = dev_get_drvdata(pdev->dev.parent);
-       if (!vreg->rpm) {
-               dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
-               return -ENODEV;
-       }
-
-       initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
-                                             &vreg->desc);
-       if (!initdata)
-               return -EINVAL;
-
-       key = "reg";
-       ret = of_property_read_u32(pdev->dev.of_node, key, &val);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to read %s\n", key);
-               return ret;
-       }
-       vreg->resource = val;
-
-       if ((vreg->parts->uV.mask || vreg->parts->mV.mask) &&
-           (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) {
-               dev_err(&pdev->dev, "no voltage specified for regulator\n");
-               return -EINVAL;
-       }
-
        key = "bias-pull-down";
-       if (of_property_read_bool(pdev->dev.of_node, key)) {
+       if (of_property_read_bool(node, key)) {
                ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
                if (ret) {
-                       dev_err(&pdev->dev, "%s is invalid", key);
+                       dev_err(dev, "%s is invalid", key);
                        return ret;
                }
        }
 
        if (vreg->parts->freq.mask) {
-               ret = rpm_reg_of_parse_freq(&pdev->dev, vreg);
+               ret = rpm_reg_of_parse_freq(dev, node, vreg);
                if (ret < 0)
                        return ret;
        }
 
        if (vreg->parts->pm.mask) {
                key = "qcom,power-mode-hysteretic";
-               pwm = !of_property_read_bool(pdev->dev.of_node, key);
+               pwm = !of_property_read_bool(node, key);
 
                ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to set power mode\n");
+                       dev_err(dev, "failed to set power mode\n");
                        return ret;
                }
        }
@@ -736,11 +695,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
                force_mode = -1;
 
                key = "qcom,force-mode";
-               ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+               ret = of_property_read_u32(node, key, &val);
                if (ret == -EINVAL) {
                        val = QCOM_RPM_FORCE_MODE_NONE;
                } else if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to read %s\n", key);
+                       dev_err(dev, "failed to read %s\n", key);
                        return ret;
                }
 
@@ -775,25 +734,192 @@ static int rpm_reg_probe(struct platform_device *pdev)
                }
 
                if (force_mode == -1) {
-                       dev_err(&pdev->dev, "invalid force mode\n");
+                       dev_err(dev, "invalid force mode\n");
                        return -EINVAL;
                }
 
                ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to set force mode\n");
+                       dev_err(dev, "failed to set force mode\n");
                        return ret;
                }
        }
 
-       config.dev = &pdev->dev;
-       config.init_data = initdata;
-       config.driver_data = vreg;
-       config.of_node = pdev->dev.of_node;
-       rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "can't register regulator\n");
-               return PTR_ERR(rdev);
+       return 0;
+}
+
+struct rpm_regulator_data {
+       const char *name;
+       int resource;
+       const struct qcom_rpm_reg *template;
+       const char *supply;
+};
+
+static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
+       { "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs" },
+       { "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },
+       { "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l3",   QCOM_RPM_PM8058_LDO3,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l4",   QCOM_RPM_PM8058_LDO4,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l5",   QCOM_RPM_PM8058_LDO5,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l6",   QCOM_RPM_PM8058_LDO6,   &pm8058_pldo, "vdd_l6_l7" },
+       { "l7",   QCOM_RPM_PM8058_LDO7,   &pm8058_pldo, "vdd_l6_l7" },
+       { "l8",   QCOM_RPM_PM8058_LDO8,   &pm8058_pldo, "vdd_l8" },
+       { "l9",   QCOM_RPM_PM8058_LDO9,   &pm8058_pldo, "vdd_l9" },
+       { "l10",  QCOM_RPM_PM8058_LDO10,  &pm8058_pldo, "vdd_l10" },
+       { "l11",  QCOM_RPM_PM8058_LDO11,  &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l12",  QCOM_RPM_PM8058_LDO12,  &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l13",  QCOM_RPM_PM8058_LDO13,  &pm8058_pldo, "vdd_l13_l16" },
+       { "l14",  QCOM_RPM_PM8058_LDO14,  &pm8058_pldo, "vdd_l14_l15" },
+       { "l15",  QCOM_RPM_PM8058_LDO15,  &pm8058_pldo, "vdd_l14_l15" },
+       { "l16",  QCOM_RPM_PM8058_LDO16,  &pm8058_pldo, "vdd_l13_l16" },
+       { "l17",  QCOM_RPM_PM8058_LDO17,  &pm8058_pldo, "vdd_l17_l18" },
+       { "l18",  QCOM_RPM_PM8058_LDO18,  &pm8058_pldo, "vdd_l17_l18" },
+       { "l19",  QCOM_RPM_PM8058_LDO19,  &pm8058_pldo, "vdd_l19_l20" },
+       { "l20",  QCOM_RPM_PM8058_LDO20,  &pm8058_pldo, "vdd_l19_l20" },
+       { "l21",  QCOM_RPM_PM8058_LDO21,  &pm8058_nldo, "vdd_l21" },
+       { "l22",  QCOM_RPM_PM8058_LDO22,  &pm8058_nldo, "vdd_l22" },
+       { "l23",  QCOM_RPM_PM8058_LDO23,  &pm8058_nldo, "vdd_l23_l24_l25" },
+       { "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },
+       { "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },
+
+       { "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
+       { "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
+       { "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
+       { "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
+       { "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
+
+       { "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" },
+       { "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" },
+
+       { "ncp",  QCOM_RPM_PM8058_NCP, &pm8058_ncp, "vdd_ncp" },
+       { }
+};
+
+static const struct rpm_regulator_data rpm_pm8901_regulators[] = {
+       { "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },
+       { "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },
+       { "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },
+       { "l3",   QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" },
+       { "l4",   QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" },
+       { "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },
+       { "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },
+
+       { "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
+       { "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
+       { "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
+       { "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
+       { "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
+
+       { "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" },
+       { "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" },
+       { "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" },
+       { "lvs3", QCOM_RPM_PM8901_LVS3, &pm8901_switch, "lvs3_in" },
+
+       { "mvs", QCOM_RPM_PM8901_MVS, &pm8901_switch, "mvs_in" },
+       { }
+};
+
+static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
+       { "s1",  QCOM_RPM_PM8921_SMPS1, &pm8921_smps, "vdd_s1" },
+       { "s2",  QCOM_RPM_PM8921_SMPS2, &pm8921_smps, "vdd_s2" },
+       { "s3",  QCOM_RPM_PM8921_SMPS3, &pm8921_smps },
+       { "s4",  QCOM_RPM_PM8921_SMPS4, &pm8921_smps, "vdd_s4" },
+       { "s7",  QCOM_RPM_PM8921_SMPS7, &pm8921_smps, "vdd_s7" },
+       { "s8",  QCOM_RPM_PM8921_SMPS8, &pm8921_smps, "vdd_s8"  },
+
+       { "l1",  QCOM_RPM_PM8921_LDO1, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l2",  QCOM_RPM_PM8921_LDO2, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l3",  QCOM_RPM_PM8921_LDO3, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l4",  QCOM_RPM_PM8921_LDO4, &pm8921_pldo, "vdd_l4_l14" },
+       { "l5",  QCOM_RPM_PM8921_LDO5, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l6",  QCOM_RPM_PM8921_LDO6, &pm8921_pldo, "vdd_l6_l7" },
+       { "l7",  QCOM_RPM_PM8921_LDO7, &pm8921_pldo, "vdd_l6_l7" },
+       { "l8",  QCOM_RPM_PM8921_LDO8, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l9",  QCOM_RPM_PM8921_LDO9, &pm8921_pldo, "vdd_l9_l11" },
+       { "l10", QCOM_RPM_PM8921_LDO10, &pm8921_pldo, "vdd_l10_l22" },
+       { "l11", QCOM_RPM_PM8921_LDO11, &pm8921_pldo, "vdd_l9_l11" },
+       { "l12", QCOM_RPM_PM8921_LDO12, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l14", QCOM_RPM_PM8921_LDO14, &pm8921_pldo, "vdd_l4_l14" },
+       { "l15", QCOM_RPM_PM8921_LDO15, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l16", QCOM_RPM_PM8921_LDO16, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l17", QCOM_RPM_PM8921_LDO17, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l18", QCOM_RPM_PM8921_LDO18, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l21", QCOM_RPM_PM8921_LDO21, &pm8921_pldo, "vdd_l21_l23_l29" },
+       { "l22", QCOM_RPM_PM8921_LDO22, &pm8921_pldo, "vdd_l10_l22" },
+       { "l23", QCOM_RPM_PM8921_LDO23, &pm8921_pldo, "vdd_l21_l23_l29" },
+       { "l24", QCOM_RPM_PM8921_LDO24, &pm8921_nldo1200, "vdd_l24" },
+       { "l25", QCOM_RPM_PM8921_LDO25, &pm8921_nldo1200, "vdd_l25" },
+       { "l26", QCOM_RPM_PM8921_LDO26, &pm8921_nldo1200, "vdd_l26" },
+       { "l27", QCOM_RPM_PM8921_LDO27, &pm8921_nldo1200, "vdd_l27" },
+       { "l28", QCOM_RPM_PM8921_LDO28, &pm8921_nldo1200, "vdd_l28" },
+       { "l29", QCOM_RPM_PM8921_LDO29, &pm8921_pldo, "vdd_l21_l23_l29" },
+
+       { "lvs1", QCOM_RPM_PM8921_LVS1, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs2", QCOM_RPM_PM8921_LVS2, &pm8921_switch, "vin_lvs2" },
+       { "lvs3", QCOM_RPM_PM8921_LVS3, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs4", QCOM_RPM_PM8921_LVS4, &pm8921_switch, "vin_lvs4_5_7" },
+       { "lvs5", QCOM_RPM_PM8921_LVS5, &pm8921_switch, "vin_lvs4_5_7" },
+       { "lvs6", QCOM_RPM_PM8921_LVS6, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs7", QCOM_RPM_PM8921_LVS7, &pm8921_switch, "vin_lvs4_5_7" },
+
+       { "usb-switch", QCOM_RPM_USB_OTG_SWITCH, &pm8921_switch, "vin_5vs" },
+       { "hdmi-switch", QCOM_RPM_HDMI_SWITCH, &pm8921_switch, "vin_5vs" },
+       { "ncp", QCOM_RPM_PM8921_NCP, &pm8921_ncp, "vdd_ncp" },
+       { }
+};
+
+static const struct of_device_id rpm_of_match[] = {
+       { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
+       { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
+       { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rpm_of_match);
+
+static int rpm_reg_probe(struct platform_device *pdev)
+{
+       const struct rpm_regulator_data *reg;
+       const struct of_device_id *match;
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+       struct qcom_rpm_reg *vreg;
+       struct qcom_rpm *rpm;
+
+       rpm = dev_get_drvdata(pdev->dev.parent);
+       if (!rpm) {
+               dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
+               return -ENODEV;
+       }
+
+       match = of_match_device(rpm_of_match, &pdev->dev);
+       for (reg = match->data; reg->name; reg++) {
+               vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
+               if (!vreg)
+                       return -ENOMEM;
+
+               memcpy(vreg, reg->template, sizeof(*vreg));
+               mutex_init(&vreg->lock);
+
+               vreg->dev = &pdev->dev;
+               vreg->resource = reg->resource;
+               vreg->rpm = rpm;
+
+               vreg->desc.id = -1;
+               vreg->desc.owner = THIS_MODULE;
+               vreg->desc.type = REGULATOR_VOLTAGE;
+               vreg->desc.name = reg->name;
+               vreg->desc.supply_name = reg->supply;
+               vreg->desc.of_match = reg->name;
+               vreg->desc.of_parse_cb = rpm_reg_of_parse;
+
+               config.dev = &pdev->dev;
+               config.driver_data = vreg;
+               rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register %s\n", reg->name);
+                       return PTR_ERR(rdev);
+               }
        }
 
        return 0;
index 89025f5602590dbc03f5fa0c3b55dad6a347aab3..7d2ae3e9e942f26f302f526450487213da2cc44d 100644 (file)
@@ -56,6 +56,7 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
 {
        struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
        struct regulator_config config = { };
+       struct regulator_dev *rdev;
        int ret;
 
        /* First disable the external VMMC if it's active */
@@ -75,12 +76,11 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
                                                      pdev->dev.of_node,
                                                      &vmmc_regulator);
 
-       stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
-                                               &vmmc_regulator, &config);
-       if (IS_ERR(stw481x->vmmc_regulator)) {
+       rdev = devm_regulator_register(&pdev->dev, &vmmc_regulator, &config);
+       if (IS_ERR(rdev)) {
                dev_err(&pdev->dev,
                        "error initializing STw481x VMMC regulator\n");
-               return PTR_ERR(stw481x->vmmc_regulator);
+               return PTR_ERR(rdev);
        }
 
        dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
index 7ec7c390eedaa1085eeb03d4adfce33f7f1b4531..95f6b040186eee1cc8407da82379fe686e7594cc 100644 (file)
@@ -1151,17 +1151,16 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 static irqreturn_t pmic_uv_handler(int irq, void *data)
 {
        struct regulator_dev *rdev = (struct regulator_dev *)data;
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
 
        mutex_lock(&rdev->mutex);
        if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
                regulator_notifier_call_chain(rdev,
                                              REGULATOR_EVENT_REGULATION_OUT,
-                                             wm8350);
+                                             NULL);
        else
                regulator_notifier_call_chain(rdev,
                                              REGULATOR_EVENT_UNDER_VOLTAGE,
-                                             wm8350);
+                                             NULL);
        mutex_unlock(&rdev->mutex);
 
        return IRQ_HANDLED;
index 5d60a868830dafe126d7d5bcdf73e959325919be..2aa85e398f769e66f14838dbfee94759089c1fea 100644 (file)
@@ -4225,22 +4225,15 @@ static struct scsi_host_template ufshcd_driver_template = {
 static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
                                   int ua)
 {
-       int ret = 0;
-       struct regulator *reg = vreg->reg;
-       const char *name = vreg->name;
+       int ret;
 
-       BUG_ON(!vreg);
+       if (!vreg)
+               return 0;
 
-       ret = regulator_set_optimum_mode(reg, ua);
-       if (ret >= 0) {
-               /*
-                * regulator_set_optimum_mode() returns new regulator
-                * mode upon success.
-                */
-               ret = 0;
-       } else {
-               dev_err(dev, "%s: %s set optimum mode(ua=%d) failed, err=%d\n",
-                               __func__, name, ua, ret);
+       ret = regulator_set_load(vreg->reg, ua);
+       if (ret < 0) {
+               dev_err(dev, "%s: %s set load (ua=%d) failed, err=%d\n",
+                               __func__, vreg->name, ua, ret);
        }
 
        return ret;
@@ -4249,18 +4242,12 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
 static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
-       if (!vreg)
-               return 0;
-
        return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
 }
 
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
-       if (!vreg)
-               return 0;
-
        return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
index 0b1bd2369293d98468641541cee2e1ccc22493d4..f5b3b928941bda5f394210a2f34b2eb46e9b7836 100644 (file)
@@ -277,7 +277,7 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
                        dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
                                        ret);
 
-               ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+               ret = regulator_set_load(ab->v_ulpi, 28000);
                if (ret < 0)
                        dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
                                        ret);
@@ -317,7 +317,7 @@ static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
                                                ab->saved_v_ulpi, ret);
                }
 
-               ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+               ret = regulator_set_load(ab->v_ulpi, 0);
                if (ret < 0)
                        dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
                                        ret);
index 000fd892455f7de0f31c94f44aad116d1c244f61..6ed67ea4ef7e594327e46c79d25451fe163713fa 100644 (file)
@@ -142,27 +142,22 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on)
        int ret = 0;
 
        if (on) {
-               ret = regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_HPM_LOAD);
+               ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_HPM_LOAD);
                if (ret < 0) {
                        pr_err("Could not set HPM for v1p8\n");
                        return ret;
                }
-               ret = regulator_set_optimum_mode(motg->v3p3,
-                               USB_PHY_3P3_HPM_LOAD);
+               ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_HPM_LOAD);
                if (ret < 0) {
                        pr_err("Could not set HPM for v3p3\n");
-                       regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_LPM_LOAD);
+                       regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
                        return ret;
                }
        } else {
-               ret = regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_LPM_LOAD);
+               ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
                if (ret < 0)
                        pr_err("Could not set LPM for v1p8\n");
-               ret = regulator_set_optimum_mode(motg->v3p3,
-                               USB_PHY_3P3_LPM_LOAD);
+               ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_LPM_LOAD);
                if (ret < 0)
                        pr_err("Could not set LPM for v3p3\n");
        }
index f0b6585cd874cd0ecb917e8dccb130460bedbb40..09a4dedaeea85fd7cd1bfa048a400fde29543ab1 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
-/* MAX77686 regulator IDs */
+/* MAX77693 regulator IDs */
 enum max77693_regulators {
        MAX77693_ESAFEOUT1 = 0,
        MAX77693_ESAFEOUT2,
@@ -38,12 +38,6 @@ enum max77693_regulators {
        MAX77693_REG_MAX,
 };
 
-struct max77693_regulator_data {
-       int id;
-       struct regulator_init_data *initdata;
-       struct device_node *of_node;
-};
-
 struct max77693_reg_data {
        u8 addr;
        u8 data;
@@ -103,10 +97,6 @@ struct max77693_led_platform_data {
 /* MAX77693 */
 
 struct max77693_platform_data {
-       /* regulator data */
-       struct max77693_regulator_data *regulators;
-       int num_regulators;
-
        /* muic data */
        struct max77693_muic_platform_data *muic_data;
        struct max77693_led_platform_data *led_data;
index ee7b1ce7a6f8f42280abcc3d1411f7bcdebb6ac2..bb270bd03eedc3eb570555b9929b7ba652a38f6e 100644 (file)
@@ -117,6 +117,7 @@ struct palmas_pmic_driver_data {
        int ldo_begin;
        int ldo_end;
        int max_reg;
+       bool has_regen3;
        struct palmas_regs_info *palmas_regs_info;
        struct of_regulator_match *palmas_matches;
        struct palmas_sleep_requestor_info *sleep_req_info;
index eda121556e5d3e142c0f3f20797c45ce08a5200f..833074b766bdfb87dbcc07dda912d2d11c0c9697 100644 (file)
 
 /**
  * struct stw481x - state holder for the Stw481x drivers
- * @mutex: mutex to serialize I2C accesses
  * @i2c_client: corresponding I2C client
- * @regulator: regulator device for regulator children
  * @map: regmap handle to access device registers
  */
 struct stw481x {
-       struct mutex            lock;
        struct i2c_client       *client;
-       struct regulator_dev    *vmmc_regulator;
        struct regmap           *map;
 };
 
index b6c4909b33af8247d685f0a6932dfc73fc352ec5..15fa8f2d35c9a58fc2e563418ee00981eb1da13f 100644 (file)
 
 #include <linux/regulator/machine.h>
 
+enum {
+       ACT8600_ID_DCDC1,
+       ACT8600_ID_DCDC2,
+       ACT8600_ID_DCDC3,
+       ACT8600_ID_SUDCDC4,
+       ACT8600_ID_LDO5,
+       ACT8600_ID_LDO6,
+       ACT8600_ID_LDO7,
+       ACT8600_ID_LDO8,
+       ACT8600_ID_LDO9,
+       ACT8600_ID_LDO10,
+};
+
 enum {
        ACT8865_ID_DCDC1,
        ACT8865_ID_DCDC2,
@@ -46,6 +59,7 @@ enum {
 };
 
 enum {
+       ACT8600,
        ACT8865,
        ACT8846,
 };
index d17e1ff7ad019987d4c4f944dd3a6b20aa571807..f8a689ed62a58753cb3d4863f61d834cdca74f62 100644 (file)
@@ -114,7 +114,7 @@ struct regmap;
 #define REGULATOR_EVENT_OVER_TEMP              0x10
 #define REGULATOR_EVENT_FORCE_DISABLE          0x20
 #define REGULATOR_EVENT_VOLTAGE_CHANGE         0x40
-#define REGULATOR_EVENT_DISABLE                0x80
+#define REGULATOR_EVENT_DISABLE                        0x80
 #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE     0x100
 #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE   0x200
 #define REGULATOR_EVENT_PRE_DISABLE            0x400
@@ -238,7 +238,7 @@ int regulator_get_current_limit(struct regulator *regulator);
 
 int regulator_set_mode(struct regulator *regulator, unsigned int mode);
 unsigned int regulator_get_mode(struct regulator *regulator);
-int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
+int regulator_set_load(struct regulator *regulator, int load_uA);
 
 int regulator_allow_bypass(struct regulator *regulator, bool allow);
 
@@ -252,8 +252,12 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
 /* regulator notifier block */
 int regulator_register_notifier(struct regulator *regulator,
                              struct notifier_block *nb);
+int devm_regulator_register_notifier(struct regulator *regulator,
+                                    struct notifier_block *nb);
 int regulator_unregister_notifier(struct regulator *regulator,
                                struct notifier_block *nb);
+void devm_regulator_unregister_notifier(struct regulator *regulator,
+                                       struct notifier_block *nb);
 
 /* driver data - core doesn't touch */
 void *regulator_get_drvdata(struct regulator *regulator);
@@ -479,8 +483,7 @@ static inline unsigned int regulator_get_mode(struct regulator *regulator)
        return REGULATOR_MODE_NORMAL;
 }
 
-static inline int regulator_set_optimum_mode(struct regulator *regulator,
-                                       int load_uA)
+static inline int regulator_set_load(struct regulator *regulator, int load_uA)
 {
        return REGULATOR_MODE_NORMAL;
 }
@@ -515,12 +518,24 @@ static inline int regulator_register_notifier(struct regulator *regulator,
        return 0;
 }
 
+static inline int devm_regulator_register_notifier(struct regulator *regulator,
+                                                  struct notifier_block *nb)
+{
+       return 0;
+}
+
 static inline int regulator_unregister_notifier(struct regulator *regulator,
                                struct notifier_block *nb)
 {
        return 0;
 }
 
+static inline int devm_regulator_unregister_notifier(struct regulator *regulator,
+                                                    struct notifier_block *nb)
+{
+       return 0;
+}
+
 static inline void *regulator_get_drvdata(struct regulator *regulator)
 {
        return NULL;
index 045f709cb89b52c5e2381635b0bea10101030120..fffa688ac3a7a36c9ecc33e006c52f1c4cf3892c 100644 (file)
@@ -98,6 +98,7 @@ struct regulator_linear_range {
  *     REGULATOR_STATUS value (or negative errno)
  * @get_optimum_mode: Get the most efficient operating mode for the regulator
  *                    when running with the specified parameters.
+ * @set_load: Set the load for the regulator.
  *
  * @set_bypass: Set the regulator in bypass mode.
  * @get_bypass: Get the regulator bypass mode state.
@@ -167,6 +168,8 @@ struct regulator_ops {
        /* get most efficient regulator operating mode for load */
        unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
                                          int output_uV, int load_uA);
+       /* set the load on the regulator */
+       int (*set_load)(struct regulator_dev *, int load_uA);
 
        /* control and report on bypass mode */
        int (*set_bypass)(struct regulator_dev *dev, bool enable);
@@ -367,6 +370,7 @@ struct regulator_dev {
        struct device dev;
        struct regulation_constraints *constraints;
        struct regulator *supply;       /* for tree */
+       const char *supply_name;
        struct regmap *regmap;
 
        struct delayed_work disable_work;