mirror of https://gitee.com/openkylin/linux.git
Merge remote-tracking branches 'regulator/topic/max77686', 'regulator/topic/max77693', 'regulator/topic/max77802', 'regulator/topic/power-off' and 'regulator/topic/rk808' into regulator-next
This commit is contained in:
commit
92d07a8ff6
|
@ -0,0 +1,18 @@
|
|||
* 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:
|
|||
- compatible: "active-semi,act8846" or "active-semi,act8865"
|
||||
- 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.
|
||||
|
||||
The valid names for regulators are:
|
||||
|
|
|
@ -25,6 +25,29 @@ with their hardware counterparts as follow. The valid names are:
|
|||
example: LDO1, LDO2, LDO35.
|
||||
-BUCKn : for BUCKs, where n can lie in range 1 to 10.
|
||||
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:
|
||||
|
||||
max77802@09 {
|
||||
|
@ -36,11 +59,23 @@ Example:
|
|||
#size-cells = <0>;
|
||||
|
||||
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 {
|
||||
regulator-name = "vdd_ldo11";
|
||||
regulator-min-microvolt = <1900000>;
|
||||
regulator-max-microvolt = <1900000>;
|
||||
regulator-always-on;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <MAX77802_OPMODE_LP>;
|
||||
};
|
||||
};
|
||||
|
||||
buck1_reg: BUCK1 {
|
||||
|
|
|
@ -19,6 +19,24 @@ Optional properties:
|
|||
design requires. This property describes the total system ramp time
|
||||
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.
|
||||
- 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:
|
||||
- regulator-compatible: If a regulator chip contains multiple
|
||||
|
@ -34,6 +52,10 @@ Example:
|
|||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
vin-supply = <&vin>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
Regulator Consumers:
|
||||
|
|
|
@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
|
|||
for_each_child_of_node(nproot, np) {
|
||||
if (!of_node_cmp(np->name, info->desc.name)) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@
|
|||
#define ACT8846_REG12_VSET 0xa0
|
||||
#define ACT8846_REG12_CTRL 0xa1
|
||||
#define ACT8846_REG13_CTRL 0xb1
|
||||
#define ACT8846_GLB_OFF_CTRL 0xc3
|
||||
#define ACT8846_OFF_SYSMASK 0x18
|
||||
|
||||
/*
|
||||
* ACT8865 Global Register Map.
|
||||
|
@ -84,6 +86,7 @@
|
|||
#define ACT8865_LDO3_CTRL 0x61
|
||||
#define ACT8865_LDO4_VSET 0x64
|
||||
#define ACT8865_LDO4_CTRL 0x65
|
||||
#define ACT8865_MSTROFF 0x20
|
||||
|
||||
/*
|
||||
* Field Definitions.
|
||||
|
@ -98,6 +101,8 @@
|
|||
|
||||
struct act8865 {
|
||||
struct regmap *regmap;
|
||||
int off_reg;
|
||||
int off_mask;
|
||||
};
|
||||
|
||||
static const struct regmap_config act8865_regmap_config = {
|
||||
|
@ -275,6 +280,16 @@ static struct regulator_init_data
|
|||
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,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
|
@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
|
|||
int i, ret, num_regulators;
|
||||
struct act8865 *act8865;
|
||||
unsigned long type;
|
||||
int off_reg, off_mask;
|
||||
|
||||
pdata = dev_get_platdata(dev);
|
||||
|
||||
|
@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client,
|
|||
case ACT8846:
|
||||
regulators = act8846_regulators;
|
||||
num_regulators = ARRAY_SIZE(act8846_regulators);
|
||||
off_reg = ACT8846_GLB_OFF_CTRL;
|
||||
off_mask = ACT8846_OFF_SYSMASK;
|
||||
break;
|
||||
case ACT8865:
|
||||
regulators = act8865_regulators;
|
||||
num_regulators = ARRAY_SIZE(act8865_regulators);
|
||||
off_reg = ACT8865_SYS_CTRL;
|
||||
off_mask = ACT8865_MSTROFF;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid device id %lu\n", type);
|
||||
|
@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client,
|
|||
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 */
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
const struct regulator_desc *desc = ®ulators[i];
|
||||
|
|
|
@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev)
|
|||
int ret = 0;
|
||||
u32 val;
|
||||
|
||||
initdata = of_get_regulator_init_data(dev, np);
|
||||
sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
|
||||
if (!sreg)
|
||||
return -ENOMEM;
|
||||
sreg->initdata = initdata;
|
||||
sreg->name = of_get_property(np, "regulator-name", NULL);
|
||||
rdesc = &sreg->rdesc;
|
||||
rdesc->name = sreg->name;
|
||||
rdesc->type = REGULATOR_VOLTAGE;
|
||||
rdesc->owner = THIS_MODULE;
|
||||
|
||||
initdata = of_get_regulator_init_data(dev, np, rdesc);
|
||||
sreg->initdata = initdata;
|
||||
|
||||
anatop_np = of_get_parent(np);
|
||||
if (!anatop_np)
|
||||
return -ENODEV;
|
||||
|
|
|
@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = {
|
|||
};
|
||||
|
||||
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_ldo1 *ldo1 = config->driver_data;
|
||||
|
@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
|
|||
if (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) {
|
||||
init_data->consumer_supplies = &ldo1->supply;
|
||||
|
@ -257,7 +259,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
|
|||
|
||||
if (IS_ENABLED(CONFIG_OF)) {
|
||||
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)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
|
|||
};
|
||||
|
||||
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_micsupp *micsupp = config->driver_data;
|
||||
|
@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
|
|||
if (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) {
|
||||
init_data->consumer_supplies = &micsupp->supply;
|
||||
|
@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
|
|||
|
||||
if (IS_ENABLED(CONFIG_OF)) {
|
||||
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)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
|
|||
if (!of_node_cmp(np->name,
|
||||
regulator->info->reg_desc.name)) {
|
||||
config.init_data = of_get_regulator_init_data(
|
||||
&pdev->dev, np);
|
||||
&pdev->dev, np,
|
||||
®ulator->info->reg_desc);
|
||||
config.of_node = np;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
config.dev = &i2c->dev;
|
||||
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.regmap = chip->regmap;
|
||||
config.of_node = dev->of_node;
|
||||
|
|
|
@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = {
|
|||
};
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
|
|||
if (!pdata)
|
||||
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",
|
||||
&tmp);
|
||||
|
@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client,
|
|||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
|
||||
GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (!pdata)
|
||||
pdata = fan53555_parse_dt(&client->dev, np);
|
||||
pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
|
||||
|
||||
if (!pdata || !pdata->regulator) {
|
||||
dev_err(&client->dev, "Platform data not found!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
|
||||
GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
di->regulator = pdata->regulator;
|
||||
if (client->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
|
|
|
@ -40,13 +40,15 @@ struct fixed_voltage_data {
|
|||
/**
|
||||
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info
|
||||
* @dev: device requesting for fixed_voltage_config
|
||||
* @desc: regulator description
|
||||
*
|
||||
* Populates fixed_voltage_config structure by extracting data from device
|
||||
* tree node, returns a pointer to the populated structure of NULL if memory
|
||||
* alloc fails.
|
||||
*/
|
||||
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 device_node *np = dev->of_node;
|
||||
|
@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev)
|
|||
if (!config)
|
||||
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)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
|
|||
struct regulator_config cfg = { };
|
||||
int ret;
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
|
||||
GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
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))
|
||||
return PTR_ERR(config);
|
||||
} else {
|
||||
|
@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
|
|||
if (!config)
|
||||
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,
|
||||
config->supply_name,
|
||||
GFP_KERNEL);
|
||||
|
|
|
@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
|
|||
};
|
||||
|
||||
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;
|
||||
const char *regtype;
|
||||
|
@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
|
|||
if (!config)
|
||||
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)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
@ -250,17 +251,18 @@ static int gpio_regulator_probe(struct platform_device *pdev)
|
|||
struct regulator_config cfg = { };
|
||||
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),
|
||||
GFP_KERNEL);
|
||||
if (drvdata == NULL)
|
||||
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);
|
||||
if (drvdata->desc.name == NULL) {
|
||||
dev_err(&pdev->dev, "Failed to allocate supply name\n");
|
||||
|
|
|
@ -45,6 +45,23 @@
|
|||
#define MAX77686_DVS_MINUV 600000
|
||||
#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_BUCK234_SHIFT 4
|
||||
#define MAX77686_OPMODE_MASK 0x3
|
||||
|
@ -65,23 +82,36 @@ enum max77686_ramp_rate {
|
|||
};
|
||||
|
||||
struct max77686_data {
|
||||
/* Array indexed by regulator id */
|
||||
unsigned int opmode[MAX77686_REGULATORS];
|
||||
};
|
||||
|
||||
/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
|
||||
static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
|
||||
static unsigned int max77686_get_opmode_shift(int id)
|
||||
{
|
||||
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);
|
||||
int ret, id = rdev_get_id(rdev);
|
||||
|
||||
if (id == MAX77686_BUCK1)
|
||||
val = 0x1;
|
||||
else
|
||||
val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
|
||||
shift = max77686_get_opmode_shift(id);
|
||||
val = MAX77686_OFF_PWRREQ;
|
||||
|
||||
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask, val);
|
||||
rdev->desc->enable_mask, val << shift);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
|
|||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = 0x2 << MAX77686_OPMODE_SHIFT;
|
||||
val = MAX77686_LDO_LOWPOWER_PWRREQ;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = 0x3 << MAX77686_OPMODE_SHIFT;
|
||||
val = MAX77686_NORMAL;
|
||||
break;
|
||||
default:
|
||||
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,
|
|||
}
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
|
@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
|
|||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_STANDBY: /* switch off */
|
||||
val = 0x1 << MAX77686_OPMODE_SHIFT;
|
||||
val = MAX77686_OFF_PWRREQ;
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = 0x2 << MAX77686_OPMODE_SHIFT;
|
||||
val = MAX77686_LDO_LOWPOWER_PWRREQ;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = 0x3 << MAX77686_OPMODE_SHIFT;
|
||||
val = MAX77686_NORMAL;
|
||||
break;
|
||||
default:
|
||||
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,
|
|||
}
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
|
@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
|
|||
static int max77686_enable(struct regulator_dev *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,
|
||||
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)
|
||||
|
@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = {
|
|||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_mode = max77686_ldo_set_suspend_mode,
|
||||
.set_suspend_disable = max77686_set_suspend_disable,
|
||||
};
|
||||
|
||||
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,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.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 = {
|
||||
|
@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.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) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_lpm_ldo(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_ldo_low(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_ldo1_low(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_buck(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_buck1(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_buck1_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
}
|
||||
#define regulator_desc_buck_dvs(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("voltage-regulators"), \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_buck_dvs_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
|||
<< MAX77686_OPMODE_BUCK234_SHIFT, \
|
||||
}
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
static const struct regulator_desc regulators[] = {
|
||||
regulator_desc_ldo1_low(1),
|
||||
regulator_desc_ldo_low(2),
|
||||
regulator_desc_ldo(3),
|
||||
|
@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = {
|
|||
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)
|
||||
{
|
||||
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
struct max77686_data *max77686;
|
||||
int i, ret = 0;
|
||||
int i;
|
||||
struct regulator_config config = { };
|
||||
|
||||
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),
|
||||
GFP_KERNEL);
|
||||
if (!max77686)
|
||||
return -ENOMEM;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.dev = iodev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
config.driver_data = max77686;
|
||||
platform_set_drvdata(pdev, max77686);
|
||||
|
||||
for (i = 0; i < MAX77686_REGULATORS; i++) {
|
||||
struct regulator_dev *rdev;
|
||||
int id = regulators[i].id;
|
||||
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.of_node = pdata->regulators[i].of_node;
|
||||
|
||||
max77686->opmode[i] = regulators[i].enable_mask;
|
||||
max77686->opmode[id] = MAX77686_NORMAL;
|
||||
rdev = devm_regulator_register(&pdev->dev,
|
||||
®ulators[i], &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
int ret = PTR_ERR(rdev);
|
||||
dev_err(&pdev->dev,
|
||||
"regulator init failed for %d\n", i);
|
||||
return PTR_ERR(rdev);
|
||||
"regulator init failed for %d: %d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ static struct regulator_ops max77693_charger_ops = {
|
|||
.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(2),
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/mfd/max77686.h>
|
||||
#include <linux/mfd/max77686-private.h>
|
||||
#include <dt-bindings/regulator/maxim,max77802.h>
|
||||
|
||||
/* Default ramp delay in case it is not manually set */
|
||||
#define MAX77802_RAMP_DELAY 100000 /* uV/us */
|
||||
|
@ -49,6 +50,10 @@
|
|||
#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0
|
||||
#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 */
|
||||
static const unsigned int ramp_table_77802_2bit[] = {
|
||||
12500,
|
||||
|
@ -65,9 +70,16 @@ static unsigned int ramp_table_77802_4bit[] = {
|
|||
};
|
||||
|
||||
struct max77802_regulator_prv {
|
||||
/* Array indexed by regulator id */
|
||||
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)
|
||||
{
|
||||
if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
|
||||
|
@ -83,17 +95,16 @@ static int max77802_get_opmode_shift(int id)
|
|||
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)
|
||||
*
|
||||
* The other mode (0x02) will make PWRREQ switch between normal
|
||||
* and low power.
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
int id = rdev_get_id(rdev);
|
||||
int shift = max77802_get_opmode_shift(id);
|
||||
|
@ -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
|
||||
* (Enable Control Logic1 by PWRREQ)
|
||||
*
|
||||
* LDOs 2, 4-19, 22-35.
|
||||
* Some LDOs support Low Power Mode while the system is running.
|
||||
*
|
||||
* LDOs 1, 3, 20, 21.
|
||||
*/
|
||||
static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||
int id = rdev_get_id(rdev);
|
||||
|
@ -119,14 +127,11 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
|
|||
int shift = max77802_get_opmode_shift(id);
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = MAX77802_OPMODE_LP;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = MAX77802_OPMODE_LP; /* ON in Low Power Mode */
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = MAX77802_OPMODE_NORMAL;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY: /* ON/OFF by PWRREQ */
|
||||
val = MAX77802_OPMODE_STANDBY;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = MAX77802_OPMODE_NORMAL; /* ON in Normal Mode */
|
||||
break;
|
||||
default:
|
||||
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,
|
|||
rdev->desc->enable_mask, val << shift);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs
|
||||
* (Enable Control Logic2 by PWRREQ)
|
||||
static unsigned max77802_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
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,
|
||||
unsigned int mode)
|
||||
static int max77802_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||
int id = rdev_get_id(rdev);
|
||||
unsigned int val;
|
||||
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) {
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = MAX77802_OPMODE_LP;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = MAX77802_OPMODE_NORMAL;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
/*
|
||||
* If the regulator opmode is normal then enable
|
||||
* ON in Low Power Mode by PWRREQ. If the mode is
|
||||
* already Low Power then no action is required.
|
||||
*/
|
||||
if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
|
||||
val = MAX77802_LP_PWRREQ;
|
||||
else
|
||||
return 0;
|
||||
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:
|
||||
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
|
||||
rdev->desc->name, mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max77802->opmode[id] = val;
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask, val << shift);
|
||||
}
|
||||
|
@ -178,6 +224,9 @@ static int max77802_enable(struct regulator_dev *rdev)
|
|||
int id = rdev_get_id(rdev);
|
||||
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,
|
||||
rdev->desc->enable_mask,
|
||||
max77802->opmode[id] << shift);
|
||||
|
@ -247,7 +296,8 @@ static struct regulator_ops max77802_ldo_ops_logic1 = {
|
|||
.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_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 = {
|
|||
.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_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 */
|
||||
|
@ -276,10 +328,25 @@ static struct regulator_ops max77802_buck_16_dvs_ops = {
|
|||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.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 = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
|
@ -290,12 +357,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.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_buck_set_suspend_disable,
|
||||
.set_suspend_disable = max77802_set_suspend_disable,
|
||||
};
|
||||
|
||||
/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
|
||||
#define regulator_77802_desc_p_ldo(num, supply, log) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_LDO##num, \
|
||||
.supply_name = "inl"#supply, \
|
||||
.ops = &max77802_ldo_ops_logic##log, \
|
||||
|
@ -309,11 +378,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.vsel_mask = MAX77802_VSEL_MASK, \
|
||||
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
|
||||
.of_map_mode = max77802_map_mode, \
|
||||
}
|
||||
|
||||
/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
|
||||
#define regulator_77802_desc_n_ldo(num, supply, log) { \
|
||||
.name = "LDO"#num, \
|
||||
.of_match = of_match_ptr("LDO"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_LDO##num, \
|
||||
.supply_name = "inl"#supply, \
|
||||
.ops = &max77802_ldo_ops_logic##log, \
|
||||
|
@ -327,11 +399,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.vsel_mask = MAX77802_VSEL_MASK, \
|
||||
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
|
||||
.of_map_mode = max77802_map_mode, \
|
||||
}
|
||||
|
||||
/* BUCKs 1, 6 */
|
||||
#define regulator_77802_desc_16_buck(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_BUCK##num, \
|
||||
.supply_name = "inb"#num, \
|
||||
.ops = &max77802_buck_16_dvs_ops, \
|
||||
|
@ -345,14 +420,17 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.vsel_mask = MAX77802_DVS_VSEL_MASK, \
|
||||
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \
|
||||
.enable_mask = MAX77802_OPMODE_MASK, \
|
||||
.of_map_mode = max77802_map_mode, \
|
||||
}
|
||||
|
||||
/* BUCKS 2-4 */
|
||||
#define regulator_77802_desc_234_buck(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_BUCK##num, \
|
||||
.supply_name = "inb"#num, \
|
||||
.ops = &max77802_buck_dvs_ops, \
|
||||
.ops = &max77802_buck_234_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = 600000, \
|
||||
|
@ -364,11 +442,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \
|
||||
.enable_mask = MAX77802_OPMODE_MASK << \
|
||||
MAX77802_OPMODE_BUCK234_SHIFT, \
|
||||
.of_map_mode = max77802_map_mode, \
|
||||
}
|
||||
|
||||
/* BUCK 5 */
|
||||
#define regulator_77802_desc_buck5(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_BUCK##num, \
|
||||
.supply_name = "inb"#num, \
|
||||
.ops = &max77802_buck_dvs_ops, \
|
||||
|
@ -382,11 +463,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.vsel_mask = MAX77802_VSEL_MASK, \
|
||||
.enable_reg = MAX77802_REG_BUCK5CTRL, \
|
||||
.enable_mask = MAX77802_OPMODE_MASK, \
|
||||
.of_map_mode = max77802_map_mode, \
|
||||
}
|
||||
|
||||
/* BUCKs 7-10 */
|
||||
#define regulator_77802_desc_buck7_10(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.of_match = of_match_ptr("BUCK"#num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77802_BUCK##num, \
|
||||
.supply_name = "inb"#num, \
|
||||
.ops = &max77802_buck_dvs_ops, \
|
||||
|
@ -400,9 +484,10 @@ static struct regulator_ops max77802_buck_dvs_ops = {
|
|||
.vsel_mask = MAX77802_VSEL_MASK, \
|
||||
.enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \
|
||||
.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_234_buck(2),
|
||||
regulator_77802_desc_234_buck(3),
|
||||
|
@ -447,85 +532,19 @@ static struct regulator_desc regulators[] = {
|
|||
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)
|
||||
{
|
||||
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;
|
||||
int i, ret = 0, val;
|
||||
int i, val;
|
||||
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,
|
||||
sizeof(struct max77802_regulator_prv),
|
||||
GFP_KERNEL);
|
||||
if (!max77802)
|
||||
return -ENOMEM;
|
||||
|
||||
if (iodev->dev->of_node) {
|
||||
ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.dev = iodev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
config.driver_data = max77802;
|
||||
|
@ -533,21 +552,25 @@ static int max77802_pmic_probe(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < MAX77802_REG_MAX; i++) {
|
||||
struct regulator_dev *rdev;
|
||||
int id = pdata->regulators[i].id;
|
||||
int id = regulators[i].id;
|
||||
int shift = max77802_get_opmode_shift(id);
|
||||
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.of_node = pdata->regulators[i].of_node;
|
||||
int ret;
|
||||
|
||||
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,
|
||||
* the hardware reports OFF as the regulator operating mode.
|
||||
* Default to operating mode NORMAL in that case.
|
||||
*/
|
||||
if (val == MAX77802_OPMODE_OFF)
|
||||
if (val == MAX77802_STATUS_OFF)
|
||||
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
|
||||
else
|
||||
max77802->opmode[id] = val;
|
||||
|
@ -555,9 +578,10 @@ static int max77802_pmic_probe(struct platform_device *pdev)
|
|||
rdev = devm_regulator_register(&pdev->dev,
|
||||
®ulators[i], &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(&pdev->dev,
|
||||
"regulator init failed for %d\n", i);
|
||||
return PTR_ERR(rdev);
|
||||
"regulator init failed for %d: %d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
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, ®ulator);
|
||||
if (!pd->reg_data) {
|
||||
dev_err(dev, "Failed to parse regulator init data\n");
|
||||
return NULL;
|
||||
|
|
|
@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client,
|
|||
|
||||
config.dev = &client->dev;
|
||||
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.of_node = client->dev.of_node;
|
||||
config.regmap = max->regmap;
|
||||
|
|
|
@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
|
|||
|
||||
rdata->id = i;
|
||||
rdata->initdata = of_get_regulator_init_data(&pdev->dev,
|
||||
reg_np);
|
||||
reg_np,
|
||||
®ulators[i]);
|
||||
rdata->reg_node = reg_np;
|
||||
rdata++;
|
||||
}
|
||||
|
|
|
@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
|
|||
continue;
|
||||
|
||||
rdata->id = regulators[i].id;
|
||||
rdata->initdata = of_get_regulator_init_data(
|
||||
iodev->dev, reg_np);
|
||||
rdata->initdata = of_get_regulator_init_data(iodev->dev,
|
||||
reg_np,
|
||||
®ulators[i]);
|
||||
rdata->reg_node = reg_np;
|
||||
++rdata;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
|
|||
regulators[i].desc.name)) {
|
||||
p->id = i;
|
||||
p->init_data = of_get_regulator_init_data(
|
||||
&pdev->dev, child);
|
||||
&pdev->dev, child,
|
||||
®ulators[i].desc);
|
||||
p->node = child;
|
||||
p++;
|
||||
|
||||
|
|
|
@ -19,12 +19,20 @@
|
|||
|
||||
#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,
|
||||
struct regulator_init_data **init_data)
|
||||
struct regulator_init_data **init_data,
|
||||
const struct regulator_desc *desc)
|
||||
{
|
||||
const __be32 *min_uV, *max_uV;
|
||||
struct regulation_constraints *constraints = &(*init_data)->constraints;
|
||||
int ret;
|
||||
struct regulator_state *suspend_state;
|
||||
struct device_node *suspend_np;
|
||||
int ret, i;
|
||||
u32 pval;
|
||||
|
||||
constraints->name = of_get_property(np, "regulator-name", NULL);
|
||||
|
@ -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);
|
||||
if (!ret)
|
||||
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
|
||||
* @dev: device requesting for regulator_init_data
|
||||
* @node: regulator device node
|
||||
* @desc: regulator description
|
||||
*
|
||||
* Populates regulator_init_data structure by extracting data from device
|
||||
* tree node, returns a pointer to the populated struture or NULL if memory
|
||||
* alloc fails.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -95,7 +169,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
|
|||
if (!init_data)
|
||||
return NULL; /* Out of memory? */
|
||||
|
||||
of_get_regulation_constraints(node, &init_data);
|
||||
of_get_regulation_constraints(node, &init_data, desc);
|
||||
return 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,
|
|||
continue;
|
||||
|
||||
match->init_data =
|
||||
of_get_regulator_init_data(dev, child);
|
||||
of_get_regulator_init_data(dev, child,
|
||||
match->desc);
|
||||
if (!match->init_data) {
|
||||
dev_err(dev,
|
||||
"failed to parse DT for regulator %s\n",
|
||||
|
@ -224,7 +299,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
|||
if (strcmp(desc->of_match, name))
|
||||
continue;
|
||||
|
||||
init_data = of_get_regulator_init_data(dev, child);
|
||||
init_data = of_get_regulator_init_data(dev, child, desc);
|
||||
if (!init_data) {
|
||||
dev_err(dev,
|
||||
"failed to parse DT for regulator %s\n",
|
||||
|
|
|
@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
|
|||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -643,10 +643,6 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
|||
match = of_match_device(rpm_of_match, &pdev->dev);
|
||||
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);
|
||||
if (!vreg) {
|
||||
dev_err(&pdev->dev, "failed to allocate vreg\n");
|
||||
|
@ -666,6 +662,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
|||
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) {
|
||||
|
|
|
@ -36,6 +36,12 @@
|
|||
#define RK808_RAMP_RATE_6MV_PER_US (2 << 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[] = {
|
||||
RK808_BUCK1_CONFIG_REG,
|
||||
RK808_BUCK2_CONFIG_REG,
|
||||
|
@ -91,6 +97,43 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
|||
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 = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
|
@ -100,6 +143,9 @@ static struct regulator_ops rk808_buck1_2_ops = {
|
|||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.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 = {
|
||||
|
@ -110,12 +156,17 @@ static struct regulator_ops rk808_reg_ops = {
|
|||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_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 = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_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[] = {
|
||||
|
|
|
@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
|
|||
|
||||
rdata->id = i;
|
||||
rdata->initdata = of_get_regulator_init_data(
|
||||
&pdev->dev, reg_np);
|
||||
&pdev->dev, reg_np,
|
||||
®ulators[i]);
|
||||
rdata->reg_node = reg_np;
|
||||
rdata++;
|
||||
rmode->id = i;
|
||||
|
|
|
@ -76,7 +76,7 @@ static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
|
|||
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);
|
||||
return init_data;
|
||||
|
|
|
@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
|
|||
config.regmap = stw481x->map;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
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,
|
||||
&vmmc_regulator, &config);
|
||||
|
|
|
@ -837,7 +837,8 @@ static int ti_abb_probe(struct platform_device *pdev)
|
|||
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) {
|
||||
dev_err(dev, "%s: Unable to alloc regulator init data\n",
|
||||
__func__);
|
||||
|
|
|
@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, tps51632_of_match);
|
||||
|
||||
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 device_node *np = dev->of_node;
|
||||
|
@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data *
|
|||
if (!pdata)
|
||||
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) {
|
||||
dev_err(dev, "Not able to get OF regulator init data\n");
|
||||
return NULL;
|
||||
|
@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data *
|
|||
}
|
||||
#else
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
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) {
|
||||
dev_err(&client->dev, "No Platform data\n");
|
||||
return -EINVAL;
|
||||
|
@ -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)
|
||||
tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG;
|
||||
else
|
||||
|
|
|
@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = {
|
|||
};
|
||||
|
||||
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 device_node *np = dev->of_node;
|
||||
|
@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data *
|
|||
if (!pdata)
|
||||
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) {
|
||||
dev_err(dev, "Not able to get OF regulator init data\n");
|
||||
return NULL;
|
||||
|
@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client,
|
|||
|
||||
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) {
|
||||
const struct of_device_id *match;
|
||||
match = of_match_device(of_match_ptr(tps62360_of_match),
|
||||
|
@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client,
|
|||
}
|
||||
chip_id = (int)(long)match->data;
|
||||
if (!pdata)
|
||||
pdata = of_get_tps62360_platform_data(&client->dev);
|
||||
pdata = of_get_tps62360_platform_data(&client->dev,
|
||||
&tps->desc);
|
||||
} else if (id) {
|
||||
chip_id = id->driver_data;
|
||||
} else {
|
||||
|
@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
|
||||
if (!tps)
|
||||
return -ENOMEM;
|
||||
|
||||
tps->en_discharge = pdata->en_discharge;
|
||||
tps->en_internal_pulldn = pdata->en_internal_pulldn;
|
||||
tps->vsel0_gpio = pdata->vsel0_gpio;
|
||||
|
@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client,
|
|||
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);
|
||||
if (IS_ERR(tps->regmap)) {
|
||||
ret = PTR_ERR(tps->regmap);
|
||||
|
|
|
@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
|
|||
|
||||
template = match->data;
|
||||
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,
|
||||
®ulators[id]);
|
||||
|
||||
platform_set_drvdata(pdev, tps);
|
||||
|
||||
|
|
|
@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev)
|
|||
template = match->data;
|
||||
id = template->desc.id;
|
||||
initdata = of_get_regulator_init_data(&pdev->dev,
|
||||
pdev->dev.of_node);
|
||||
pdev->dev.of_node,
|
||||
&template->desc);
|
||||
drvdata = NULL;
|
||||
} else {
|
||||
id = pdev->id;
|
||||
|
|
|
@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
|
|||
reg->desc.owner = THIS_MODULE;
|
||||
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,
|
||||
®->desc);
|
||||
if (!init_data)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 {
|
|||
MAX77686_OPMODE_STANDBY,
|
||||
};
|
||||
|
||||
enum max77802_opmode {
|
||||
MAX77802_OPMODE_OFF,
|
||||
MAX77802_OPMODE_STANDBY,
|
||||
MAX77802_OPMODE_LP,
|
||||
MAX77802_OPMODE_NORMAL,
|
||||
};
|
||||
|
||||
struct max77686_opmode_data {
|
||||
int id;
|
||||
int mode;
|
||||
|
|
|
@ -922,4 +922,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
|
|||
/* CONFIG_OF_RESOLVE api */
|
||||
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 */
|
||||
|
|
|
@ -243,6 +243,8 @@ enum regulator_type {
|
|||
*
|
||||
* @enable_time: Time taken for initial enable of regulator (in uS).
|
||||
* @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 {
|
||||
const char *name;
|
||||
|
@ -285,6 +287,8 @@ struct regulator_desc {
|
|||
unsigned int enable_time;
|
||||
|
||||
unsigned int off_on_delay;
|
||||
|
||||
unsigned int (*of_map_mode)(unsigned int mode);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,24 +6,29 @@
|
|||
#ifndef __LINUX_OF_REG_H
|
||||
#define __LINUX_OF_REG_H
|
||||
|
||||
struct regulator_desc;
|
||||
|
||||
struct of_regulator_match {
|
||||
const char *name;
|
||||
void *driver_data;
|
||||
struct regulator_init_data *init_data;
|
||||
struct device_node *of_node;
|
||||
const struct regulator_desc *desc;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
extern 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);
|
||||
extern int of_regulator_match(struct device *dev, struct device_node *node,
|
||||
struct of_regulator_match *matches,
|
||||
unsigned int num_matches);
|
||||
#else
|
||||
static inline 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)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue