regulator: Updates for v4.1

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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJVK+w1AAoJECTWi3JdVIfQeg0H/2ckXZEQWH/yzAz7JgAoSmVr
 +y8pvfNLOyOVVulFI0QBOaCAoyJNXNPNqDrkYaTykMIwX4y+weoDqfH/LMiGpnXl
 D3aAgdLPSWLTUMteCs9KIHesnOdjKclZUjnbskJgnmeMCW23WcX9T1lBVoLBVdlo
 p+oe287rhEwF6j2t63aLwFv8QGpamgVQ/8mXXs8EK7L5E3OO262SwLaXRBAtWk30
 Eb68qXrbbkrDunEL6Hjggj5pFi93M4eNfQHpzVmjidvwz1g4JpLtWHW4XpQlXoHJ
 G2rlVwNFsyedT1MX2ByKhrIPu5kq5pt0/rjear34G3vuEnQm7vR3aW/38AOxffs=
 =t8gT
 -----END PGP SIGNATURE-----

Merge tag 'regulator-v4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

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
  ...
This commit is contained in:
Linus Torvalds 2015-04-13 15:13:25 -07:00
commit d700b05671
26 changed files with 778 additions and 358 deletions

View File

@ -2,13 +2,35 @@ ACT88xx regulators
------------------- -------------------
Required properties: 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 - reg: I2C slave address
Optional properties: Optional properties:
- system-power-controller: Telling whether or not this pmic is controlling - system-power-controller: Telling whether or not this pmic is controlling
the system power. See Documentation/devicetree/bindings/power/power-controller.txt . 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. Any standard regulator properties can be used to configure the single regulator.
The valid names for regulators are: 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 REG1, REG2, REG3, REG4, REG5, REG6, REG7, REG8, REG9, REG10, REG11, REG12
- for act8865: - for act8865:
DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4. 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: Example:
-------- --------

View File

@ -137,7 +137,7 @@ Indirect operating mode control.
Consumer drivers can request a change in their supply regulator operating mode Consumer drivers can request a change in their supply regulator operating mode
by calling :- 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 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) on all its consumers) and change operating mode (if necessary and permitted)

View File

