Commit 92d07a8f authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'regulator/topic/max77686',...

Merge remote-tracking branches 'regulator/topic/max77686', 'regulator/topic/max77693', 'regulator/topic/max77802', 'regulator/topic/power-off' and 'regulator/topic/rk808' into regulator-next
* Generic system power control capability
Power-management integrated circuits or miscellaneous hardware components are
sometimes able to control the system power. The device driver associated with these
components might need to define this capability, which tells the kernel that
it can be used to switch off the system. The corresponding device must have the
standard property "system-power-controller" in its device node. This property
marks the device as able to control the system power. In order to test if this
property is found programmatically, use the helper function
"of_device_is_system_power_controller" from of.h .
Example:
act8846: act8846@5 {
compatible = "active-semi,act8846";
status = "okay";
system-power-controller;
}
...@@ -5,6 +5,10 @@ Required properties: ...@@ -5,6 +5,10 @@ Required properties:
- compatible: "active-semi,act8846" or "active-semi,act8865" - compatible: "active-semi,act8846" or "active-semi,act8865"
- reg: I2C slave address - 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 .
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:
......
...@@ -25,6 +25,29 @@ with their hardware counterparts as follow. The valid names are: ...@@ -25,6 +25,29 @@ with their hardware counterparts as follow. The valid names are:
example: LDO1, LDO2, LDO35. example: LDO1, LDO2, LDO35.
-BUCKn : for BUCKs, where n can lie in range 1 to 10. -BUCKn : for BUCKs, where n can lie in range 1 to 10.
example: BUCK1, BUCK5, BUCK10. example: BUCK1, BUCK5, BUCK10.
The max77802 regulator supports two different operating modes: Normal and Low
Power Mode. Some regulators support the modes to be changed at startup or by
the consumers during normal operation while others only support to change the
mode during system suspend. The standard regulator suspend states binding can
be used to configure the regulator operating mode.
The regulators that support the standard "regulator-initial-mode" property,
changing their mode during normal operation are: LDOs 1, 3, 20 and 21.
The possible values for "regulator-initial-mode" and "regulator-mode" are:
1: Normal regulator voltage output mode.
3: Low Power which reduces the quiescent current down to only 1uA
The list of valid modes are defined in the dt-bindings/clock/maxim,max77802.h
header and can be included by device tree source files.
The standard "regulator-mode" property can only be used for regulators that
support changing their mode to Low Power Mode during suspend. These regulators
are: BUCKs 2-4 and LDOs 1-35. Also, it only takes effect if the regulator has
been enabled for the given suspend state using "regulator-on-in-suspend" and
has not been disabled for that state using "regulator-off-in-suspend".
Example: Example:
max77802@09 { max77802@09 {
...@@ -36,11 +59,23 @@ Example: ...@@ -36,11 +59,23 @@ Example:
#size-cells = <0>; #size-cells = <0>;
regulators { regulators {
ldo1_reg: LDO1 {
regulator-name = "vdd_1v0";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
regulator-initial-mode = <MAX77802_OPMODE_LP>;
};
ldo11_reg: LDO11 { ldo11_reg: LDO11 {
regulator-name = "vdd_ldo11"; regulator-name = "vdd_ldo11";
regulator-min-microvolt = <1900000>; regulator-min-microvolt = <1900000>;
regulator-max-microvolt = <1900000>; regulator-max-microvolt = <1900000>;
regulator-always-on; regulator-always-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-mode = <MAX77802_OPMODE_LP>;
};
}; };
buck1_reg: BUCK1 { buck1_reg: BUCK1 {
......
...@@ -19,6 +19,24 @@ Optional properties: ...@@ -19,6 +19,24 @@ Optional properties:
design requires. This property describes the total system ramp time design requires. This property describes the total system ramp time
required due to the combination of internal ramping of the regulator itself, required due to the combination of internal ramping of the regulator itself,
and board design issues such as trace capacitance and load on the supply. and board design issues such as trace capacitance and load on the supply.
- regulator-state-mem sub-root node for Suspend-to-RAM mode
: suspend to memory, the device goes to sleep, but all data stored in memory,
only some external interrupt can wake the device.
- regulator-state-disk sub-root node for Suspend-to-DISK mode
: suspend to disk, this state operates similarly to Suspend-to-RAM,
but includes a final step of writing memory contents to disk.
- regulator-state-[mem/disk] node has following common properties:
- regulator-on-in-suspend: regulator should be on in suspend state.
- regulator-off-in-suspend: regulator should be off in suspend state.
- regulator-suspend-microvolt: regulator should be set to this voltage
in suspend.
- regulator-mode: operating mode in the given suspend state.
The set of possible operating modes depends on the capabilities of
every hardware so the valid modes are documented on each regulator
device tree binding document.
- regulator-initial-mode: initial operating mode. The set of possible operating
modes depends on the capabilities of every hardware so each device binding
documentation explains which values the regulator supports.
Deprecated properties: Deprecated properties:
- regulator-compatible: If a regulator chip contains multiple - regulator-compatible: If a regulator chip contains multiple
...@@ -34,6 +52,10 @@ Example: ...@@ -34,6 +52,10 @@ Example:
regulator-max-microvolt = <2500000>; regulator-max-microvolt = <2500000>;
regulator-always-on; regulator-always-on;
vin-supply = <&vin>; vin-supply = <&vin>;
regulator-state-mem {
regulator-on-in-suspend;
};
}; };
Regulator Consumers: Regulator Consumers:
......
...@@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, ...@@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
for_each_child_of_node(nproot, np) { for_each_child_of_node(nproot, np) {
if (!of_node_cmp(np->name, info->desc.name)) { if (!of_node_cmp(np->name, info->desc.name)) {
config->init_data = config->init_data =
of_get_regulator_init_data(&pdev->dev, np); of_get_regulator_init_data(&pdev->dev, np,
&info->desc);
config->of_node = np; config->of_node = np;
break; break;
} }
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
#define ACT8846_REG12_VSET 0xa0 #define ACT8846_REG12_VSET 0xa0
#define ACT8846_REG12_CTRL 0xa1 #define ACT8846_REG12_CTRL 0xa1
#define ACT8846_REG13_CTRL 0xb1 #define ACT8846_REG13_CTRL 0xb1
#define ACT8846_GLB_OFF_CTRL 0xc3
#define ACT8846_OFF_SYSMASK 0x18
/* /*
* ACT8865 Global Register Map. * ACT8865 Global Register Map.
...@@ -84,6 +86,7 @@ ...@@ -84,6 +86,7 @@
#define ACT8865_LDO3_CTRL 0x61 #define ACT8865_LDO3_CTRL 0x61
#define ACT8865_LDO4_VSET 0x64 #define ACT8865_LDO4_VSET 0x64
#define ACT8865_LDO4_CTRL 0x65 #define ACT8865_LDO4_CTRL 0x65
#define ACT8865_MSTROFF 0x20
/* /*
* Field Definitions. * Field Definitions.
...@@ -98,6 +101,8 @@ ...@@ -98,6 +101,8 @@
struct act8865 { struct act8865 {
struct regmap *regmap; struct regmap *regmap;
int off_reg;
int off_mask;
}; };
static const struct regmap_config act8865_regmap_config = { static const struct regmap_config act8865_regmap_config = {
...@@ -275,6 +280,16 @@ static struct regulator_init_data ...@@ -275,6 +280,16 @@ static struct regulator_init_data
return NULL; return NULL;
} }
static struct i2c_client *act8865_i2c_client;
static void act8865_power_off(void)
{
struct act8865 *act8865;
act8865 = i2c_get_clientdata(act8865_i2c_client);
regmap_write(act8865->regmap, act8865->off_reg, act8865->off_mask);
while (1);
}
static int act8865_pmic_probe(struct i2c_client *client, static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
...@@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client, ...@@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
int i, ret, num_regulators; int i, ret, num_regulators;
struct act8865 *act8865; struct act8865 *act8865;
unsigned long type; unsigned long type;
int off_reg, off_mask;
pdata = dev_get_platdata(dev); pdata = dev_get_platdata(dev);
...@@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client, ...@@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client,
case ACT8846: case ACT8846:
regulators = act8846_regulators; regulators = act8846_regulators;
num_regulators = ARRAY_SIZE(act8846_regulators); num_regulators = ARRAY_SIZE(act8846_regulators);
off_reg = ACT8846_GLB_OFF_CTRL;
off_mask = ACT8846_OFF_SYSMASK;
break; break;
case ACT8865: case ACT8865:
regulators = act8865_regulators; regulators = act8865_regulators;
num_regulators = ARRAY_SIZE(act8865_regulators); num_regulators = ARRAY_SIZE(act8865_regulators);
off_reg = ACT8865_SYS_CTRL;
off_mask = ACT8865_MSTROFF;
break; break;
default: default:
dev_err(dev, "invalid device id %lu\n", type); dev_err(dev, "invalid device id %lu\n", type);
...@@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client, ...@@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client,
return ret; return ret;
} }
if (of_device_is_system_power_controller(dev->of_node)) {
if (!pm_power_off) {
act8865_i2c_client = client;
act8865->off_reg = off_reg;
act8865->off_mask = off_mask;
pm_power_off = act8865_power_off;
} else {
dev_err(dev, "Failed to set poweroff capability, already defined\n");
}
}
/* Finally register devices */ /* Finally register devices */
for (i = 0; i < num_regulators; i++) { for (i = 0; i < num_regulators; i++) {
const struct regulator_desc *desc = &regulators[i]; const struct regulator_desc *desc = &regulators[i];
......
...@@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev) ...@@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev)
int ret = 0; int ret = 0;
u32 val; u32 val;
initdata = of_get_regulator_init_data(dev, np);
sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
if (!sreg) if (!sreg)
return -ENOMEM; return -ENOMEM;
sreg->initdata = initdata;
sreg->name = of_get_property(np, "regulator-name", NULL); sreg->name = of_get_property(np, "regulator-name", NULL);
rdesc = &sreg->rdesc; rdesc = &sreg->rdesc;
rdesc->name = sreg->name; rdesc->name = sreg->name;
rdesc->type = REGULATOR_VOLTAGE; rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE; rdesc->owner = THIS_MODULE;
initdata = of_get_regulator_init_data(dev, np, rdesc);
sreg->initdata = initdata;
anatop_np = of_get_parent(np); anatop_np = of_get_parent(np);
if (!anatop_np) if (!anatop_np)
return -ENODEV; return -ENODEV;
......
...@@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = { ...@@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = {
}; };
static int arizona_ldo1_of_get_pdata(struct arizona *arizona, static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
struct regulator_config *config) struct regulator_config *config,
const struct regulator_desc *desc)
{ {
struct arizona_pdata *pdata = &arizona->pdata; struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_ldo1 *ldo1 = config->driver_data; struct arizona_ldo1 *ldo1 = config->driver_data;
...@@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona, ...@@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
if (init_node) { if (init_node) {
config->of_node = init_node; config->of_node = init_node;
init_data = of_get_regulator_init_data(arizona->dev, init_node); init_data = of_get_regulator_init_data(arizona->dev, init_node,
desc);
if (init_data) { if (init_data) {
init_data->consumer_supplies = &ldo1->supply; init_data->consumer_supplies = &ldo1->supply;
...@@ -257,7 +259,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -257,7 +259,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_OF)) { if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) { if (!dev_get_platdata(arizona->dev)) {
ret = arizona_ldo1_of_get_pdata(arizona, &config); ret = arizona_ldo1_of_get_pdata(arizona, &config, desc);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { ...@@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
}; };
static int arizona_micsupp_of_get_pdata(struct arizona *arizona, static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
struct regulator_config *config) struct regulator_config *config,
const struct regulator_desc *desc)
{ {
struct arizona_pdata *pdata = &arizona->pdata; struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_micsupp *micsupp = config->driver_data; struct arizona_micsupp *micsupp = config->driver_data;
...@@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona, ...@@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
if (np) { if (np) {
config->of_node = np; config->of_node = np;
init_data = of_get_regulator_init_data(arizona->dev, np); init_data = of_get_regulator_init_data(arizona->dev, np, desc);
if (init_data) { if (init_data) {
init_data->consumer_supplies = &micsupp->supply; init_data->consumer_supplies = &micsupp->supply;
...@@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) ...@@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_OF)) { if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) { if (!dev_get_platdata(arizona->dev)) {
ret = arizona_micsupp_of_get_pdata(arizona, &config); ret = arizona_micsupp_of_get_pdata(arizona, &config,
desc);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
......
...@@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev) ...@@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
if (!of_node_cmp(np->name, if (!of_node_cmp(np->name,
regulator->info->reg_desc.name)) { regulator->info->reg_desc.name)) {
config.init_data = of_get_regulator_init_data( config.init_data = of_get_regulator_init_data(
&pdev->dev, np); &pdev->dev, np,
&regulator->info->reg_desc);
config.of_node = np; config.of_node = np;
break; break;
} }
......
...@@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c, ...@@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
config.dev = &i2c->dev; config.dev = &i2c->dev;
config.init_data = pdata ? &pdata->da9210_constraints : config.init_data = pdata ? &pdata->da9210_constraints :
of_get_regulator_init_data(dev, dev->of_node); of_get_regulator_init_data(dev, dev->of_node, &da9210_reg);
config.driver_data = chip; config.driver_data = chip;
config.regmap = chip->regmap; config.regmap = chip->regmap;
config.of_node = dev->of_node; config.of_node = dev->of_node;
......
...@@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = { ...@@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = {
}; };
static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
struct device_node *np) struct device_node *np,
const struct regulator_desc *desc)
{ {
struct fan53555_platform_data *pdata; struct fan53555_platform_data *pdata;
int ret; int ret;
...@@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, ...@@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
if (!pdata) if (!pdata)
return NULL; return NULL;
pdata->regulator = of_get_regulator_init_data(dev, np); pdata->regulator = of_get_regulator_init_data(dev, np, desc);
ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
&tmp); &tmp);
...@@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client, ...@@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client,
unsigned int val; unsigned int val;
int ret; int ret;
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
GFP_KERNEL);
if (!di)
return -ENOMEM;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
if (!pdata) if (!pdata)
pdata = fan53555_parse_dt(&client->dev, np); pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
if (!pdata || !pdata->regulator) { if (!pdata || !pdata->regulator) {
dev_err(&client->dev, "Platform data not found!\n"); dev_err(&client->dev, "Platform data not found!\n");
return -ENODEV; return -ENODEV;
} }
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
GFP_KERNEL);
if (!di)
return -ENOMEM;
di->regulator = pdata->regulator; di->regulator = pdata->regulator;
if (client->dev.of_node) { if (client->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
......
...@@ -40,13 +40,15 @@ struct fixed_voltage_data { ...@@ -40,13 +40,15 @@ struct fixed_voltage_data {
/** /**
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info * of_get_fixed_voltage_config - extract fixed_voltage_config structure info
* @dev: device requesting for fixed_voltage_config * @dev: device requesting for fixed_voltage_config
* @desc: regulator description
* *
* Populates fixed_voltage_config structure by extracting data from device * Populates fixed_voltage_config structure by extracting data from device
* tree node, returns a pointer to the populated structure of NULL if memory * tree node, returns a pointer to the populated structure of NULL if memory
* alloc fails. * alloc fails.
*/ */
static struct fixed_voltage_config * static struct fixed_voltage_config *
of_get_fixed_voltage_config(struct device *dev) of_get_fixed_voltage_config(struct device *dev,
const struct regulator_desc *desc)
{ {
struct fixed_voltage_config *config; struct fixed_voltage_config *config;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
...@@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev) ...@@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev)
if (!config) if (!config)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
config->init_data = of_get_regulator_init_data(dev, dev->of_node); config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc);
if (!config->init_data) if (!config->init_data)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
struct regulator_config cfg = { }; struct regulator_config cfg = { };
int ret; int ret;
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
config = of_get_fixed_voltage_config(&pdev->dev); config = of_get_fixed_voltage_config(&pdev->dev,
&drvdata->desc);
if (IS_ERR(config)) if (IS_ERR(config))
return PTR_ERR(config); return PTR_ERR(config);
} else { } else {
...@@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
if (!config) if (!config)
return -ENOMEM; return -ENOMEM;
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->desc.name = devm_kstrdup(&pdev->dev, drvdata->desc.name = devm_kstrdup(&pdev->dev,
config->supply_name, config->supply_name,
GFP_KERNEL); GFP_KERNEL);
......
...@@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = { ...@@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
}; };
static struct gpio_regulator_config * static struct gpio_regulator_config *
of_get_gpio_regulator_config(struct device *dev, struct device_node *np) of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
const struct regulator_desc *desc)
{ {
struct gpio_regulator_config *config; struct gpio_regulator_config *config;
const char *regtype; const char *regtype;
...@@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) ...@@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
if (!config) if (!config)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
config->init_data = of_get_regulator_init_data(dev, np); config->init_data = of_get_regulator_init_data(dev, np, desc);
if (!config->init_data) if (!config->init_data)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -250,17 +251,18 @@ static int gpio_regulator_probe(struct platform_device *pdev) ...@@ -250,17 +251,18 @@ static int gpio_regulator_probe(struct platform_device *pdev)
struct regulator_config cfg = { }; struct regulator_config cfg = { };
int ptr, ret, state; int ptr, ret, state;
if (np) {
config = of_get_gpio_regulator_config(&pdev->dev, np);
if (IS_ERR(config))
return PTR_ERR(config);
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL); GFP_KERNEL);
if (drvdata == NULL) if (drvdata == NULL)
return -ENOMEM; return -ENOMEM;
if (np) {
config = of_get_gpio_regulator_config(&pdev->dev, np,
&drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
}
drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
if (drvdata->desc.name == NULL) { if (drvdata->desc.name == NULL) {
dev_err(&pdev->dev, "Failed to allocate supply name\n"); dev_err(&pdev->dev, "Failed to allocate supply name\n");
......
...@@ -45,6 +45,23 @@ ...@@ -45,6 +45,23 @@
#define MAX77686_DVS_MINUV 600000 #define MAX77686_DVS_MINUV 600000
#define MAX77686_DVS_UVSTEP 12500 #define MAX77686_DVS_UVSTEP 12500
/*
* Values used for configuring LDOs and bucks.
* Forcing low power mode: LDO1, 3-5, 9, 13, 17-26
*/
#define MAX77686_LDO_LOWPOWER 0x1
/*
* On/off controlled by PWRREQ:
* - LDO2, 6-8, 10-12, 14-16
* - buck[1234]
*/
#define MAX77686_OFF_PWRREQ 0x1
/* Low power mode controlled by PWRREQ: All LDOs */
#define MAX77686_LDO_LOWPOWER_PWRREQ 0x2
/* Forcing low power mode: buck[234] */
#define MAX77686_BUCK_LOWPOWER 0x2
#define MAX77686_NORMAL 0x3
#define MAX77686_OPMODE_SHIFT 6 #define MAX77686_OPMODE_SHIFT 6
#define MAX77686_OPMODE_BUCK234_SHIFT 4 #define MAX77686_OPMODE_BUCK234_SHIFT 4
#define MAX77686_OPMODE_MASK 0x3 #define MAX77686_OPMODE_MASK 0x3
...@@ -65,23 +82,36 @@ enum max77686_ramp_rate { ...@@ -65,23 +82,36 @@ enum max77686_ramp_rate {
}; };
struct max77686_data { struct max77686_data {
/* Array indexed by regulator id */
unsigned int opmode[MAX77686_REGULATORS]; unsigned int opmode[MAX77686_REGULATORS];
}; };
/* Some BUCKS supports Normal[ON/OFF] mode during suspend */ static unsigned int max77686_get_opmode_shift(int id)
static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
{ {
unsigned int val; switch (id) {
case MAX77686_BUCK1:
case MAX77686_BUCK5 ... MAX77686_BUCK9:
return 0;
case MAX77686_BUCK2 ... MAX77686_BUCK4:
return MAX77686_OPMODE_BUCK234_SHIFT;
default:
/* all LDOs */
return MAX77686_OPMODE_SHIFT;
}
}
/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */
static int max77686_set_suspend_disable(struct regulator_dev *rdev)
{
unsigned int val, shift;
struct max77686_data *max77686 = rdev_get_drvdata(rdev); struct max77686_data *max77686 = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev); int ret, id = rdev_get_id(rdev);
if (id == MAX77686_BUCK1) shift = max77686_get_opmode_shift(id);
val = 0x1; val = MAX77686_OFF_PWRREQ;
else
val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val); rdev->desc->enable_mask, val << shift);
if (ret) if (ret)
return ret; return ret;
...@@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, ...@@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
switch (mode) { switch (mode) {
case REGULATOR_MODE_IDLE: /* ON in LP Mode */ case REGULATOR_MODE_IDLE: /* ON in LP Mode */
val = 0x2 << MAX77686_OPMODE_SHIFT; val = MAX77686_LDO_LOWPOWER_PWRREQ;
break; break;
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
val = 0x3 << MAX77686_OPMODE_SHIFT; val = MAX77686_NORMAL;
break; break;
default: default:
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
...@@ -115,7 +145,8 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, ...@@ -115,7 +145,8 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
} }
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val); rdev->desc->enable_mask,
val << MAX77686_OPMODE_SHIFT);
if (ret) if (ret)
return ret; return ret;
...@@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, ...@@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
switch (mode) { switch (mode) {
case REGULATOR_MODE_STANDBY: /* switch off */ case REGULATOR_MODE_STANDBY: /* switch off */
val = 0x1 << MAX77686_OPMODE_SHIFT; val = MAX77686_OFF_PWRREQ;
break; break;
case REGULATOR_MODE_IDLE: /* ON in LP Mode */ case REGULATOR_MODE_IDLE: /* ON in LP Mode */
val = 0x2 << MAX77686_OPMODE_SHIFT; val = MAX77686_LDO_LOWPOWER_PWRREQ;
break; break;
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
val = 0x3 << MAX77686_OPMODE_SHIFT; val = MAX77686_NORMAL;
break; break;
default: default:
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
...@@ -148,7 +179,8 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, ...@@ -148,7 +179,8 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
} }
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val); rdev->desc->enable_mask,
val << MAX77686_OPMODE_SHIFT);
if (ret) if (ret)
return ret; return ret;
...@@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, ...@@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
static int max77686_enable(struct regulator_dev *rdev) static int max77686_enable(struct regulator_dev *rdev)
{ {
struct max77686_data *max77686 = rdev_get_drvdata(rdev); struct max77686_data *max77686 = rdev_get_drvdata(rdev);
unsigned int shift;
int id = rdev_get_id(rdev);
shift = max77686_get_opmode_shift(id);
if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)
max77686->opmode[id] = MAX77686_NORMAL;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, rdev->desc->enable_mask,
max77686->opmode[rdev_get_id(rdev)]); max77686->opmode[id] << shift);
} }
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
...@@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = { ...@@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_mode = max77686_ldo_set_suspend_mode, .set_suspend_mode = max77686_ldo_set_suspend_mode,
.set_suspend_disable = max77686_set_suspend_disable,
}; };
static struct regulator_ops max77686_buck1_ops = { static struct regulator_ops max77686_buck1_ops = {
...@@ -223,7 +263,7 @@ static struct regulator_ops max77686_buck1_ops = { ...@@ -223,7 +263,7 @@ static struct regulator_ops max77686_buck1_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_disable = max77686_buck_set_suspend_disable, .set_suspend_disable = max77686_set_suspend_disable,
}; };
static struct regulator_ops max77686_buck_dvs_ops = { static struct regulator_ops max77686_buck_dvs_ops = {
...@@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77686_set_ramp_delay, .set_ramp_delay = max77686_set_ramp_delay,
.set_suspend_disable = max77686_buck_set_suspend_disable, .set_suspend_disable = max77686_set_suspend_disable,
}; };
#define regulator_desc_ldo(num) { \ #define regulator_desc_ldo(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \ .id = MAX77686_LDO##num, \
.ops = &max77686_ops, \ .ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_lpm_ldo(num) { \ #define regulator_desc_lpm_ldo(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \ .id = MAX77686_LDO##num, \
.ops = &max77686_ldo_ops, \ .ops = &max77686_ldo_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_ldo_low(num) { \ #define regulator_desc_ldo_low(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \ .id = MAX77686_LDO##num, \
.ops = &max77686_ldo_ops, \ .ops = &max77686_ldo_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_ldo1_low(num) { \ #define regulator_desc_ldo1_low(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \ .id = MAX77686_LDO##num, \
.ops = &max77686_ops, \ .ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_buck(num) { \ #define regulator_desc_buck(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \ .id = MAX77686_BUCK##num, \
.ops = &max77686_ops, \ .ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_buck1(num) { \ #define regulator_desc_buck1(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \ .id = MAX77686_BUCK##num, \
.ops = &max77686_buck1_ops, \ .ops = &max77686_buck1_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
} }
#define regulator_desc_buck_dvs(num) { \ #define regulator_desc_buck_dvs(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \ .id = MAX77686_BUCK##num, \
.ops = &max77686_buck_dvs_ops, \ .ops = &max77686_buck_dvs_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
...@@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { ...@@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
<< MAX77686_OPMODE_BUCK234_SHIFT, \ << MAX77686_OPMODE_BUCK234_SHIFT, \
} }
static struct regulator_desc regulators[] = { static const struct regulator_desc regulators[] = {
regulator_desc_ldo1_low(1), regulator_desc_ldo1_low(1),
regulator_desc_ldo_low(2), regulator_desc_ldo_low(2),
regulator_desc_ldo(3), regulator_desc_ldo(3),
...@@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = { ...@@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = {
regulator_desc_buck(9), regulator_desc_buck(9),
}; };
#ifdef CONFIG_OF
static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
struct max77686_platform_data *pdata)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct device_node *pmic_np, *regulators_np;
struct max77686_regulator_data *rdata;
struct of_regulator_match rmatch = { };
unsigned int i;
pmic_np = iodev->dev->of_node;
regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
if (!regulators_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL;
}
pdata->num_regulators = ARRAY_SIZE(regulators);
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL);
if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM;
}
for (i = 0; i < pdata->num_regulators; i++) {
rmatch.name = regulators[i].name;
rmatch.init_data = NULL;
rmatch.of_node = NULL;
of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
rdata[i].initdata = rmatch.init_data;
rdata[i].of_node = rmatch.of_node;
}
pdata->regulators = rdata;
of_node_put(regulators_np);
return 0;
}
#else
static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
struct max77686_platform_data *pdata)
{
return 0;
}
#endif /* CONFIG_OF */
static int max77686_pmic_probe(struct platform_device *pdev) static int max77686_pmic_probe(struct platform_device *pdev)
{ {
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
struct max77686_data *max77686; struct max77686_data *max77686;
int i, ret = 0; int i;
struct regulator_config config = { }; struct regulator_config config = { };
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
if (!pdata) {
dev_err(&pdev->dev, "no platform data found for regulator\n");
return -ENODEV;
}
if (iodev->dev->of_node) {
ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
if (ret)
return ret;
}
if (pdata->num_regulators != MAX77686_REGULATORS) {
dev_err(&pdev->dev,
"Invalid initial data for regulator's initialiation\n");
return -EINVAL;
}
max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
GFP_KERNEL); GFP_KERNEL);
if (!max77686) if (!max77686)
return -ENOMEM; return -ENOMEM;
config.dev = &pdev->dev; config.dev = iodev->dev;
config.regmap = iodev->regmap; config.regmap = iodev->regmap;
config.driver_data = max77686; config.driver_data = max77686;
platform_set_drvdata(pdev, max77686); platform_set_drvdata(pdev, max77686);
for (i = 0; i < MAX77686_REGULATORS; i++) { for (i = 0; i < MAX77686_REGULATORS; i++) {
struct regulator_dev *rdev; struct regulator_dev *rdev;
int id = regulators[i].id;
config.init_data = pdata->regulators[i].initdata; max77686->opmode[id] = MAX77686_NORMAL;
config.of_node = pdata->regulators[i].of_node;
max77686->opmode[i] = regulators[i].enable_mask;
rdev = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
int ret = PTR_ERR(rdev);
dev_err(&pdev->dev, dev_err(&pdev->dev,
"regulator init failed for %d\n", i); "regulator init failed for %d: %d\n", i, ret);
return PTR_ERR(rdev); return ret;
} }
} }
......
...@@ -139,7 +139,7 @@ static struct regulator_ops max77693_charger_ops = { ...@@ -139,7 +139,7 @@ static struct regulator_ops max77693_charger_ops = {
.enable_mask = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \ .enable_mask = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \
} }
static struct regulator_desc regulators[] = { static const struct regulator_desc regulators[] = {
regulator_desc_esafeout(1), regulator_desc_esafeout(1),
regulator_desc_esafeout(2), regulator_desc_esafeout(2),
{ {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/mfd/max77686.h> #include <linux/mfd/max77686.h>
#include <linux/mfd/max77686-private.h> #include <linux/mfd/max77686-private.h>
#include <dt-bindings/regulator/maxim,max77802.h>
/* Default ramp delay in case it is not manually set */ /* Default ramp delay in case it is not manually set */
#define MAX77802_RAMP_DELAY 100000 /* uV/us */ #define MAX77802_RAMP_DELAY 100000 /* uV/us */
...@@ -49,6 +50,10 @@ ...@@ -49,6 +50,10 @@
#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0 #define MAX77802_RAMP_RATE_MASK_4BIT 0xF0
#define MAX77802_RAMP_RATE_SHIFT_4BIT 4 #define MAX77802_RAMP_RATE_SHIFT_4BIT 4
#define MAX77802_STATUS_OFF 0x0
#define MAX77802_OFF_PWRREQ 0x1
#define MAX77802_LP_PWRREQ 0x2
/* MAX77802 has two register formats: 2-bit and 4-bit */ /* MAX77802 has two register formats: 2-bit and 4-bit */
static const unsigned int ramp_table_77802_2bit[] = { static const unsigned int ramp_table_77802_2bit[] = {
12500, 12500,
...@@ -65,9 +70,16 @@ static unsigned int ramp_table_77802_4bit[] = { ...@@ -65,9 +70,16 @@ static unsigned int ramp_table_77802_4bit[] = {
}; };
struct max77802_regulator_prv { struct max77802_regulator_prv {
/* Array indexed by regulator id */
unsigned int opmode[MAX77802_REG_MAX]; unsigned int opmode[MAX77802_REG_MAX];
}; };
static inline unsigned int max77802_map_mode(unsigned int mode)
{
return mode == MAX77802_OPMODE_NORMAL ?
REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
}
static int max77802_get_opmode_shift(int id) static int max77802_get_opmode_shift(int id)
{ {
if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 && if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
...@@ -83,17 +95,16 @@ static int max77802_get_opmode_shift(int id) ...@@ -83,17 +95,16 @@ static int max77802_get_opmode_shift(int id)
return -EINVAL; return -EINVAL;
} }
/* /**
* Some BUCKS supports Normal[ON/OFF] mode during suspend * max77802_set_suspend_disable - Disable the regulator during system suspend
* @rdev: regulator to mark as disabled
* *
* BUCK 1, 6, 2-4, 5, 7-10 (all) * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ.
* * Configure the regulator so the PMIC will turn it OFF during system suspend.
* The other mode (0x02) will make PWRREQ switch between normal
* and low power.
*/ */
static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev) static int max77802_set_suspend_disable(struct regulator_dev *rdev)
{ {
unsigned int val = MAX77802_OPMODE_STANDBY; unsigned int val = MAX77802_OFF_PWRREQ;
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
int shift = max77802_get_opmode_shift(id); int shift = max77802_get_opmode_shift(id);
...@@ -104,14 +115,11 @@ static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev) ...@@ -104,14 +115,11 @@ static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev)
} }
/* /*
* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state * Some LDOs support Low Power Mode while the system is running.
* (Enable Control Logic1 by PWRREQ)
*
* LDOs 2, 4-19, 22-35.
* *
* LDOs 1, 3, 20, 21.
*/ */
static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev, static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
unsigned int mode)
{ {
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
...@@ -119,14 +127,11 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev, ...@@ -119,14 +127,11 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
int shift = max77802_get_opmode_shift(id); int shift = max77802_get_opmode_shift(id);
switch (mode) { switch (mode) {
case REGULATOR_MODE_IDLE: /* ON in LP Mode */ case REGULATOR_MODE_STANDBY:
val = MAX77802_OPMODE_LP; val = MAX77802_OPMODE_LP; /* ON in Low Power Mode */
break; break;
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ case REGULATOR_MODE_NORMAL:
val = MAX77802_OPMODE_NORMAL; val = MAX77802_OPMODE_NORMAL; /* ON in Normal Mode */
break;
case REGULATOR_MODE_STANDBY: /* ON/OFF by PWRREQ */
val = MAX77802_OPMODE_STANDBY;
break; break;
default: default:
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
...@@ -139,35 +144,76 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev, ...@@ -139,35 +144,76 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
rdev->desc->enable_mask, val << shift); rdev->desc->enable_mask, val << shift);
} }
/* static unsigned max77802_get_mode(struct regulator_dev *rdev)
* Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs {
* (Enable Control Logic2 by PWRREQ) struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
return max77802_map_mode(max77802->opmode[id]);
}
/**
* max77802_set_suspend_mode - set regulator opmode when the system is suspended
* @rdev: regulator to change mode
* @mode: operating mode to be set
* *
* LDOs 1, 20, 21, and 3, * Will set the operating mode for the regulators during system suspend.
* This function is valid for the three different enable control logics:
* *
* Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35)
* Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21)
* Enable Control Logic3 by PWRREQ (LDO 3)
*
* If setting the regulator mode fails, the function only warns but does
* not return an error code to avoid the regulator core to stop setting
* the operating mode for the remaining regulators.
*/ */
static int max77802_ldo_set_suspend_mode_logic2(struct regulator_dev *rdev, static int max77802_set_suspend_mode(struct regulator_dev *rdev,
unsigned int mode) unsigned int mode)
{ {
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
unsigned int val; unsigned int val;
int shift = max77802_get_opmode_shift(id); int shift = max77802_get_opmode_shift(id);
/*
* If the regulator has been disabled for suspend
* then is invalid to try setting a suspend mode.
*/
if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) {
dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n",
rdev->desc->name, mode);
return 0;
}
switch (mode) { switch (mode) {
case REGULATOR_MODE_IDLE: /* ON in LP Mode */ case REGULATOR_MODE_STANDBY:
val = MAX77802_OPMODE_LP; /*
break; * If the regulator opmode is normal then enable
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ * ON in Low Power Mode by PWRREQ. If the mode is
val = MAX77802_OPMODE_NORMAL; * already Low Power then no action is required.
*/
if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
val = MAX77802_LP_PWRREQ;
else
return 0;
break; break;
case REGULATOR_MODE_NORMAL:
/*
* If the regulator operating mode is Low Power then
* normal is not a valid opmode in suspend. If the
* mode is already normal then no action is required.
*/
if (max77802->opmode[id] == MAX77802_OPMODE_LP)
dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n",
rdev->desc->name, mode);
return 0;
default: default:
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
rdev->desc->name, mode); rdev->desc->name, mode);
return -EINVAL; return -EINVAL;
} }
max77802->opmode[id] = val;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val << shift); rdev->desc->enable_mask, val << shift);
} }
...@@ -178,6 +224,9 @@ static int max77802_enable(struct regulator_dev *rdev) ...@@ -178,6 +224,9 @@ static int max77802_enable(struct regulator_dev *rdev)
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
int shift = max77802_get_opmode_shift(id); int shift = max77802_get_opmode_shift(id);
if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, rdev->desc->enable_mask,
max77802->opmode[id] << shift); max77802->opmode[id] << shift);
...@@ -247,7 +296,8 @@ static struct regulator_ops max77802_ldo_ops_logic1 = { ...@@ -247,7 +296,8 @@ static struct regulator_ops max77802_ldo_ops_logic1 = {
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_mode = max77802_ldo_set_suspend_mode_logic1, .set_suspend_disable = max77802_set_suspend_disable,
.set_suspend_mode = max77802_set_suspend_mode,
}; };
/* /*
...@@ -262,7 +312,9 @@ static struct regulator_ops max77802_ldo_ops_logic2 = { ...@@ -262,7 +312,9 @@ static struct regulator_ops max77802_ldo_ops_logic2 = {
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_mode = max77802_ldo_set_suspend_mode_logic2, .set_mode = max77802_set_mode,
.get_mode = max77802_get_mode,
.set_suspend_mode = max77802_set_suspend_mode,
}; };
/* BUCKS 1, 6 */ /* BUCKS 1, 6 */
...@@ -276,10 +328,25 @@ static struct regulator_ops max77802_buck_16_dvs_ops = { ...@@ -276,10 +328,25 @@ static struct regulator_ops max77802_buck_16_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77802_set_ramp_delay_4bit, .set_ramp_delay = max77802_set_ramp_delay_4bit,
.set_suspend_disable = max77802_buck_set_suspend_disable, .set_suspend_disable = max77802_set_suspend_disable,
}; };
/* BUCKs 2-4, 5, 7-10 */ /* BUCKs 2-4 */
static struct regulator_ops max77802_buck_234_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap,
.enable = max77802_enable,
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77802_set_ramp_delay_2bit,
.set_suspend_disable = max77802_set_suspend_disable,
.set_suspend_mode = max77802_set_suspend_mode,
};
/* BUCKs 5, 7-10 */
static struct regulator_ops max77802_buck_dvs_ops = { static struct regulator_ops max77802_buck_dvs_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
...@@ -290,12 +357,14 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -290,12 +357,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77802_set_ramp_delay_2bit, .set_ramp_delay = max77802_set_ramp_delay_2bit,
.set_suspend_disable = max77802_buck_set_suspend_disable, .set_suspend_disable = max77802_set_suspend_disable,
}; };
/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */ /* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
#define regulator_77802_desc_p_ldo(num, supply, log) { \ #define regulator_77802_desc_p_ldo(num, supply, log) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_LDO##num, \ .id = MAX77802_LDO##num, \
.supply_name = "inl"#supply, \ .supply_name = "inl"#supply, \
.ops = &max77802_ldo_ops_logic##log, \ .ops = &max77802_ldo_ops_logic##log, \
...@@ -309,11 +378,14 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -309,11 +378,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \ .vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
.of_map_mode = max77802_map_mode, \
} }
/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */ /* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
#define regulator_77802_desc_n_ldo(num, supply, log) { \ #define regulator_77802_desc_n_ldo(num, supply, log) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.of_match = of_match_ptr("LDO"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_LDO##num, \ .id = MAX77802_LDO##num, \
.supply_name = "inl"#supply, \ .supply_name = "inl"#supply, \
.ops = &max77802_ldo_ops_logic##log, \ .ops = &max77802_ldo_ops_logic##log, \
...@@ -327,11 +399,14 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -327,11 +399,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \ .vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
.of_map_mode = max77802_map_mode, \
} }
/* BUCKs 1, 6 */ /* BUCKs 1, 6 */
#define regulator_77802_desc_16_buck(num) { \ #define regulator_77802_desc_16_buck(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \ .id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \ .supply_name = "inb"#num, \
.ops = &max77802_buck_16_dvs_ops, \ .ops = &max77802_buck_16_dvs_ops, \
...@@ -345,14 +420,17 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -345,14 +420,17 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_DVS_VSEL_MASK, \ .vsel_mask = MAX77802_DVS_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \ .enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \
.enable_mask = MAX77802_OPMODE_MASK, \ .enable_mask = MAX77802_OPMODE_MASK, \
.of_map_mode = max77802_map_mode, \
} }
/* BUCKS 2-4 */ /* BUCKS 2-4 */
#define regulator_77802_desc_234_buck(num) { \ #define regulator_77802_desc_234_buck(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \ .id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \ .supply_name = "inb"#num, \
.ops = &max77802_buck_dvs_ops, \ .ops = &max77802_buck_234_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.min_uV = 600000, \ .min_uV = 600000, \
...@@ -364,11 +442,14 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -364,11 +442,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \ .enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \
.enable_mask = MAX77802_OPMODE_MASK << \ .enable_mask = MAX77802_OPMODE_MASK << \
MAX77802_OPMODE_BUCK234_SHIFT, \ MAX77802_OPMODE_BUCK234_SHIFT, \
.of_map_mode = max77802_map_mode, \
} }
/* BUCK 5 */ /* BUCK 5 */
#define regulator_77802_desc_buck5(num) { \ #define regulator_77802_desc_buck5(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \ .id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \ .supply_name = "inb"#num, \
.ops = &max77802_buck_dvs_ops, \ .ops = &max77802_buck_dvs_ops, \
...@@ -382,11 +463,14 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -382,11 +463,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \ .vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK5CTRL, \ .enable_reg = MAX77802_REG_BUCK5CTRL, \
.enable_mask = MAX77802_OPMODE_MASK, \ .enable_mask = MAX77802_OPMODE_MASK, \
.of_map_mode = max77802_map_mode, \
} }
/* BUCKs 7-10 */ /* BUCKs 7-10 */
#define regulator_77802_desc_buck7_10(num) { \ #define regulator_77802_desc_buck7_10(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.of_match = of_match_ptr("BUCK"#num), \
.regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \ .id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \ .supply_name = "inb"#num, \
.ops = &max77802_buck_dvs_ops, \ .ops = &max77802_buck_dvs_ops, \
...@@ -400,9 +484,10 @@ static struct regulator_ops max77802_buck_dvs_ops = { ...@@ -400,9 +484,10 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \ .vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \ .enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \
.enable_mask = MAX77802_OPMODE_MASK, \ .enable_mask = MAX77802_OPMODE_MASK, \
.of_map_mode = max77802_map_mode, \
} }
static struct regulator_desc regulators[] = { static const struct regulator_desc regulators[] = {
regulator_77802_desc_16_buck(1), regulator_77802_desc_16_buck(1),
regulator_77802_desc_234_buck(2), regulator_77802_desc_234_buck(2),
regulator_77802_desc_234_buck(3), regulator_77802_desc_234_buck(3),
...@@ -447,85 +532,19 @@ static struct regulator_desc regulators[] = { ...@@ -447,85 +532,19 @@ static struct regulator_desc regulators[] = {
regulator_77802_desc_n_ldo(35, 2, 1), regulator_77802_desc_n_ldo(35, 2, 1),
}; };
#ifdef CONFIG_OF
static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
struct max77686_platform_data *pdata)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct device_node *pmic_np, *regulators_np;
struct max77686_regulator_data *rdata;
struct of_regulator_match rmatch = { };
unsigned int i;
pmic_np = iodev->dev->of_node;
regulators_np = of_get_child_by_name(pmic_np, "regulators");
if (!regulators_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL;
}
pdata->num_regulators = ARRAY_SIZE(regulators);
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL);
if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM;
}
for (i = 0; i < pdata->num_regulators; i++) {
rmatch.name = regulators[i].name;
rmatch.init_data = NULL;
rmatch.of_node = NULL;
if (of_regulator_match(&pdev->dev, regulators_np, &rmatch,
1) != 1) {
dev_warn(&pdev->dev, "No matching regulator for '%s'\n",
rmatch.name);
continue;
}
rdata[i].initdata = rmatch.init_data;
rdata[i].of_node = rmatch.of_node;
rdata[i].id = regulators[i].id;
}
pdata->regulators = rdata;
of_node_put(regulators_np);
return 0;
}
#else
static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
struct max77686_platform_data *pdata)
{
return 0;
}
#endif /* CONFIG_OF */
static int max77802_pmic_probe(struct platform_device *pdev) static int max77802_pmic_probe(struct platform_device *pdev)
{ {
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
struct max77802_regulator_prv *max77802; struct max77802_regulator_prv *max77802;
int i, ret = 0, val; int i, val;
struct regulator_config config = { }; struct regulator_config config = { };
/* This is allocated by the MFD driver */
if (!pdata) {
dev_err(&pdev->dev, "no platform data found for regulator\n");
return -ENODEV;
}
max77802 = devm_kzalloc(&pdev->dev, max77802 = devm_kzalloc(&pdev->dev,
sizeof(struct max77802_regulator_prv), sizeof(struct max77802_regulator_prv),
GFP_KERNEL); GFP_KERNEL);
if (!max77802) if (!max77802)
return -ENOMEM; return -ENOMEM;
if (iodev->dev->of_node) {
ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
if (ret)
return ret;
}
config.dev = iodev->dev; config.dev = iodev->dev;
config.regmap = iodev->regmap; config.regmap = iodev->regmap;
config.driver_data = max77802; config.driver_data = max77802;
...@@ -533,21 +552,25 @@ static int max77802_pmic_probe(struct platform_device *pdev) ...@@ -533,21 +552,25 @@ static int max77802_pmic_probe(struct platform_device *pdev)
for (i = 0; i < MAX77802_REG_MAX; i++) { for (i = 0; i < MAX77802_REG_MAX; i++) {
struct regulator_dev *rdev; struct regulator_dev *rdev;
int id = pdata->regulators[i].id; int id = regulators[i].id;
int shift = max77802_get_opmode_shift(id); int shift = max77802_get_opmode_shift(id);
int ret;
config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].of_node;
ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val); ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
val = val >> shift & MAX77802_OPMODE_MASK; if (ret < 0) {
dev_warn(&pdev->dev,
"cannot read current mode for %d\n", i);
val = MAX77802_OPMODE_NORMAL;
} else {
val = val >> shift & MAX77802_OPMODE_MASK;
}
/* /*
* If the regulator is disabled and the system warm rebooted, * If the regulator is disabled and the system warm rebooted,
* the hardware reports OFF as the regulator operating mode. * the hardware reports OFF as the regulator operating mode.
* Default to operating mode NORMAL in that case. * Default to operating mode NORMAL in that case.
*/ */
if (val == MAX77802_OPMODE_OFF) if (val == MAX77802_STATUS_OFF)
max77802->opmode[id] = MAX77802_OPMODE_NORMAL; max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
else else
max77802->opmode[id] = val; max77802->opmode[id] = val;
...@@ -555,9 +578,10 @@ static int max77802_pmic_probe(struct platform_device *pdev) ...@@ -555,9 +578,10 @@ static int max77802_pmic_probe(struct platform_device *pdev)
rdev = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&pdev->dev, dev_err(&pdev->dev,
"regulator init failed for %d\n", i); "regulator init failed for %d: %d\n", i, ret);
return PTR_ERR(rdev); return ret;
} }
} }
......
...@@ -174,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) ...@@ -174,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed)) if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed))
dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n"); dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n");
pd->reg_data = of_get_regulator_init_data(dev, np); pd->reg_data = of_get_regulator_init_data(dev, np, &regulator);
if (!pd->reg_data) { if (!pd->reg_data) {
dev_err(dev, "Failed to parse regulator init data\n"); dev_err(dev, "Failed to parse regulator init data\n");
return NULL; return NULL;
......
...@@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client, ...@@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client,
config.dev = &client->dev; config.dev = &client->dev;
config.init_data = pdata ? pdata->reg_init_data : config.init_data = pdata ? pdata->reg_init_data :
of_get_regulator_init_data(&client->dev, client->dev.of_node); of_get_regulator_init_data(&client->dev, client->dev.of_node,
&max->desc);
config.driver_data = max; config.driver_data = max;
config.of_node = client->dev.of_node; config.of_node = client->dev.of_node;
config.regmap = max->regmap; config.regmap = max->regmap;
......
...@@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata->id = i; rdata->id = i;
rdata->initdata = of_get_regulator_init_data(&pdev->dev, rdata->initdata = of_get_regulator_init_data(&pdev->dev,
reg_np); reg_np,
&regulators[i]);
rdata->reg_node = reg_np; rdata->reg_node = reg_np;
rdata++; rdata++;
} }
......
...@@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, ...@@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
continue; continue;
rdata->id = regulators[i].id; rdata->id = regulators[i].id;
rdata->initdata = of_get_regulator_init_data( rdata->initdata = of_get_regulator_init_data(iodev->dev,
iodev->dev, reg_np); reg_np,
&regulators[i]);
rdata->reg_node = reg_np; rdata->reg_node = reg_np;
++rdata; ++rdata;
} }
......
...@@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( ...@@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
regulators[i].desc.name)) { regulators[i].desc.name)) {
p->id = i; p->id = i;
p->init_data = of_get_regulator_init_data( p->init_data = of_get_regulator_init_data(
&pdev->dev, child); &pdev->dev, child,
&regulators[i].desc);
p->node = child; p->node = child;
p++; p++;
......
...@@ -19,12 +19,20 @@ ...@@ -19,12 +19,20 @@
#include "internal.h" #include "internal.h"
static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
[PM_SUSPEND_MEM] = "regulator-state-mem",
[PM_SUSPEND_MAX] = "regulator-state-disk",
};
static void of_get_regulation_constraints(struct device_node *np, static void of_get_regulation_constraints(struct device_node *np,
struct regulator_init_data **init_data) struct regulator_init_data **init_data,
const struct regulator_desc *desc)
{ {
const __be32 *min_uV, *max_uV; const __be32 *min_uV, *max_uV;
struct regulation_constraints *constraints = &(*init_data)->constraints; struct regulation_constraints *constraints = &(*init_data)->constraints;
int ret; struct regulator_state *suspend_state;
struct device_node *suspend_np;
int ret, i;
u32 pval; u32 pval;
constraints->name = of_get_property(np, "regulator-name", NULL); constraints->name = of_get_property(np, "regulator-name", NULL);
...@@ -73,18 +81,84 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -73,18 +81,84 @@ static void of_get_regulation_constraints(struct device_node *np,
ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
if (!ret) if (!ret)
constraints->enable_time = pval; constraints->enable_time = pval;
if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
if (desc && desc->of_map_mode) {
ret = desc->of_map_mode(pval);
if (ret == -EINVAL)
pr_err("%s: invalid mode %u\n", np->name, pval);
else
constraints->initial_mode = ret;
} else {
pr_warn("%s: mapping for mode %d not defined\n",
np->name, pval);
}
}
for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
switch (i) {
case PM_SUSPEND_MEM:
suspend_state = &constraints->state_mem;
break;
case PM_SUSPEND_MAX:
suspend_state = &constraints->state_disk;
break;
case PM_SUSPEND_ON:
case PM_SUSPEND_FREEZE:
case PM_SUSPEND_STANDBY:
default:
continue;
};
suspend_np = of_get_child_by_name(np, regulator_states[i]);
if (!suspend_np || !suspend_state)
continue;
if (!of_property_read_u32(suspend_np, "regulator-mode",
&pval)) {
if (desc && desc->of_map_mode) {
ret = desc->of_map_mode(pval);
if (ret == -EINVAL)
pr_err("%s: invalid mode %u\n",
np->name, pval);
else
suspend_state->mode = ret;
} else {
pr_warn("%s: mapping for mode %d not defined\n",
np->name, pval);
}
}
if (of_property_read_bool(suspend_np,
"regulator-on-in-suspend"))
suspend_state->enabled = true;
else if (of_property_read_bool(suspend_np,
"regulator-off-in-suspend"))
suspend_state->disabled = true;
if (!of_property_read_u32(suspend_np,
"regulator-suspend-microvolt", &pval))
suspend_state->uV = pval;
of_node_put(suspend_np);
suspend_state = NULL;
suspend_np = NULL;
}
} }
/** /**
* of_get_regulator_init_data - extract regulator_init_data structure info * of_get_regulator_init_data - extract regulator_init_data structure info
* @dev: device requesting for regulator_init_data * @dev: device requesting for regulator_init_data
* @node: regulator device node
* @desc: regulator description
* *
* Populates regulator_init_data structure by extracting data from device * Populates regulator_init_data structure by extracting data from device
* tree node, returns a pointer to the populated struture or NULL if memory * tree node, returns a pointer to the populated struture or NULL if memory
* alloc fails. * alloc fails.
*/ */
struct regulator_init_data *of_get_regulator_init_data(struct device *dev, struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
struct device_node *node) struct device_node *node,
const struct regulator_desc *desc)
{ {
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
...@@ -95,7 +169,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, ...@@ -95,7 +169,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
if (!init_data) if (!init_data)
return NULL; /* Out of memory? */ return NULL; /* Out of memory? */
of_get_regulation_constraints(node, &init_data); of_get_regulation_constraints(node, &init_data, desc);
return init_data; return init_data;
} }
EXPORT_SYMBOL_GPL(of_get_regulator_init_data); EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
...@@ -176,7 +250,8 @@ int of_regulator_match(struct device *dev, struct device_node *node, ...@@ -176,7 +250,8 @@ int of_regulator_match(struct device *dev, struct device_node *node,
continue; continue;
match->init_data = match->init_data =
of_get_regulator_init_data(dev, child); of_get_regulator_init_data(dev, child,
match->desc);
if (!match->init_data) { if (!match->init_data) {
dev_err(dev, dev_err(dev,
"failed to parse DT for regulator %s\n", "failed to parse DT for regulator %s\n",
...@@ -224,7 +299,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, ...@@ -224,7 +299,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
if (strcmp(desc->of_match, name)) if (strcmp(desc->of_match, name))
continue; continue;
init_data = of_get_regulator_init_data(dev, child); init_data = of_get_regulator_init_data(dev, child, desc);
if (!init_data) { if (!init_data) {
dev_err(dev, dev_err(dev,
"failed to parse DT for regulator %s\n", "failed to parse DT for regulator %s\n",
......
...@@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev) ...@@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
return ret; return ret;
} }
config.init_data = of_get_regulator_init_data(&pdev->dev, np); config.init_data = of_get_regulator_init_data(&pdev->dev, np,
&drvdata->desc);
if (!config.init_data) if (!config.init_data)
return -ENOMEM; return -ENOMEM;
......
...@@ -643,10 +643,6 @@ static int rpm_reg_probe(struct platform_device *pdev) ...@@ -643,10 +643,6 @@ static int rpm_reg_probe(struct platform_device *pdev)
match = of_match_device(rpm_of_match, &pdev->dev); match = of_match_device(rpm_of_match, &pdev->dev);
template = match->data; template = match->data;
initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
if (!initdata)
return -EINVAL;
vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
if (!vreg) { if (!vreg) {
dev_err(&pdev->dev, "failed to allocate vreg\n"); dev_err(&pdev->dev, "failed to allocate vreg\n");
...@@ -666,6 +662,11 @@ static int rpm_reg_probe(struct platform_device *pdev) ...@@ -666,6 +662,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
&vreg->desc);
if (!initdata)
return -EINVAL;
key = "reg"; key = "reg";
ret = of_property_read_u32(pdev->dev.of_node, key, &val); ret = of_property_read_u32(pdev->dev.of_node, key, &val);
if (ret) { if (ret) {
......
...@@ -36,6 +36,12 @@ ...@@ -36,6 +36,12 @@
#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET)
#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET)
/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
#define RK808_SLP_REG_OFFSET 1
/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
#define RK808_SLP_SET_OFF_REG_OFFSET 2
static const int rk808_buck_config_regs[] = { static const int rk808_buck_config_regs[] = {
RK808_BUCK1_CONFIG_REG, RK808_BUCK1_CONFIG_REG,
RK808_BUCK2_CONFIG_REG, RK808_BUCK2_CONFIG_REG,
...@@ -91,6 +97,43 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) ...@@ -91,6 +97,43 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
RK808_RAMP_RATE_MASK, ramp_value); RK808_RAMP_RATE_MASK, ramp_value);
} }
int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
{
unsigned int reg;
int sel = regulator_map_voltage_linear_range(rdev, uv, uv);
if (sel < 0)
return -EINVAL;
reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
return regmap_update_bits(rdev->regmap, reg,
rdev->desc->vsel_mask,
sel);
}
int rk808_set_suspend_enable(struct regulator_dev *rdev)
{
unsigned int reg;
reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
return regmap_update_bits(rdev->regmap, reg,
rdev->desc->enable_mask,
0);
}
int rk808_set_suspend_disable(struct regulator_dev *rdev)
{
unsigned int reg;
reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
return regmap_update_bits(rdev->regmap, reg,
rdev->desc->enable_mask,
rdev->desc->enable_mask);
}
static struct regulator_ops rk808_buck1_2_ops = { static struct regulator_ops rk808_buck1_2_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,
...@@ -100,6 +143,9 @@ static struct regulator_ops rk808_buck1_2_ops = { ...@@ -100,6 +143,9 @@ static struct regulator_ops rk808_buck1_2_ops = {
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.set_ramp_delay = rk808_set_ramp_delay, .set_ramp_delay = rk808_set_ramp_delay,
.set_suspend_voltage = rk808_set_suspend_voltage,
.set_suspend_enable = rk808_set_suspend_enable,
.set_suspend_disable = rk808_set_suspend_disable,
}; };
static struct regulator_ops rk808_reg_ops = { static struct regulator_ops rk808_reg_ops = {
...@@ -110,12 +156,17 @@ static struct regulator_ops rk808_reg_ops = { ...@@ -110,12 +156,17 @@ static struct regulator_ops rk808_reg_ops = {
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.set_suspend_voltage = rk808_set_suspend_voltage,
.set_suspend_enable = rk808_set_suspend_enable,
.set_suspend_disable = rk808_set_suspend_disable,
}; };
static struct regulator_ops rk808_switch_ops = { static struct regulator_ops rk808_switch_ops = {
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.set_suspend_enable = rk808_set_suspend_enable,
.set_suspend_disable = rk808_set_suspend_disable,
}; };
static const struct regulator_desc rk808_reg[] = { static const struct regulator_desc rk808_reg[] = {
......
...@@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata->id = i; rdata->id = i;
rdata->initdata = of_get_regulator_init_data( rdata->initdata = of_get_regulator_init_data(
&pdev->dev, reg_np); &pdev->dev, reg_np,
&regulators[i]);
rdata->reg_node = reg_np; rdata->reg_node = reg_np;
rdata++; rdata++;
rmode->id = i; rmode->id = i;
......
...@@ -76,7 +76,7 @@ static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) ...@@ -76,7 +76,7 @@ static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
return NULL; return NULL;
} }
init_data = of_get_regulator_init_data(dev, np); init_data = of_get_regulator_init_data(dev, np, &sky81452_reg);
of_node_put(np); of_node_put(np);
return init_data; return init_data;
......
...@@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev) ...@@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
config.regmap = stw481x->map; config.regmap = stw481x->map;
config.of_node = pdev->dev.of_node; config.of_node = pdev->dev.of_node;
config.init_data = of_get_regulator_init_data(&pdev->dev, config.init_data = of_get_regulator_init_data(&pdev->dev,
pdev->dev.of_node); pdev->dev.of_node,
&vmmc_regulator);
stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev, stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
&vmmc_regulator, &config); &vmmc_regulator, &config);
......
...@@ -837,7 +837,8 @@ static int ti_abb_probe(struct platform_device *pdev) ...@@ -837,7 +837,8 @@ static int ti_abb_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
initdata = of_get_regulator_init_data(dev, pdev->dev.of_node); initdata = of_get_regulator_init_data(dev, pdev->dev.of_node,
&abb->rdesc);
if (!initdata) { if (!initdata) {
dev_err(dev, "%s: Unable to alloc regulator init data\n", dev_err(dev, "%s: Unable to alloc regulator init data\n",
__func__); __func__);
......
...@@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = { ...@@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = {
MODULE_DEVICE_TABLE(of, tps51632_of_match); MODULE_DEVICE_TABLE(of, tps51632_of_match);
static struct tps51632_regulator_platform_data * static struct tps51632_regulator_platform_data *
of_get_tps51632_platform_data(struct device *dev) of_get_tps51632_platform_data(struct device *dev,
const struct regulator_desc *desc)
{ {
struct tps51632_regulator_platform_data *pdata; struct tps51632_regulator_platform_data *pdata;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
...@@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data * ...@@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data *
if (!pdata) if (!pdata)
return NULL; return NULL;
pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
desc);
if (!pdata->reg_init_data) { if (!pdata->reg_init_data) {
dev_err(dev, "Not able to get OF regulator init data\n"); dev_err(dev, "Not able to get OF regulator init data\n");
return NULL; return NULL;
...@@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data * ...@@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data *
} }
#else #else
static struct tps51632_regulator_platform_data * static struct tps51632_regulator_platform_data *
of_get_tps51632_platform_data(struct device *dev) of_get_tps51632_platform_data(struct device *dev,
const struct regulator_desc *desc)
{ {
return NULL; return NULL;
} }
...@@ -273,9 +276,25 @@ static int tps51632_probe(struct i2c_client *client, ...@@ -273,9 +276,25 @@ static int tps51632_probe(struct i2c_client *client,
} }
} }
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
tps->dev = &client->dev;
tps->desc.name = client->name;
tps->desc.id = 0;
tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
tps->desc.ops = &tps51632_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
if (!pdata && client->dev.of_node) if (!pdata && client->dev.of_node)
pdata = of_get_tps51632_platform_data(&client->dev); pdata = of_get_tps51632_platform_data(&client->dev, &tps->desc);
if (!pdata) { if (!pdata) {
dev_err(&client->dev, "No Platform data\n"); dev_err(&client->dev, "No Platform data\n");
return -EINVAL; return -EINVAL;
...@@ -296,22 +315,6 @@ static int tps51632_probe(struct i2c_client *client, ...@@ -296,22 +315,6 @@ static int tps51632_probe(struct i2c_client *client,
} }
} }
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
tps->dev = &client->dev;
tps->desc.name = client->name;
tps->desc.id = 0;
tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
tps->desc.ops = &tps51632_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
if (pdata->enable_pwm_dvfs) if (pdata->enable_pwm_dvfs)
tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG; tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG;
else else
......
...@@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = { ...@@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = {
}; };
static struct tps62360_regulator_platform_data * static struct tps62360_regulator_platform_data *
of_get_tps62360_platform_data(struct device *dev) of_get_tps62360_platform_data(struct device *dev,
const struct regulator_desc *desc)
{ {
struct tps62360_regulator_platform_data *pdata; struct tps62360_regulator_platform_data *pdata;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
...@@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data * ...@@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data *
if (!pdata) if (!pdata)
return NULL; return NULL;
pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
desc);
if (!pdata->reg_init_data) { if (!pdata->reg_init_data) {
dev_err(dev, "Not able to get OF regulator init data\n"); dev_err(dev, "Not able to get OF regulator init data\n");
return NULL; return NULL;
...@@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client, ...@@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client,
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
tps->desc.name = client->name;
tps->desc.id = 0;
tps->desc.ops = &tps62360_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
tps->desc.uV_step = 10000;
if (client->dev.of_node) { if (client->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_device(of_match_ptr(tps62360_of_match), match = of_match_device(of_match_ptr(tps62360_of_match),
...@@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client, ...@@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client,
} }
chip_id = (int)(long)match->data; chip_id = (int)(long)match->data;
if (!pdata) if (!pdata)
pdata = of_get_tps62360_platform_data(&client->dev); pdata = of_get_tps62360_platform_data(&client->dev,
&tps->desc);
} else if (id) { } else if (id) {
chip_id = id->driver_data; chip_id = id->driver_data;
} else { } else {
...@@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client, ...@@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
tps->en_discharge = pdata->en_discharge; tps->en_discharge = pdata->en_discharge;
tps->en_internal_pulldn = pdata->en_internal_pulldn; tps->en_internal_pulldn = pdata->en_internal_pulldn;
tps->vsel0_gpio = pdata->vsel0_gpio; tps->vsel0_gpio = pdata->vsel0_gpio;
...@@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client, ...@@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
tps->desc.name = client->name;
tps->desc.id = 0;
tps->desc.ops = &tps62360_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
tps->desc.uV_step = 10000;
tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config); tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
if (IS_ERR(tps->regmap)) { if (IS_ERR(tps->regmap)) {
ret = PTR_ERR(tps->regmap); ret = PTR_ERR(tps->regmap);
......
...@@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev) ...@@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
template = match->data; template = match->data;
id = template->id; id = template->id;
init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
&regulators[id]);
platform_set_drvdata(pdev, tps); platform_set_drvdata(pdev, tps);
......
...@@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev) ...@@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev)
template = match->data; template = match->data;
id = template->desc.id; id = template->desc.id;
initdata = of_get_regulator_init_data(&pdev->dev, initdata = of_get_regulator_init_data(&pdev->dev,
pdev->dev.of_node); pdev->dev.of_node,
&template->desc);
drvdata = NULL; drvdata = NULL;
} else { } else {
id = pdev->id; id = pdev->id;
......
...@@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev) ...@@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
reg->desc.owner = THIS_MODULE; reg->desc.owner = THIS_MODULE;
reg->desc.continuous_voltage_range = true; reg->desc.continuous_voltage_range = true;
init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
&reg->desc);
if (!init_data) if (!init_data)
return -EINVAL; return -EINVAL;
......
/*
* Copyright (C) 2014 Google, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Device Tree binding constants for the Maxim 77802 PMIC regulators
*/
#ifndef _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H
#define _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H
/* Regulator operating modes */
#define MAX77802_OPMODE_LP 1
#define MAX77802_OPMODE_NORMAL 3
#endif /* _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H */
...@@ -131,13 +131,6 @@ enum max77686_opmode { ...@@ -131,13 +131,6 @@ enum max77686_opmode {
MAX77686_OPMODE_STANDBY, MAX77686_OPMODE_STANDBY,
}; };
enum max77802_opmode {
MAX77802_OPMODE_OFF,
MAX77802_OPMODE_STANDBY,
MAX77802_OPMODE_LP,
MAX77802_OPMODE_NORMAL,
};
struct max77686_opmode_data { struct max77686_opmode_data {
int id; int id;
int mode; int mode;
......
...@@ -922,4 +922,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs, ...@@ -922,4 +922,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
/* CONFIG_OF_RESOLVE api */ /* CONFIG_OF_RESOLVE api */
extern int of_resolve_phandles(struct device_node *tree); extern int of_resolve_phandles(struct device_node *tree);
/**
* of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
* @np: Pointer to the given device_node
*
* return true if present false otherwise
*/
static inline bool of_device_is_system_power_controller(const struct device_node *np)
{
return of_property_read_bool(np, "system-power-controller");
}
#endif /* _LINUX_OF_H */ #endif /* _LINUX_OF_H */
...@@ -243,6 +243,8 @@ enum regulator_type { ...@@ -243,6 +243,8 @@ enum regulator_type {
* *
* @enable_time: Time taken for initial enable of regulator (in uS). * @enable_time: Time taken for initial enable of regulator (in uS).
* @off_on_delay: guard time (in uS), before re-enabling a regulator * @off_on_delay: guard time (in uS), before re-enabling a regulator
*
* @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode
*/ */
struct regulator_desc { struct regulator_desc {
const char *name; const char *name;
...@@ -285,6 +287,8 @@ struct regulator_desc { ...@@ -285,6 +287,8 @@ struct regulator_desc {
unsigned int enable_time; unsigned int enable_time;
unsigned int off_on_delay; unsigned int off_on_delay;
unsigned int (*of_map_mode)(unsigned int mode);
}; };
/** /**
......
...@@ -6,24 +6,29 @@ ...@@ -6,24 +6,29 @@
#ifndef __LINUX_OF_REG_H #ifndef __LINUX_OF_REG_H
#define __LINUX_OF_REG_H #define __LINUX_OF_REG_H
struct regulator_desc;
struct of_regulator_match { struct of_regulator_match {
const char *name; const char *name;
void *driver_data; void *driver_data;
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
struct device_node *of_node; struct device_node *of_node;
const struct regulator_desc *desc;
}; };
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
extern struct regulator_init_data extern struct regulator_init_data
*of_get_regulator_init_data(struct device *dev, *of_get_regulator_init_data(struct device *dev,
struct device_node *node); struct device_node *node,
const struct regulator_desc *desc);
extern int of_regulator_match(struct device *dev, struct device_node *node, extern int of_regulator_match(struct device *dev, struct device_node *node,
struct of_regulator_match *matches, struct of_regulator_match *matches,
unsigned int num_matches); unsigned int num_matches);
#else #else
static inline struct regulator_init_data static inline struct regulator_init_data
*of_get_regulator_init_data(struct device *dev, *of_get_regulator_init_data(struct device *dev,
struct device_node *node) struct device_node *node,
const struct regulator_desc *desc)
{ {
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment