mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 01:04:08 +08:00
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:
commit
d700b05671
@ -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:
|
||||
--------
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -28,6 +28,35 @@
|
||||
#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.
|
||||
*/
|
||||
@ -94,10 +123,15 @@
|
||||
#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 },
|
||||
{ },
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,6 +678,12 @@ static int drms_uA_update(struct regulator_dev *rdev)
|
||||
list_for_each_entry(sibling, &rdev->consumer_list, list)
|
||||
current_uA += sibling->uA_load;
|
||||
|
||||
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);
|
||||
@ -691,6 +699,7 @@ static int drms_uA_update(struct regulator_dev *rdev)
|
||||
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;
|
||||
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 */
|
||||
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 == ®ulator_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(®ulator_list_mutex);
|
||||
|
||||
list_for_each_entry(rdev, list, list) {
|
||||
if (rdev->supply)
|
||||
continue;
|
||||
|
||||
regulator_summary_show_subtree(s, rdev, 0);
|
||||
}
|
||||
|
||||
mutex_unlock(®ulator_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,
|
||||
®ulator_list, ®ulator_summary_fops);
|
||||
|
||||
regulator_dummy_init();
|
||||
|
||||
return ret;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
seq_printf(s, "ux500-regulator power state count: %i\n",
|
||||
power_state_active_get());
|
||||
if (err < 0)
|
||||
dev_err(dev, "seq_printf overflow\n");
|
||||
|
||||
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,
|
||||
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");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
®ulators[id], &config);
|
||||
®ulators[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);
|
||||
}
|
||||
}
|
||||
|
@ -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,8 +442,8 @@ 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 = false;
|
||||
else
|
||||
boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
|
||||
|
||||
switch (pdata->subdevs[i].id) {
|
||||
|
@ -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;
|
||||
|
@ -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,26 +734,193 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
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.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");
|
||||
dev_err(&pdev->dev, "failed to register %s\n", reg->name);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -41,15 +41,11 @@
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,19 @@
|
||||
|
||||
#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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user