@ -332,7 +332,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
goto vdda_set_fail; 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) { if (ret < 0) {
pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__); pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
goto vdda_set_fail; goto vdda_set_fail;
@ -356,7 +356,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
lvl_enable_fail: lvl_enable_fail:
regulator_disable(ctrl->vdda_vreg); regulator_disable(ctrl->vdda_vreg);
vdda_enable_fail: 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: vdda_set_fail:
return ret; return ret;
} }
@ -365,7 +365,7 @@ static void edp_regulator_disable(struct edp_ctrl *ctrl)
{ {
regulator_disable(ctrl->lvl_vreg); regulator_disable(ctrl->lvl_vreg);
regulator_disable(ctrl->vdda_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) static int edp_gpio_config(struct edp_ctrl *ctrl)

View File

@ -346,10 +346,10 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy,
goto out; goto out;
} }
uA_load = on ? vreg->max_uA : 0; 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) { if (ret >= 0) {
/* /*
* regulator_set_optimum_mode() returns new regulator * regulator_set_load() returns new regulator
* mode upon success. * mode upon success.
*/ */
ret = 0; ret = 0;

View File

@ -28,6 +28,35 @@
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/regmap.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. * ACT8846 Global Register Map.
*/ */
@ -94,10 +123,15 @@
#define ACT8865_ENA 0x80 /* ON - [7] */ #define ACT8865_ENA 0x80 /* ON - [7] */
#define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */ #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 * ACT8865 voltage number
*/ */
#define ACT8865_VOLTAGE_NUM 64 #define ACT8865_VOLTAGE_NUM 64
#define ACT8600_SUDCDC_VOLTAGE_NUM 255
struct act8865 { struct act8865 {
struct regmap *regmap; struct regmap *regmap;
@ -116,6 +150,13 @@ static const struct regulator_linear_range act8865_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000), 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 = { static struct regulator_ops act8865_ops = {
.list_voltage = regulator_list_voltage_linear_range, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_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, .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] = { \ [_family##_ID_##_id] = { \
.name = _name, \ .name = _name, \
.supply_name = _supply, \
.id = _family##_ID_##_id, \ .id = _family##_ID_##_id, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.ops = &act8865_ops, \ .ops = &act8865_ops, \
@ -142,33 +190,80 @@ static struct regulator_ops act8865_ops = {
.owner = THIS_MODULE, \ .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[] = { static const struct regulator_desc act8846_regulators[] = {
ACT88xx_REG("REG1", ACT8846, REG1, VSET), ACT88xx_REG("REG1", ACT8846, REG1, VSET, "vp1"),
ACT88xx_REG("REG2", ACT8846, REG2, VSET0), ACT88xx_REG("REG2", ACT8846, REG2, VSET0, "vp2"),
ACT88xx_REG("REG3", ACT8846, REG3, VSET0), ACT88xx_REG("REG3", ACT8846, REG3, VSET0, "vp3"),
ACT88xx_REG("REG4", ACT8846, REG4, VSET0), ACT88xx_REG("REG4", ACT8846, REG4, VSET0, "vp4"),
ACT88xx_REG("REG5", ACT8846, REG5, VSET), ACT88xx_REG("REG5", ACT8846, REG5, VSET, "inl1"),
ACT88xx_REG("REG6", ACT8846, REG6, VSET), ACT88xx_REG("REG6", ACT8846, REG6, VSET, "inl1"),
ACT88xx_REG("REG7", ACT8846, REG7, VSET), ACT88xx_REG("REG7", ACT8846, REG7, VSET, "inl1"),
ACT88xx_REG("REG8", ACT8846, REG8, VSET), ACT88xx_REG("REG8", ACT8846, REG8, VSET, "inl2"),
ACT88xx_REG("REG9", ACT8846, REG9, VSET), ACT88xx_REG("REG9", ACT8846, REG9, VSET, "inl2"),
ACT88xx_REG("REG10", ACT8846, REG10, VSET), ACT88xx_REG("REG10", ACT8846, REG10, VSET, "inl3"),
ACT88xx_REG("REG11", ACT8846, REG11, VSET), ACT88xx_REG("REG11", ACT8846, REG11, VSET, "inl3"),
ACT88xx_REG("REG12", ACT8846, REG12, VSET), ACT88xx_REG("REG12", ACT8846, REG12, VSET, "inl3"),
}; };
static const struct regulator_desc act8865_regulators[] = { static const struct regulator_desc act8865_regulators[] = {
ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1), ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"),
ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1), ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"),
ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1), ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"),
ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET), ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET), ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET), ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET), ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id act8865_dt_ids[] = { 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,act8846", .data = (void *)ACT8846 },
{ .compatible = "active-semi,act8865", .data = (void *)ACT8865 }, { .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
{ } { }
@ -200,6 +295,19 @@ static struct of_regulator_match act8865_matches[] = {
[ACT8865_ID_LDO4] = { .name = "LDO_REG4"}, [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, static int act8865_pdata_from_dt(struct device *dev,
struct device_node **of_node, struct device_node **of_node,
struct act8865_platform_data *pdata, struct act8865_platform_data *pdata,
@ -217,6 +325,10 @@ static int act8865_pdata_from_dt(struct device *dev,
} }
switch (type) { switch (type) {
case ACT8600:
matches = act8600_matches;
num_matches = ARRAY_SIZE(act8600_matches);
break;
case ACT8846: case ACT8846:
matches = act8846_matches; matches = act8846_matches;
num_matches = ARRAY_SIZE(act8846_matches); num_matches = ARRAY_SIZE(act8846_matches);
@ -317,6 +429,12 @@ static int act8865_pmic_probe(struct i2c_client *client,
} }
switch (type) { switch (type) {
case ACT8600:
regulators = act8600_regulators;
num_regulators = ARRAY_SIZE(act8600_regulators);
off_reg = -1;
off_mask = -1;
break;
case ACT8846: case ACT8846:
regulators = act8846_regulators; regulators = act8846_regulators;
num_regulators = ARRAY_SIZE(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 (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_i2c_client = client;
act8865->off_reg = off_reg; act8865->off_reg = off_reg;
act8865->off_mask = off_mask; 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[] = { static const struct i2c_device_id act8865_ids[] = {
{ .name = "act8600", .driver_data = ACT8600 },
{ .name = "act8846", .driver_data = ACT8846 }, { .name = "act8846", .driver_data = ACT8846 },
{ .name = "act8865", .driver_data = ACT8865 }, { .name = "act8865", .driver_data = ACT8865 },
{ }, { },

View File

@ -282,6 +282,9 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
arizona->external_dcvdd = true; arizona->external_dcvdd = true;
ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
of_node_put(config.of_node);
if (IS_ERR(ldo1->regulator)) { if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator); ret = PTR_ERR(ldo1->regulator);
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n", 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; return ret;
} }
of_node_put(config.of_node);
platform_set_drvdata(pdev, ldo1); platform_set_drvdata(pdev, ldo1);
return 0; return 0;

View File

@ -284,6 +284,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
micsupp->regulator = devm_regulator_register(&pdev->dev, micsupp->regulator = devm_regulator_register(&pdev->dev,
desc, desc,
&config); &config);
of_node_put(config.of_node);
if (IS_ERR(micsupp->regulator)) { if (IS_ERR(micsupp->regulator)) {
ret = PTR_ERR(micsupp->regulator); ret = PTR_ERR(micsupp->regulator);
dev_err(arizona->dev, "Failed to register mic supply: %d\n", 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; return ret;
} }
of_node_put(config.of_node);
platform_set_drvdata(pdev, micsupp); platform_set_drvdata(pdev, micsupp);
return 0; return 0;

View File

@ -648,10 +648,12 @@ static int drms_uA_update(struct regulator_dev *rdev)
if (err < 0) if (err < 0)
return 0; return 0;
if (!rdev->desc->ops->get_optimum_mode) if (!rdev->desc->ops->get_optimum_mode &&
!rdev->desc->ops->set_load)
return 0; return 0;
if (!rdev->desc->ops->set_mode) if (!rdev->desc->ops->set_mode &&
!rdev->desc->ops->set_load)
return -EINVAL; return -EINVAL;
/* get output voltage */ /* 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) list_for_each_entry(sibling, &rdev->consumer_list, list)
current_uA += sibling->uA_load; current_uA += sibling->uA_load;
/* now get the optimum mode for our new total regulator load */ if (rdev->desc->ops->set_load) {
mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, /* set the optimum mode for our new total regulator load */
output_uV, current_uA); 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 */ /* check the new mode is allowed */
err = regulator_mode_constrain(rdev, &mode); err = regulator_mode_constrain(rdev, &mode);
if (err < 0) { if (err < 0) {
rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
current_uA, input_uV, output_uV); current_uA, input_uV, output_uV);
return err; 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; return err;
} }
@ -1316,6 +1325,54 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
return NULL; 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 */ /* Internal regulator request function */
static struct regulator *_regulator_get(struct device *dev, const char *id, static struct regulator *_regulator_get(struct device *dev, const char *id,
bool exclusive, bool allow_dummy) bool exclusive, bool allow_dummy)
@ -1385,6 +1442,12 @@ found:
goto out; goto out;
} }
ret = regulator_resolve_supply(rdev);
if (ret < 0) {
regulator = ERR_PTR(ret);
goto out;
}
if (!try_module_get(rdev->owner)) if (!try_module_get(rdev->owner))
goto out; goto out;
@ -2998,7 +3061,7 @@ unsigned int regulator_get_mode(struct regulator *regulator)
EXPORT_SYMBOL_GPL(regulator_get_mode); EXPORT_SYMBOL_GPL(regulator_get_mode);
/** /**
* regulator_set_optimum_mode - set regulator optimum operating mode * regulator_set_load - set regulator load
* @regulator: regulator source * @regulator: regulator source
* @uA_load: load current * @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 * DRMS will sum the total requested load on the regulator and change
* to the most efficient operating mode if platform constraints allow. * 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; struct regulator_dev *rdev = regulator->rdev;
int ret; int ret;
@ -3035,7 +3098,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
return ret; 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 * 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) 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) { if (!rdev->debugfs) {
rdev_warn(rdev, "Failed to create debugfs directory\n"); rdev_warn(rdev, "Failed to create debugfs directory\n");
return; return;
@ -3533,7 +3607,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
struct regulator_dev *rdev; struct regulator_dev *rdev;
struct device *dev; struct device *dev;
int ret, i; int ret, i;
const char *supply = NULL;
if (regulator_desc == NULL || cfg == NULL) if (regulator_desc == NULL || cfg == NULL)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -3641,41 +3714,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
goto scrub; goto scrub;
if (init_data && init_data->supply_regulator) 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) else if (regulator_desc->supply_name)
supply = regulator_desc->supply_name; rdev->supply_name = regulator_desc->supply_name;
if (supply) {
struct regulator_dev *r;
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 */ /* add consumers devices */
if (init_data) { if (init_data) {
for (i = 0; i < init_data->num_consumer_supplies; i++) { for (i = 0; i < init_data->num_consumer_supplies; i++) {
@ -3702,8 +3744,6 @@ unset_supplies:
unset_regulator_supplies(rdev); unset_regulator_supplies(rdev);
scrub: scrub:
if (rdev->supply)
_regulator_put(rdev->supply);
regulator_ena_gpio_free(rdev); regulator_ena_gpio_free(rdev);
kfree(rdev->constraints); kfree(rdev->constraints);
wash: wash:
@ -3936,6 +3976,110 @@ static const struct file_operations supply_map_fops = {
#endif #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) static int __init regulator_init(void)
{ {
int ret; int ret;
@ -3949,6 +4093,9 @@ static int __init regulator_init(void)
debugfs_create_file("supply_map", 0444, debugfs_root, NULL, debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
&supply_map_fops); &supply_map_fops);
debugfs_create_file("regulator_summary", 0444, debugfs_root,
&regulator_list, &regulator_summary_fops);
regulator_dummy_init(); regulator_dummy_init();
return ret; return ret;

View File

@ -305,8 +305,7 @@ static irqreturn_t da9211_irq_handler(int irq, void *data)
if (reg_val & DA9211_E_OV_CURR_A) { if (reg_val & DA9211_E_OV_CURR_A) {
regulator_notifier_call_chain(chip->rdev[0], regulator_notifier_call_chain(chip->rdev[0],
REGULATOR_EVENT_OVER_CURRENT, REGULATOR_EVENT_OVER_CURRENT, NULL);
rdev_get_drvdata(chip->rdev[0]));
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B, err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_A); 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) { if (reg_val & DA9211_E_OV_CURR_B) {
regulator_notifier_call_chain(chip->rdev[1], regulator_notifier_call_chain(chip->rdev[1],
REGULATOR_EVENT_OVER_CURRENT, REGULATOR_EVENT_OVER_CURRENT, NULL);
rdev_get_drvdata(chip->rdev[1]));
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B, err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_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); ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
if (ret < 0) { 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; return ret;
} }

View 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) 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 */ /* print power state count */
err = seq_printf(s, "ux500-regulator power state count: %i\n", seq_printf(s, "ux500-regulator power state count: %i\n",
power_state_active_get()); power_state_active_get());
if (err < 0)
dev_err(dev, "seq_printf overflow\n");
return 0; 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) static int ux500_regulator_status_print(struct seq_file *s, void *p)
{ {
struct device *dev = s->private;
int err;
int i; int i;
/* print dump header */ /* print dump header */
err = seq_puts(s, "ux500-regulator status:\n"); seq_puts(s, "ux500-regulator status:\n");
if (err < 0) seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
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");
for (i = 0; i < rdebug.num_regulators; i++) { for (i = 0; i < rdebug.num_regulators; i++) {
struct dbx500_regulator_info *info; 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]; info = &rdebug.regulator_array[i];
/* print status */ /* print status */
err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name, seq_printf(s, "%20s : %8s : %8s : %8s\n",
info->is_enabled ? "enabled" : "disabled", info->desc.name,
rdebug.state_before_suspend[i] ? "enabled" : "disabled", info->is_enabled ? "enabled" : "disabled",
rdebug.state_after_suspend[i] ? "enabled" : "disabled"); rdebug.state_before_suspend[i] ? "enabled" : "disabled",
if (err < 0) rdebug.state_after_suspend[i] ? "enabled" : "disabled");
dev_err(dev, "seq_printf overflow\n");
} }
return 0; return 0;

View File

@ -413,3 +413,88 @@ void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
devm_regulator_unregister_supply_alias(dev, id[i]); devm_regulator_unregister_supply_alias(dev, id[i]);
} }
EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias); 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);

View File

@ -128,6 +128,8 @@ static struct regulator_ops max77693_charger_ops = {
#define regulator_desc_esafeout(_num) { \ #define regulator_desc_esafeout(_num) { \
.name = "ESAFEOUT"#_num, \ .name = "ESAFEOUT"#_num, \
.id = MAX77693_ESAFEOUT##_num, \ .id = MAX77693_ESAFEOUT##_num, \
.of_match = of_match_ptr("ESAFEOUT"#_num), \
.regulators_node = of_match_ptr("regulators"), \
.n_voltages = 4, \ .n_voltages = 4, \
.ops = &max77693_safeout_ops, \ .ops = &max77693_safeout_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
@ -145,6 +147,8 @@ static const struct regulator_desc regulators[] = {
{ {
.name = "CHARGER", .name = "CHARGER",
.id = MAX77693_CHARGER, .id = MAX77693_CHARGER,
.of_match = of_match_ptr("CHARGER"),
.regulators_node = of_match_ptr("regulators"),
.ops = &max77693_charger_ops, .ops = &max77693_charger_ops,
.type = REGULATOR_CURRENT, .type = REGULATOR_CURRENT,
.owner = THIS_MODULE, .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) static int max77693_pmic_probe(struct platform_device *pdev)
{ {
struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77693_regulator_data *rdata = NULL; int i;
int num_rdata, i;
struct regulator_config config = { }; struct regulator_config config = { };
num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata); config.dev = iodev->dev;
if (!rdata || num_rdata <= 0) {
dev_err(&pdev->dev, "No init data supplied.\n");
return -ENODEV;
}
config.dev = &pdev->dev;
config.regmap = iodev->regmap; config.regmap = iodev->regmap;
for (i = 0; i < num_rdata; i++) { for (i = 0; i < ARRAY_SIZE(regulators); i++) {
int id = rdata[i].id;
struct regulator_dev *rdev; struct regulator_dev *rdev;
config.init_data = rdata[i].initdata;
config.of_node = rdata[i].of_node;
rdev = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&regulators[id], &config); &regulators[i], &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Failed to initialize regulator-%d\n", id); "Failed to initialize regulator-%d\n", i);
return PTR_ERR(rdev); return PTR_ERR(rdev);
} }
} }

View File

@ -382,7 +382,7 @@ static int max8660_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
struct device *dev = &client->dev; 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 regulator_config config = { };
struct max8660 *max8660; struct max8660 *max8660;
int boot_on, i, id, ret = -EINVAL; int boot_on, i, id, ret = -EINVAL;
@ -391,7 +391,6 @@ static int max8660_probe(struct i2c_client *client,
if (dev->of_node && !pdata) { if (dev->of_node && !pdata) {
const struct of_device_id *id; const struct of_device_id *id;
struct max8660_platform_data pdata_of;
id = of_match_device(of_match_ptr(max8660_dt_ids), dev); id = of_match_device(of_match_ptr(max8660_dt_ids), dev);
if (!id) if (!id)
@ -443,9 +442,9 @@ static int max8660_probe(struct i2c_client *client,
for (i = 0; i < pdata->num_subdevs; i++) { for (i = 0; i < pdata->num_subdevs; i++) {
if (!pdata->subdevs[i].platform_data) if (!pdata->subdevs[i].platform_data)
return ret; boot_on = false;
else
boot_on = pdata->subdevs[i].platform_data->constraints.boot_on; boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
switch (pdata->subdevs[i].id) { switch (pdata->subdevs[i].id) {
case MAX8660_V3: case MAX8660_V3:

View File

@ -916,6 +916,9 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic,
(id == PALMAS_REG_LDO6)) (id == PALMAS_REG_LDO6))
desc->enable_time = 2000; desc->enable_time = 2000;
} else { } else {
if (!ddata->has_regen3 && id == PALMAS_REG_REGEN3)
continue;
desc->n_voltages = 1; desc->n_voltages = 1;
if (reg_init && reg_init->roof_floor) if (reg_init && reg_init->roof_floor)
desc->ops = &palmas_ops_ext_control_extreg; 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_begin = PALMAS_REG_LDO1,
.ldo_end = PALMAS_REG_LDOUSB, .ldo_end = PALMAS_REG_LDOUSB,
.max_reg = PALMAS_NUM_REGS, .max_reg = PALMAS_NUM_REGS,
.has_regen3 = true,
.palmas_regs_info = palmas_generic_regs_info, .palmas_regs_info = palmas_generic_regs_info,
.palmas_matches = palmas_matches, .palmas_matches = palmas_matches,
.sleep_req_info = palma_sleep_req_info, .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_begin = TPS65917_REG_LDO1,
.ldo_end = TPS65917_REG_LDO5, .ldo_end = TPS65917_REG_LDO5,
.max_reg = TPS65917_NUM_REGS, .max_reg = TPS65917_NUM_REGS,
.has_regen3 = true,
.palmas_regs_info = tps65917_regs_info, .palmas_regs_info = tps65917_regs_info,
.palmas_matches = tps65917_matches, .palmas_matches = tps65917_matches,
.sleep_req_info = tps65917_sleep_req_info, .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"); 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", .compatible = "ti,palmas-pmic",
.data = &palmas_ddata, .data = &palmas_ddata,
@ -1572,9 +1577,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (!pmic) if (!pmic)
return -ENOMEM; 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 = palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
TPS659038_REGEN2_CTRL; TPS659038_REGEN2_CTRL;
palmas_ddata.has_regen3 = false;
}
pmic->dev = &pdev->dev; pmic->dev = &pdev->dev;
pmic->palmas = palmas; pmic->palmas = palmas;

View File

@ -393,6 +393,28 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
return vreg->is_enabled; 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 = { static struct regulator_ops uV_ops = {
.list_voltage = regulator_list_voltage_linear_range, .list_voltage = regulator_list_voltage_linear_range,
@ -402,6 +424,8 @@ static struct regulator_ops uV_ops = {
.enable = rpm_reg_uV_enable, .enable = rpm_reg_uV_enable,
.disable = rpm_reg_uV_disable, .disable = rpm_reg_uV_disable,
.is_enabled = rpm_reg_is_enabled, .is_enabled = rpm_reg_is_enabled,
.set_load = rpm_reg_set_load,
}; };
static struct regulator_ops mV_ops = { static struct regulator_ops mV_ops = {
@ -413,6 +437,8 @@ static struct regulator_ops mV_ops = {
.enable = rpm_reg_mV_enable, .enable = rpm_reg_mV_enable,
.disable = rpm_reg_mV_disable, .disable = rpm_reg_mV_disable,
.is_enabled = rpm_reg_is_enabled, .is_enabled = rpm_reg_is_enabled,
.set_load = rpm_reg_set_load,
}; };
static struct regulator_ops switch_ops = { static struct regulator_ops switch_ops = {
@ -581,31 +607,6 @@ static const struct qcom_rpm_reg smb208_smps = {
.supports_force_mode_bypass = false, .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, static int rpm_reg_set(struct qcom_rpm_reg *vreg,
const struct request_member *req, const struct request_member *req,
const int value) const int value)
@ -619,7 +620,9 @@ static int rpm_reg_set(struct qcom_rpm_reg *vreg,
return 0; 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[] = { static const int freq_table[] = {
19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000, 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; int i;
key = "qcom,switch-mode-frequency"; 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) { if (ret) {
dev_err(dev, "regulator requires %s property\n", key); dev_err(dev, "regulator requires %s property\n", key);
return -EINVAL; return -EINVAL;
@ -650,84 +653,40 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
return -EINVAL; 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; struct qcom_rpm_reg *vreg = config->driver_data;
const struct qcom_rpm_reg *template; struct device *dev = config->dev;
const struct of_device_id *match;
struct regulator_config config = { };
struct regulator_dev *rdev;
struct qcom_rpm_reg *vreg;
const char *key; const char *key;
u32 force_mode; u32 force_mode;
bool pwm; bool pwm;
u32 val; u32 val;
int ret; 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"; 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); ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
if (ret) { if (ret) {
dev_err(&pdev->dev, "%s is invalid", key); dev_err(dev, "%s is invalid", key);
return ret; return ret;
} }
} }
if (vreg->parts->freq.mask) { 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) if (ret < 0)
return ret; return ret;
} }
if (vreg->parts->pm.mask) { if (vreg->parts->pm.mask) {
key = "qcom,power-mode-hysteretic"; 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); ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to set power mode\n"); dev_err(dev, "failed to set power mode\n");
return ret; return ret;
} }
} }
@ -736,11 +695,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
force_mode = -1; force_mode = -1;
key = "qcom,force-mode"; 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) { if (ret == -EINVAL) {
val = QCOM_RPM_FORCE_MODE_NONE; val = QCOM_RPM_FORCE_MODE_NONE;
} else if (ret < 0) { } 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; return ret;
} }
@ -775,25 +734,192 @@ static int rpm_reg_probe(struct platform_device *pdev)
} }
if (force_mode == -1) { if (force_mode == -1) {
dev_err(&pdev->dev, "invalid force mode\n"); dev_err(dev, "invalid force mode\n");
return -EINVAL; return -EINVAL;
} }
ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode); ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to set force mode\n"); dev_err(dev, "failed to set force mode\n");
return ret; return ret;
} }
} }
config.dev = &pdev->dev; return 0;
config.init_data = initdata; }
config.driver_data = vreg;
config.of_node = pdev->dev.of_node; struct rpm_regulator_data {
rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); const char *name;
if (IS_ERR(rdev)) { int resource;
dev_err(&pdev->dev, "can't register regulator\n"); const struct qcom_rpm_reg *template;
return PTR_ERR(rdev); 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; return 0;

View File

@ -56,6 +56,7 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
{ {
struct stw481x *stw481x = dev_get_platdata(&pdev->dev); struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev *rdev;
int ret; int ret;
/* First disable the external VMMC if it's active */ /* 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, pdev->dev.of_node,
&vmmc_regulator); &vmmc_regulator);
stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev, &vmmc_regulator, &config);
&vmmc_regulator, &config); if (IS_ERR(rdev)) {
if (IS_ERR(stw481x->vmmc_regulator)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"error initializing STw481x VMMC regulator\n"); "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"); dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");

View 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) static irqreturn_t pmic_uv_handler(int irq, void *data)
{ {
struct regulator_dev *rdev = (struct regulator_dev *)data; struct regulator_dev *rdev = (struct regulator_dev *)data;
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
regulator_notifier_call_chain(rdev, regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_REGULATION_OUT, REGULATOR_EVENT_REGULATION_OUT,
wm8350); NULL);
else else
regulator_notifier_call_chain(rdev, regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_UNDER_VOLTAGE, REGULATOR_EVENT_UNDER_VOLTAGE,
wm8350); NULL);
mutex_unlock(&rdev->mutex); mutex_unlock(&rdev->mutex);
return IRQ_HANDLED; return IRQ_HANDLED;

View 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, static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
int ua) int ua)
{ {
int ret = 0; int ret;
struct regulator *reg = vreg->reg;
const char *name = vreg->name;
BUG_ON(!vreg); if (!vreg)
return 0;
ret = regulator_set_optimum_mode(reg, ua); ret = regulator_set_load(vreg->reg, ua);
if (ret >= 0) { if (ret < 0) {
/* dev_err(dev, "%s: %s set load (ua=%d) failed, err=%d\n",
* regulator_set_optimum_mode() returns new regulator __func__, vreg->name, ua, ret);
* mode upon success.
*/
ret = 0;
} else {
dev_err(dev, "%s: %s set optimum mode(ua=%d) failed, err=%d\n",
__func__, name, ua, ret);
} }
return 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, static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
struct ufs_vreg *vreg) struct ufs_vreg *vreg)
{ {
if (!vreg)
return 0;
return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA); return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
} }
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
struct ufs_vreg *vreg) struct ufs_vreg *vreg)
{ {
if (!vreg)
return 0;
return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA); return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
} }

View 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", dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
ret); ret);
ret = regulator_set_optimum_mode(ab->v_ulpi, 28000); ret = regulator_set_load(ab->v_ulpi, 28000);
if (ret < 0) if (ret < 0)
dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
ret); ret);
@ -317,7 +317,7 @@ static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
ab->saved_v_ulpi, ret); 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) if (ret < 0)
dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
ret); ret);

View File

@ -142,27 +142,22 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on)
int ret = 0; int ret = 0;
if (on) { if (on) {
ret = regulator_set_optimum_mode(motg->v1p8, ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_HPM_LOAD);
USB_PHY_1P8_HPM_LOAD);
if (ret < 0) { if (ret < 0) {
pr_err("Could not set HPM for v1p8\n"); pr_err("Could not set HPM for v1p8\n");
return ret; return ret;
} }
ret = regulator_set_optimum_mode(motg->v3p3, ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_HPM_LOAD);
USB_PHY_3P3_HPM_LOAD);
if (ret < 0) { if (ret < 0) {
pr_err("Could not set HPM for v3p3\n"); pr_err("Could not set HPM for v3p3\n");
regulator_set_optimum_mode(motg->v1p8, regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
USB_PHY_1P8_LPM_LOAD);
return ret; return ret;
} }
} else { } else {
ret = regulator_set_optimum_mode(motg->v1p8, ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
USB_PHY_1P8_LPM_LOAD);
if (ret < 0) if (ret < 0)
pr_err("Could not set LPM for v1p8\n"); pr_err("Could not set LPM for v1p8\n");
ret = regulator_set_optimum_mode(motg->v3p3, ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_LPM_LOAD);
USB_PHY_3P3_LPM_LOAD);
if (ret < 0) if (ret < 0)
pr_err("Could not set LPM for v3p3\n"); pr_err("Could not set LPM for v3p3\n");
} }

View File

@ -30,7 +30,7 @@
#ifndef __LINUX_MFD_MAX77693_H #ifndef __LINUX_MFD_MAX77693_H
#define __LINUX_MFD_MAX77693_H #define __LINUX_MFD_MAX77693_H
/* MAX77686 regulator IDs */ /* MAX77693 regulator IDs */
enum max77693_regulators { enum max77693_regulators {
MAX77693_ESAFEOUT1 = 0, MAX77693_ESAFEOUT1 = 0,
MAX77693_ESAFEOUT2, MAX77693_ESAFEOUT2,
@ -38,12 +38,6 @@ enum max77693_regulators {
MAX77693_REG_MAX, MAX77693_REG_MAX,
}; };
struct max77693_regulator_data {
int id;
struct regulator_init_data *initdata;
struct device_node *of_node;
};
struct max77693_reg_data { struct max77693_reg_data {
u8 addr; u8 addr;
u8 data; u8 data;
@ -103,10 +97,6 @@ struct max77693_led_platform_data {
/* MAX77693 */ /* MAX77693 */
struct max77693_platform_data { struct max77693_platform_data {
/* regulator data */
struct max77693_regulator_data *regulators;
int num_regulators;
/* muic data */ /* muic data */
struct max77693_muic_platform_data *muic_data; struct max77693_muic_platform_data *muic_data;
struct max77693_led_platform_data *led_data; struct max77693_led_platform_data *led_data;

View File

@ -117,6 +117,7 @@ struct palmas_pmic_driver_data {
int ldo_begin; int ldo_begin;
int ldo_end; int ldo_end;
int max_reg; int max_reg;
bool has_regen3;
struct palmas_regs_info *palmas_regs_info; struct palmas_regs_info *palmas_regs_info;
struct of_regulator_match *palmas_matches; struct of_regulator_match *palmas_matches;
struct palmas_sleep_requestor_info *sleep_req_info; struct palmas_sleep_requestor_info *sleep_req_info;

View File

@ -41,15 +41,11 @@
/** /**
* struct stw481x - state holder for the Stw481x drivers * struct stw481x - state holder for the Stw481x drivers
* @mutex: mutex to serialize I2C accesses
* @i2c_client: corresponding I2C client * @i2c_client: corresponding I2C client
* @regulator: regulator device for regulator children
* @map: regmap handle to access device registers * @map: regmap handle to access device registers
*/ */
struct stw481x { struct stw481x {
struct mutex lock;
struct i2c_client *client; struct i2c_client *client;
struct regulator_dev *vmmc_regulator;
struct regmap *map; struct regmap *map;
}; };

View File

@ -18,6 +18,19 @@
#include <linux/regulator/machine.h> #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 { enum {
ACT8865_ID_DCDC1, ACT8865_ID_DCDC1,
ACT8865_ID_DCDC2, ACT8865_ID_DCDC2,
@ -46,6 +59,7 @@ enum {
}; };
enum { enum {
ACT8600,
ACT8865, ACT8865,
ACT8846, ACT8846,
}; };

View File

@ -114,7 +114,7 @@ struct regmap;
#define REGULATOR_EVENT_OVER_TEMP 0x10 #define REGULATOR_EVENT_OVER_TEMP 0x10
#define REGULATOR_EVENT_FORCE_DISABLE 0x20 #define REGULATOR_EVENT_FORCE_DISABLE 0x20
#define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 #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_PRE_VOLTAGE_CHANGE 0x100
#define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200
#define REGULATOR_EVENT_PRE_DISABLE 0x400 #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); int regulator_set_mode(struct regulator *regulator, unsigned int mode);
unsigned int regulator_get_mode(struct regulator *regulator); 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); int regulator_allow_bypass(struct regulator *regulator, bool allow);
@ -252,8 +252,12 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
/* regulator notifier block */ /* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator, int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb); struct notifier_block *nb);
int devm_regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb);
int regulator_unregister_notifier(struct regulator *regulator, int regulator_unregister_notifier(struct regulator *regulator,
struct notifier_block *nb); struct notifier_block *nb);
void devm_regulator_unregister_notifier(struct regulator *regulator,
struct notifier_block *nb);
/* driver data - core doesn't touch */ /* driver data - core doesn't touch */
void *regulator_get_drvdata(struct regulator *regulator); 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; return REGULATOR_MODE_NORMAL;
} }
static inline int regulator_set_optimum_mode(struct regulator *regulator, static inline int regulator_set_load(struct regulator *regulator, int load_uA)
int load_uA)
{ {
return REGULATOR_MODE_NORMAL; return REGULATOR_MODE_NORMAL;
} }
@ -515,12 +518,24 @@ static inline int regulator_register_notifier(struct regulator *regulator,
return 0; 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, static inline int regulator_unregister_notifier(struct regulator *regulator,
struct notifier_block *nb) struct notifier_block *nb)
{ {
return 0; 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) static inline void *regulator_get_drvdata(struct regulator *regulator)
{ {
return NULL; return NULL;

View File

@ -98,6 +98,7 @@ struct regulator_linear_range {
* REGULATOR_STATUS value (or negative errno) * REGULATOR_STATUS value (or negative errno)
* @get_optimum_mode: Get the most efficient operating mode for the regulator * @get_optimum_mode: Get the most efficient operating mode for the regulator
* when running with the specified parameters. * when running with the specified parameters.
* @set_load: Set the load for the regulator.
* *
* @set_bypass: Set the regulator in bypass mode. * @set_bypass: Set the regulator in bypass mode.
* @get_bypass: Get the regulator bypass mode state. * @get_bypass: Get the regulator bypass mode state.
@ -167,6 +168,8 @@ struct regulator_ops {
/* get most efficient regulator operating mode for load */ /* get most efficient regulator operating mode for load */
unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
int output_uV, int load_uA); 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 */ /* control and report on bypass mode */
int (*set_bypass)(struct regulator_dev *dev, bool enable); int (*set_bypass)(struct regulator_dev *dev, bool enable);
@ -367,6 +370,7 @@ struct regulator_dev {
struct device dev; struct device dev;
struct regulation_constraints *constraints; struct regulation_constraints *constraints;
struct regulator *supply; /* for tree */ struct regulator *supply; /* for tree */
const char *supply_name;
struct regmap *regmap; struct regmap *regmap;
struct delayed_work disable_work; struct delayed_work disable_work;