mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (40 commits) regulator: set constraints.apply_uV to 0 in of_get_fixed_voltage_config regulator: max8925: fix enabled/disabled judgement mistake regulator: add regulator_bulk_force_disable function regulator: pass regulator_register of_node in fixed voltage driver regulator: add regulator_force_disable() definition for !CONFIG_REGULATOR regulator: Enable supply regulator if child rail is enabled. regulator: mc13892: Convert to devm_kzalloc() regulator: mc13783: Convert to devm_kzalloc() regulator: Fix checking return value of create_regulator regulator: Fix the error handling if create_regulator fails regulator: Export regulator_is_supported_voltage() regulator: mc13892: add device tree probe support regulator: mc13892: remove the unnecessary prefix from regulator name regulator: Convert wm831x regulator drivers to devm_kzalloc() regulator: da9052: Staticize non-exported symbols regulator: Replace kzalloc with devm_kzalloc and if-else with a switch-case for da9052-regulator regulator: Update da9052-regulator for DT changes regulator: DA9052/53 Regulator support regulator: pass device_node to of_get_regulator_init_data() regulator: If a single voltage is set with device tree then set apply_uV ...
This commit is contained in:
commit
269d430131
@ -0,0 +1,29 @@
|
||||
Fixed Voltage regulators
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "regulator-fixed";
|
||||
|
||||
Optional properties:
|
||||
- gpio: gpio to use for enable control
|
||||
- startup-delay-us: startup time in microseconds
|
||||
- enable-active-high: Polarity of GPIO is Active high
|
||||
If this property is missing, the default assumed is Active low.
|
||||
|
||||
Any property defined as part of the core regulator
|
||||
binding, defined in regulator.txt, can also be used.
|
||||
However a fixed voltage regulator is expected to have the
|
||||
regulator-min-microvolt and regulator-max-microvolt
|
||||
to be the same.
|
||||
|
||||
Example:
|
||||
|
||||
abc: fixedregulator@0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fixed-supply";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio1 16 0>;
|
||||
startup-delay-us = <70000>;
|
||||
enable-active-high;
|
||||
regulator-boot-on
|
||||
};
|
54
Documentation/devicetree/bindings/regulator/regulator.txt
Normal file
54
Documentation/devicetree/bindings/regulator/regulator.txt
Normal file
@ -0,0 +1,54 @@
|
||||
Voltage/Current Regulators
|
||||
|
||||
Optional properties:
|
||||
- regulator-name: A string used as a descriptive name for regulator outputs
|
||||
- regulator-min-microvolt: smallest voltage consumers may set
|
||||
- regulator-max-microvolt: largest voltage consumers may set
|
||||
- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops
|
||||
- regulator-min-microamp: smallest current consumers may set
|
||||
- regulator-max-microamp: largest current consumers may set
|
||||
- regulator-always-on: boolean, regulator should never be disabled
|
||||
- regulator-boot-on: bootloader/firmware enabled regulator
|
||||
- <name>-supply: phandle to the parent supply/regulator node
|
||||
|
||||
Example:
|
||||
|
||||
xyzreg: regulator@0 {
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
vin-supply = <&vin>;
|
||||
};
|
||||
|
||||
Regulator Consumers:
|
||||
Consumer nodes can reference one or more of its supplies/
|
||||
regulators using the below bindings.
|
||||
|
||||
- <name>-supply: phandle to the regulator node
|
||||
|
||||
These are the same bindings that a regulator in the above
|
||||
example used to reference its own supply, in which case
|
||||
its just seen as a special case of a regulator being a
|
||||
consumer itself.
|
||||
|
||||
Example of a consumer device node (mmc) referencing two
|
||||
regulators (twl_reg1 and twl_reg2),
|
||||
|
||||
twl_reg1: regulator@0 {
|
||||
...
|
||||
...
|
||||
...
|
||||
};
|
||||
|
||||
twl_reg2: regulator@1 {
|
||||
...
|
||||
...
|
||||
...
|
||||
};
|
||||
|
||||
mmc: mmc@0x0 {
|
||||
...
|
||||
...
|
||||
vmmc-supply = <&twl_reg1>;
|
||||
vmmcaux-supply = <&twl_reg2>;
|
||||
};
|
@ -12,7 +12,7 @@ Drivers can register a regulator by calling :-
|
||||
|
||||
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
struct device *dev, struct regulator_init_data *init_data,
|
||||
void *driver_data);
|
||||
void *driver_data, struct device_node *of_node);
|
||||
|
||||
This will register the regulators capabilities and operations to the regulator
|
||||
core.
|
||||
|
@ -427,7 +427,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
/* replace driver_data with info */
|
||||
info->regulator = regulator_register(&info->desc, &pdev->dev,
|
||||
pdata, info);
|
||||
pdata, info, NULL);
|
||||
if (IS_ERR(info->regulator)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
info->desc.name);
|
||||
|
@ -93,6 +93,7 @@ config REGULATOR_MAX1586
|
||||
config REGULATOR_MAX8649
|
||||
tristate "Maxim 8649 voltage regulator"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver controls a Maxim 8649 voltage output regulator via
|
||||
I2C bus.
|
||||
@ -177,6 +178,13 @@ config REGULATOR_DA903X
|
||||
Say y here to support the BUCKs and LDOs regulators found on
|
||||
Dialog Semiconductor DA9030/DA9034 PMIC.
|
||||
|
||||
config REGULATOR_DA9052
|
||||
tristate "Dialog DA9052/DA9053 regulators"
|
||||
depends on PMIC_DA9052
|
||||
help
|
||||
This driver supports the voltage regulators of DA9052-BC and
|
||||
DA9053-AA/Bx PMIC.
|
||||
|
||||
config REGULATOR_PCF50633
|
||||
tristate "PCF50633 regulator driver"
|
||||
depends on MFD_PCF50633
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
|
||||
obj-$(CONFIG_REGULATOR) += core.o dummy.o
|
||||
obj-$(CONFIG_OF) += of_regulator.o
|
||||
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
|
||||
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
|
||||
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
|
||||
@ -29,6 +30,7 @@ obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
|
||||
|
@ -63,7 +63,7 @@ static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
|
||||
struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
|
||||
|
||||
return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask,
|
||||
(selector << ri->voltage_shift) & ri->voltage_mask);
|
||||
selector << ri->voltage_shift);
|
||||
}
|
||||
|
||||
static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev)
|
||||
@ -188,7 +188,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
|
||||
ri->pdev = pdev;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &pdev->dev,
|
||||
pdev->dev.platform_data, ri);
|
||||
pdev->dev.platform_data, ri, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "Failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
|
@ -634,7 +634,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
|
||||
rdev = regulator_register(&ab3100_regulator_desc[i],
|
||||
&pdev->dev,
|
||||
&plfdata->reg_constraints[i],
|
||||
reg);
|
||||
reg, NULL);
|
||||
|
||||
if (IS_ERR(rdev)) {
|
||||
err = PTR_ERR(rdev);
|
||||
|
@ -822,7 +822,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
/* register regulator with framework */
|
||||
info->regulator = regulator_register(&info->desc, &pdev->dev,
|
||||
&pdata->regulator[i], info);
|
||||
&pdata->regulator[i], info, NULL);
|
||||
if (IS_ERR(info->regulator)) {
|
||||
err = PTR_ERR(info->regulator);
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
|
@ -233,7 +233,7 @@ static int __devinit ad5398_probe(struct i2c_client *client,
|
||||
chip->current_mask = (chip->current_level - 1) << chip->current_offset;
|
||||
|
||||
chip->rdev = regulator_register(&ad5398_reg, &client->dev,
|
||||
init_data, chip);
|
||||
init_data, chip, NULL);
|
||||
if (IS_ERR(chip->rdev)) {
|
||||
ret = PTR_ERR(chip->rdev);
|
||||
dev_err(&client->dev, "failed to register %s %s\n",
|
||||
|
@ -107,7 +107,7 @@ static int __init bq24022_probe(struct platform_device *pdev)
|
||||
ret = gpio_direction_output(pdata->gpio_nce, 1);
|
||||
|
||||
bq24022 = regulator_register(&bq24022_desc, &pdev->dev,
|
||||
pdata->init_data, pdata);
|
||||
pdata->init_data, pdata, NULL);
|
||||
if (IS_ERR(bq24022)) {
|
||||
dev_dbg(&pdev->dev, "couldn't register regulator\n");
|
||||
ret = PTR_ERR(bq24022);
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
@ -132,6 +134,33 @@ static struct regulator *get_device_regulator(struct device *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_get_regulator - get a regulator device node based on supply name
|
||||
* @dev: Device pointer for the consumer (of regulator) device
|
||||
* @supply: regulator supply name
|
||||
*
|
||||
* Extract the regulator device node corresponding to the supply name.
|
||||
* retruns the device node corresponding to the regulator if found, else
|
||||
* returns NULL.
|
||||
*/
|
||||
static struct device_node *of_get_regulator(struct device *dev, const char *supply)
|
||||
{
|
||||
struct device_node *regnode = NULL;
|
||||
char prop_name[32]; /* 32 is max size of property name */
|
||||
|
||||
dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
|
||||
|
||||
snprintf(prop_name, 32, "%s-supply", supply);
|
||||
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
|
||||
|
||||
if (!regnode) {
|
||||
dev_warn(dev, "%s property in node %s references invalid phandle",
|
||||
prop_name, dev->of_node->full_name);
|
||||
return NULL;
|
||||
}
|
||||
return regnode;
|
||||
}
|
||||
|
||||
/* Platform voltage constraint check */
|
||||
static int regulator_check_voltage(struct regulator_dev *rdev,
|
||||
int *min_uV, int *max_uV)
|
||||
@ -883,8 +912,12 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
int ret = 0;
|
||||
struct regulator_ops *ops = rdev->desc->ops;
|
||||
|
||||
rdev->constraints = kmemdup(constraints, sizeof(*constraints),
|
||||
GFP_KERNEL);
|
||||
if (constraints)
|
||||
rdev->constraints = kmemdup(constraints, sizeof(*constraints),
|
||||
GFP_KERNEL);
|
||||
else
|
||||
rdev->constraints = kzalloc(sizeof(*constraints),
|
||||
GFP_KERNEL);
|
||||
if (!rdev->constraints)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -893,7 +926,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
goto out;
|
||||
|
||||
/* do we need to setup our suspend state */
|
||||
if (constraints->initial_state) {
|
||||
if (rdev->constraints->initial_state) {
|
||||
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to set suspend state\n");
|
||||
@ -901,7 +934,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (constraints->initial_mode) {
|
||||
if (rdev->constraints->initial_mode) {
|
||||
if (!ops->set_mode) {
|
||||
rdev_err(rdev, "no set_mode operation\n");
|
||||
ret = -EINVAL;
|
||||
@ -952,9 +985,8 @@ static int set_supply(struct regulator_dev *rdev,
|
||||
rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
|
||||
|
||||
rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
|
||||
if (IS_ERR(rdev->supply)) {
|
||||
err = PTR_ERR(rdev->supply);
|
||||
rdev->supply = NULL;
|
||||
if (rdev->supply == NULL) {
|
||||
err = -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1148,6 +1180,30 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
|
||||
return rdev->desc->ops->enable_time(rdev);
|
||||
}
|
||||
|
||||
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
|
||||
const char *supply)
|
||||
{
|
||||
struct regulator_dev *r;
|
||||
struct device_node *node;
|
||||
|
||||
/* first do a dt based lookup */
|
||||
if (dev && dev->of_node) {
|
||||
node = of_get_regulator(dev, supply);
|
||||
if (node)
|
||||
list_for_each_entry(r, ®ulator_list, list)
|
||||
if (r->dev.parent &&
|
||||
node == r->dev.of_node)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* if not found, try doing it non-dt way */
|
||||
list_for_each_entry(r, ®ulator_list, list)
|
||||
if (strcmp(rdev_get_name(r), supply) == 0)
|
||||
return r;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Internal regulator request function */
|
||||
static struct regulator *_regulator_get(struct device *dev, const char *id,
|
||||
int exclusive)
|
||||
@ -1168,6 +1224,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
|
||||
rdev = regulator_dev_lookup(dev, id);
|
||||
if (rdev)
|
||||
goto found;
|
||||
|
||||
list_for_each_entry(map, ®ulator_map_list, list) {
|
||||
/* If the mapping has a device set up it must match */
|
||||
if (map->dev_name &&
|
||||
@ -1221,6 +1281,7 @@ found:
|
||||
if (regulator == NULL) {
|
||||
regulator = ERR_PTR(-ENOMEM);
|
||||
module_put(rdev->owner);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rdev->open_count++;
|
||||
@ -1726,6 +1787,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
|
||||
|
||||
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
@ -2428,6 +2490,43 @@ err:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_bulk_disable);
|
||||
|
||||
/**
|
||||
* regulator_bulk_force_disable - force disable multiple regulator consumers
|
||||
*
|
||||
* @num_consumers: Number of consumers
|
||||
* @consumers: Consumer data; clients are stored here.
|
||||
* @return 0 on success, an errno on failure
|
||||
*
|
||||
* This convenience API allows consumers to forcibly disable multiple regulator
|
||||
* clients in a single API call.
|
||||
* NOTE: This should be used for situations when device damage will
|
||||
* likely occur if the regulators are not disabled (e.g. over temp).
|
||||
* Although regulator_force_disable function call for some consumers can
|
||||
* return error numbers, the function is called for all consumers.
|
||||
*/
|
||||
int regulator_bulk_force_disable(int num_consumers,
|
||||
struct regulator_bulk_data *consumers)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < num_consumers; i++)
|
||||
consumers[i].ret =
|
||||
regulator_force_disable(consumers[i].consumer);
|
||||
|
||||
for (i = 0; i < num_consumers; i++) {
|
||||
if (consumers[i].ret != 0) {
|
||||
ret = consumers[i].ret;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
|
||||
|
||||
/**
|
||||
* regulator_bulk_free - free multiple regulator consumers
|
||||
*
|
||||
@ -2503,7 +2602,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
||||
int status = 0;
|
||||
|
||||
/* some attributes need specific methods to be displayed */
|
||||
if (ops->get_voltage || ops->get_voltage_sel) {
|
||||
if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
|
||||
(ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) {
|
||||
status = device_create_file(dev, &dev_attr_microvolts);
|
||||
if (status < 0)
|
||||
return status;
|
||||
@ -2637,11 +2737,13 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
|
||||
*/
|
||||
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
struct device *dev, const struct regulator_init_data *init_data,
|
||||
void *driver_data)
|
||||
void *driver_data, struct device_node *of_node)
|
||||
{
|
||||
const struct regulation_constraints *constraints = NULL;
|
||||
static atomic_t regulator_no = ATOMIC_INIT(0);
|
||||
struct regulator_dev *rdev;
|
||||
int ret, i;
|
||||
const char *supply = NULL;
|
||||
|
||||
if (regulator_desc == NULL)
|
||||
return ERR_PTR(-EINVAL);
|
||||
@ -2653,9 +2755,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
regulator_desc->type != REGULATOR_CURRENT)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!init_data)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Only one of each should be implemented */
|
||||
WARN_ON(regulator_desc->ops->get_voltage &&
|
||||
regulator_desc->ops->get_voltage_sel);
|
||||
@ -2688,7 +2787,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
|
||||
|
||||
/* preform any regulator specific init */
|
||||
if (init_data->regulator_init) {
|
||||
if (init_data && init_data->regulator_init) {
|
||||
ret = init_data->regulator_init(rdev->reg_data);
|
||||
if (ret < 0)
|
||||
goto clean;
|
||||
@ -2696,6 +2795,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
|
||||
/* register with sysfs */
|
||||
rdev->dev.class = ®ulator_class;
|
||||
rdev->dev.of_node = of_node;
|
||||
rdev->dev.parent = dev;
|
||||
dev_set_name(&rdev->dev, "regulator.%d",
|
||||
atomic_inc_return(®ulator_no) - 1);
|
||||
@ -2708,7 +2808,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
dev_set_drvdata(&rdev->dev, rdev);
|
||||
|
||||
/* set regulator constraints */
|
||||
ret = set_machine_constraints(rdev, &init_data->constraints);
|
||||
if (init_data)
|
||||
constraints = &init_data->constraints;
|
||||
|
||||
ret = set_machine_constraints(rdev, constraints);
|
||||
if (ret < 0)
|
||||
goto scrub;
|
||||
|
||||
@ -2717,21 +2820,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
if (ret < 0)
|
||||
goto scrub;
|
||||
|
||||
if (init_data->supply_regulator) {
|
||||
if (init_data && init_data->supply_regulator)
|
||||
supply = init_data->supply_regulator;
|
||||
else if (regulator_desc->supply_name)
|
||||
supply = regulator_desc->supply_name;
|
||||
|
||||
if (supply) {
|
||||
struct regulator_dev *r;
|
||||
int found = 0;
|
||||
|
||||
list_for_each_entry(r, ®ulator_list, list) {
|
||||
if (strcmp(rdev_get_name(r),
|
||||
init_data->supply_regulator) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
r = regulator_dev_lookup(dev, supply);
|
||||
|
||||
if (!found) {
|
||||
dev_err(dev, "Failed to find supply %s\n",
|
||||
init_data->supply_regulator);
|
||||
if (!r) {
|
||||
dev_err(dev, "Failed to find supply %s\n", supply);
|
||||
ret = -ENODEV;
|
||||
goto scrub;
|
||||
}
|
||||
@ -2739,18 +2839,28 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
ret = set_supply(rdev, r);
|
||||
if (ret < 0)
|
||||
goto scrub;
|
||||
|
||||
/* Enable supply if rail is enabled */
|
||||
if (rdev->desc->ops->is_enabled &&
|
||||
rdev->desc->ops->is_enabled(rdev)) {
|
||||
ret = regulator_enable(rdev->supply);
|
||||
if (ret < 0)
|
||||
goto scrub;
|
||||
}
|
||||
}
|
||||
|
||||
/* add consumers devices */
|
||||
for (i = 0; i < init_data->num_consumer_supplies; i++) {
|
||||
ret = set_consumer_device_supply(rdev,
|
||||
init_data->consumer_supplies[i].dev,
|
||||
init_data->consumer_supplies[i].dev_name,
|
||||
init_data->consumer_supplies[i].supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set supply %s\n",
|
||||
if (init_data) {
|
||||
for (i = 0; i < init_data->num_consumer_supplies; i++) {
|
||||
ret = set_consumer_device_supply(rdev,
|
||||
init_data->consumer_supplies[i].dev,
|
||||
init_data->consumer_supplies[i].dev_name,
|
||||
init_data->consumer_supplies[i].supply);
|
||||
goto unset_supplies;
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set supply %s\n",
|
||||
init_data->consumer_supplies[i].supply);
|
||||
goto unset_supplies;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
|
||||
ri->desc.ops = &da9030_regulator_ldo1_15_ops;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &pdev->dev,
|
||||
pdev->dev.platform_data, ri);
|
||||
pdev->dev.platform_data, ri, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
|
606
drivers/regulator/da9052-regulator.c
Normal file
606
drivers/regulator/da9052-regulator.c
Normal file
@ -0,0 +1,606 @@
|
||||
/*
|
||||
* da9052-regulator.c: Regulator driver for DA9052
|
||||
*
|
||||
* Copyright(c) 2011 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: David Dajun Chen <dchen@diasemi.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/mfd/da9052/da9052.h>
|
||||
#include <linux/mfd/da9052/reg.h>
|
||||
#include <linux/mfd/da9052/pdata.h>
|
||||
|
||||
/* Buck step size */
|
||||
#define DA9052_BUCK_PERI_3uV_STEP 100000
|
||||
#define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
|
||||
#define DA9052_CONST_3uV 3000000
|
||||
|
||||
#define DA9052_MIN_UA 0
|
||||
#define DA9052_MAX_UA 3
|
||||
#define DA9052_CURRENT_RANGE 4
|
||||
|
||||
/* Bit masks */
|
||||
#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
|
||||
#define DA9052_BUCK_ILIM_MASK_ODD 0xc0
|
||||
|
||||
static const u32 da9052_current_limits[3][4] = {
|
||||
{700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
|
||||
{1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
|
||||
{800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
|
||||
* BUCK-MEM and BUCK-PERI
|
||||
*/
|
||||
};
|
||||
|
||||
struct da9052_regulator_info {
|
||||
struct regulator_desc reg_desc;
|
||||
int step_uV;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
unsigned char volt_shift;
|
||||
unsigned char en_bit;
|
||||
unsigned char activate_bit;
|
||||
};
|
||||
|
||||
struct da9052_regulator {
|
||||
struct da9052 *da9052;
|
||||
struct da9052_regulator_info *info;
|
||||
struct regulator_dev *rdev;
|
||||
};
|
||||
|
||||
static int verify_range(struct da9052_regulator_info *info,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
if (min_uV > info->max_uV || max_uV < info->min_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9052_regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKCORE_REG + offset,
|
||||
1 << info->en_bit, 1 << info->en_bit);
|
||||
}
|
||||
|
||||
static int da9052_regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKCORE_REG + offset,
|
||||
1 << info->en_bit, 0);
|
||||
}
|
||||
|
||||
static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret & (1 << info->en_bit);
|
||||
}
|
||||
|
||||
static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret, row = 2;
|
||||
|
||||
ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Determine the even or odd position of the buck current limit
|
||||
* register field
|
||||
*/
|
||||
if (offset % 2 == 0)
|
||||
ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
|
||||
else
|
||||
ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
|
||||
|
||||
/* Select the appropriate current limit range */
|
||||
if (regulator->da9052->chip_id == DA9052)
|
||||
row = 0;
|
||||
else if (offset == 0)
|
||||
row = 1;
|
||||
|
||||
return da9052_current_limits[row][ret];
|
||||
}
|
||||
|
||||
static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
int max_uA)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
int offset = rdev_get_id(rdev);
|
||||
int reg_val = 0;
|
||||
int i, row = 2;
|
||||
|
||||
/* Select the appropriate current limit range */
|
||||
if (regulator->da9052->chip_id == DA9052)
|
||||
row = 0;
|
||||
else if (offset == 0)
|
||||
row = 1;
|
||||
|
||||
if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
|
||||
max_uA < da9052_current_limits[row][DA9052_MIN_UA])
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
|
||||
if (min_uA <= da9052_current_limits[row][i]) {
|
||||
reg_val = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the even or odd position of the buck current limit
|
||||
* register field
|
||||
*/
|
||||
if (offset % 2 == 0)
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKA_REG + offset/2,
|
||||
DA9052_BUCK_ILIM_MASK_EVEN,
|
||||
reg_val << 2);
|
||||
else
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKA_REG + offset/2,
|
||||
DA9052_BUCK_ILIM_MASK_ODD,
|
||||
reg_val << 6);
|
||||
}
|
||||
|
||||
static int da9052_list_buckperi_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int volt_uV;
|
||||
|
||||
if ((regulator->da9052->chip_id == DA9052) &&
|
||||
(selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
|
||||
volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
|
||||
+ info->min_uV);
|
||||
volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
|
||||
* (DA9052_BUCK_PERI_3uV_STEP);
|
||||
} else
|
||||
volt_uV = (selector * info->step_uV) + info->min_uV;
|
||||
|
||||
if (volt_uV > info->max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return volt_uV;
|
||||
}
|
||||
|
||||
static int da9052_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int volt_uV;
|
||||
|
||||
volt_uV = info->min_uV + info->step_uV * selector;
|
||||
|
||||
if (volt_uV > info->max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return volt_uV;
|
||||
}
|
||||
|
||||
static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
ret = verify_range(info, min_uV, max_uV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (min_uV < info->min_uV)
|
||||
min_uV = info->min_uV;
|
||||
|
||||
*selector = (min_uV - info->min_uV) / info->step_uV;
|
||||
|
||||
ret = da9052_list_voltage(rdev, *selector);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKCORE_REG + offset,
|
||||
(1 << info->volt_shift) - 1, *selector);
|
||||
}
|
||||
|
||||
static int da9052_set_ldo_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
|
||||
}
|
||||
|
||||
static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Some LDOs are DVC controlled which requires enabling of
|
||||
* the LDO activate bit to implment the changes on the
|
||||
* LDO output.
|
||||
*/
|
||||
return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, 0,
|
||||
info->activate_bit);
|
||||
}
|
||||
|
||||
static int da9052_set_dcdc_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Some DCDCs are DVC controlled which requires enabling of
|
||||
* the DCDC activate bit to implment the changes on the
|
||||
* DCDC output.
|
||||
*/
|
||||
return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, 0,
|
||||
info->activate_bit);
|
||||
}
|
||||
|
||||
static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ((1 << info->volt_shift) - 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
|
||||
int max_uV, unsigned int *selector)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
ret = verify_range(info, min_uV, max_uV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (min_uV < info->min_uV)
|
||||
min_uV = info->min_uV;
|
||||
|
||||
if ((regulator->da9052->chip_id == DA9052) &&
|
||||
(min_uV >= DA9052_CONST_3uV))
|
||||
*selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
|
||||
((min_uV - DA9052_CONST_3uV) /
|
||||
(DA9052_BUCK_PERI_3uV_STEP));
|
||||
else
|
||||
*selector = (min_uV - info->min_uV) / info->step_uV;
|
||||
|
||||
ret = da9052_list_buckperi_voltage(rdev, *selector);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return da9052_reg_update(regulator->da9052,
|
||||
DA9052_BUCKCORE_REG + offset,
|
||||
(1 << info->volt_shift) - 1, *selector);
|
||||
}
|
||||
|
||||
static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9052_regulator_info *info = regulator->info;
|
||||
int offset = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= ((1 << info->volt_shift) - 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops da9052_buckperi_ops = {
|
||||
.list_voltage = da9052_list_buckperi_voltage,
|
||||
.get_voltage_sel = da9052_get_buckperi_voltage_sel,
|
||||
.set_voltage = da9052_set_buckperi_voltage,
|
||||
|
||||
.get_current_limit = da9052_dcdc_get_current_limit,
|
||||
.set_current_limit = da9052_dcdc_set_current_limit,
|
||||
|
||||
.is_enabled = da9052_regulator_is_enabled,
|
||||
.enable = da9052_regulator_enable,
|
||||
.disable = da9052_regulator_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9052_dcdc_ops = {
|
||||
.set_voltage = da9052_set_dcdc_voltage,
|
||||
.get_current_limit = da9052_dcdc_get_current_limit,
|
||||
.set_current_limit = da9052_dcdc_set_current_limit,
|
||||
|
||||
.list_voltage = da9052_list_voltage,
|
||||
.get_voltage_sel = da9052_get_regulator_voltage_sel,
|
||||
.is_enabled = da9052_regulator_is_enabled,
|
||||
.enable = da9052_regulator_enable,
|
||||
.disable = da9052_regulator_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9052_ldo5_6_ops = {
|
||||
.set_voltage = da9052_set_ldo5_6_voltage,
|
||||
|
||||
.list_voltage = da9052_list_voltage,
|
||||
.get_voltage_sel = da9052_get_regulator_voltage_sel,
|
||||
.is_enabled = da9052_regulator_is_enabled,
|
||||
.enable = da9052_regulator_enable,
|
||||
.disable = da9052_regulator_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9052_ldo_ops = {
|
||||
.set_voltage = da9052_set_ldo_voltage,
|
||||
|
||||
.list_voltage = da9052_list_voltage,
|
||||
.get_voltage_sel = da9052_get_regulator_voltage_sel,
|
||||
.is_enabled = da9052_regulator_is_enabled,
|
||||
.enable = da9052_regulator_enable,
|
||||
.disable = da9052_regulator_disable,
|
||||
};
|
||||
|
||||
#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = "LDO" #_id,\
|
||||
.ops = &da9052_ldo5_6_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = _id,\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.min_uV = (min) * 1000,\
|
||||
.max_uV = (max) * 1000,\
|
||||
.step_uV = (step) * 1000,\
|
||||
.volt_shift = (sbits),\
|
||||
.en_bit = (ebits),\
|
||||
.activate_bit = (abits),\
|
||||
}
|
||||
|
||||
#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = "LDO" #_id,\
|
||||
.ops = &da9052_ldo_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = _id,\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.min_uV = (min) * 1000,\
|
||||
.max_uV = (max) * 1000,\
|
||||
.step_uV = (step) * 1000,\
|
||||
.volt_shift = (sbits),\
|
||||
.en_bit = (ebits),\
|
||||
.activate_bit = (abits),\
|
||||
}
|
||||
|
||||
#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = "BUCK" #_id,\
|
||||
.ops = &da9052_dcdc_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = _id,\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.min_uV = (min) * 1000,\
|
||||
.max_uV = (max) * 1000,\
|
||||
.step_uV = (step) * 1000,\
|
||||
.volt_shift = (sbits),\
|
||||
.en_bit = (ebits),\
|
||||
.activate_bit = (abits),\
|
||||
}
|
||||
|
||||
#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = "BUCK" #_id,\
|
||||
.ops = &da9052_buckperi_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = _id,\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.min_uV = (min) * 1000,\
|
||||
.max_uV = (max) * 1000,\
|
||||
.step_uV = (step) * 1000,\
|
||||
.volt_shift = (sbits),\
|
||||
.en_bit = (ebits),\
|
||||
.activate_bit = (abits),\
|
||||
}
|
||||
|
||||
static struct da9052_regulator_info da9052_regulator_info[] = {
|
||||
/* Buck1 - 4 */
|
||||
DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
|
||||
DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
|
||||
DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
|
||||
DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0),
|
||||
/* LD01 - LDO10 */
|
||||
DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
|
||||
DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
|
||||
DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
|
||||
DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
|
||||
DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
|
||||
DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
|
||||
};
|
||||
|
||||
static struct da9052_regulator_info da9053_regulator_info[] = {
|
||||
/* Buck1 - 4 */
|
||||
DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
|
||||
DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
|
||||
DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
|
||||
DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0),
|
||||
/* LD01 - LDO10 */
|
||||
DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
|
||||
DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
|
||||
DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
|
||||
DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
|
||||
DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
|
||||
DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
|
||||
DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
|
||||
};
|
||||
|
||||
static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
|
||||
int id)
|
||||
{
|
||||
struct da9052_regulator_info *info;
|
||||
int i;
|
||||
|
||||
switch (chip_id) {
|
||||
case DA9052:
|
||||
for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
|
||||
info = &da9052_regulator_info[i];
|
||||
if (info->reg_desc.id == id)
|
||||
return info;
|
||||
}
|
||||
break;
|
||||
case DA9053_AA:
|
||||
case DA9053_BA:
|
||||
case DA9053_BB:
|
||||
for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
|
||||
info = &da9053_regulator_info[i];
|
||||
if (info->reg_desc.id == id)
|
||||
return info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit da9052_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_regulator *regulator;
|
||||
struct da9052 *da9052;
|
||||
struct da9052_pdata *pdata;
|
||||
int ret;
|
||||
|
||||
regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
|
||||
GFP_KERNEL);
|
||||
if (!regulator)
|
||||
return -ENOMEM;
|
||||
|
||||
da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||
pdata = da9052->dev->platform_data;
|
||||
regulator->da9052 = da9052;
|
||||
|
||||
regulator->info = find_regulator_info(regulator->da9052->chip_id,
|
||||
pdev->id);
|
||||
if (regulator->info == NULL) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
regulator->rdev = regulator_register(®ulator->info->reg_desc,
|
||||
&pdev->dev,
|
||||
pdata->regulators[pdev->id],
|
||||
regulator, NULL);
|
||||
if (IS_ERR(regulator->rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
regulator->info->reg_desc.name);
|
||||
ret = PTR_ERR(regulator->rdev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, regulator);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
devm_kfree(&pdev->dev, regulator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da9052_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(regulator->rdev);
|
||||
devm_kfree(&pdev->dev, regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9052_regulator_driver = {
|
||||
.probe = da9052_regulator_probe,
|
||||
.remove = __devexit_p(da9052_regulator_remove),
|
||||
.driver = {
|
||||
.name = "da9052-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init da9052_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&da9052_regulator_driver);
|
||||
}
|
||||
subsys_initcall(da9052_regulator_init);
|
||||
|
||||
static void __exit da9052_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da9052_regulator_driver);
|
||||
}
|
||||
module_exit(da9052_regulator_exit);
|
||||
|
||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
||||
MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9052-regulator");
|
@ -486,7 +486,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
/* register with the regulator framework */
|
||||
info->rdev = regulator_register(&info->desc, &pdev->dev,
|
||||
init_data, info);
|
||||
init_data, info, NULL);
|
||||
if (IS_ERR(info->rdev)) {
|
||||
err = PTR_ERR(info->rdev);
|
||||
dev_err(&pdev->dev, "failed to register %s: err %i\n",
|
||||
|
@ -42,7 +42,7 @@ static int __devinit dummy_regulator_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
|
||||
&dummy_initdata, NULL);
|
||||
&dummy_initdata, NULL, NULL);
|
||||
if (IS_ERR(dummy_regulator_rdev)) {
|
||||
ret = PTR_ERR(dummy_regulator_rdev);
|
||||
pr_err("Failed to register regulator: %d\n", ret);
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
struct fixed_voltage_data {
|
||||
struct regulator_desc desc;
|
||||
@ -38,6 +42,58 @@ struct fixed_voltage_data {
|
||||
bool is_enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info
|
||||
* @dev: device requesting for fixed_voltage_config
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
struct fixed_voltage_config *config;
|
||||
struct device_node *np = dev->of_node;
|
||||
const __be32 *delay;
|
||||
struct regulator_init_data *init_data;
|
||||
|
||||
config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
|
||||
GFP_KERNEL);
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
config->init_data = of_get_regulator_init_data(dev, dev->of_node);
|
||||
if (!config->init_data)
|
||||
return NULL;
|
||||
|
||||
init_data = config->init_data;
|
||||
init_data->constraints.apply_uV = 0;
|
||||
|
||||
config->supply_name = init_data->constraints.name;
|
||||
if (init_data->constraints.min_uV == init_data->constraints.max_uV) {
|
||||
config->microvolts = init_data->constraints.min_uV;
|
||||
} else {
|
||||
dev_err(dev,
|
||||
"Fixed regulator specified with variable voltages\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (init_data->constraints.boot_on)
|
||||
config->enabled_at_boot = true;
|
||||
|
||||
config->gpio = of_get_named_gpio(np, "gpio", 0);
|
||||
delay = of_get_property(np, "startup-delay-us", NULL);
|
||||
if (delay)
|
||||
config->startup_delay = be32_to_cpu(*delay);
|
||||
|
||||
if (of_find_property(np, "enable-active-high", NULL))
|
||||
config->enable_high = true;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static int fixed_voltage_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
@ -80,7 +136,10 @@ static int fixed_voltage_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->microvolts;
|
||||
if (data->microvolts)
|
||||
return data->microvolts;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int fixed_voltage_list_voltage(struct regulator_dev *dev,
|
||||
@ -105,10 +164,18 @@ static struct regulator_ops fixed_voltage_ops = {
|
||||
|
||||
static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fixed_voltage_config *config = pdev->dev.platform_data;
|
||||
struct fixed_voltage_config *config;
|
||||
struct fixed_voltage_data *drvdata;
|
||||
int ret;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
config = of_get_fixed_voltage_config(&pdev->dev);
|
||||
else
|
||||
config = pdev->dev.platform_data;
|
||||
|
||||
if (!config)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
|
||||
if (drvdata == NULL) {
|
||||
dev_err(&pdev->dev, "Failed to allocate device data\n");
|
||||
@ -180,7 +247,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
|
||||
config->init_data, drvdata);
|
||||
config->init_data, drvdata,
|
||||
pdev->dev.of_node);
|
||||
if (IS_ERR(drvdata->dev)) {
|
||||
ret = PTR_ERR(drvdata->dev);
|
||||
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
|
||||
@ -217,12 +285,23 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id fixed_of_match[] __devinitconst = {
|
||||
{ .compatible = "regulator-fixed", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fixed_of_match);
|
||||
#else
|
||||
#define fixed_of_match NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver regulator_fixed_voltage_driver = {
|
||||
.probe = reg_fixed_voltage_probe,
|
||||
.remove = __devexit_p(reg_fixed_voltage_remove),
|
||||
.driver = {
|
||||
.name = "reg-fixed-voltage",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = fixed_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -284,7 +284,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
drvdata->state = state;
|
||||
|
||||
drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
|
||||
config->init_data, drvdata);
|
||||
config->init_data, drvdata, NULL);
|
||||
if (IS_ERR(drvdata->dev)) {
|
||||
ret = PTR_ERR(drvdata->dev);
|
||||
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
|
||||
|
@ -170,7 +170,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c,
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev,
|
||||
init_data, pmic);
|
||||
init_data, pmic, NULL);
|
||||
if (IS_ERR(pmic->rdev[i])) {
|
||||
dev_err(&i2c->dev, "failed to register %s\n", id->name);
|
||||
err = PTR_ERR(pmic->rdev[i]);
|
||||
|
@ -451,7 +451,7 @@ static int __devinit setup_regulators(struct lp3971 *lp3971,
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
|
||||
lp3971->rdev[i] = regulator_register(®ulators[reg->id],
|
||||
lp3971->dev, reg->initdata, lp3971);
|
||||
lp3971->dev, reg->initdata, lp3971, NULL);
|
||||
|
||||
if (IS_ERR(lp3971->rdev[i])) {
|
||||
err = PTR_ERR(lp3971->rdev[i]);
|
||||
|
@ -555,7 +555,7 @@ static int __devinit setup_regulators(struct lp3972 *lp3972,
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
struct lp3972_regulator_subdev *reg = &pdata->regulators[i];
|
||||
lp3972->rdev[i] = regulator_register(®ulators[reg->id],
|
||||
lp3972->dev, reg->initdata, lp3972);
|
||||
lp3972->dev, reg->initdata, lp3972, NULL);
|
||||
|
||||
if (IS_ERR(lp3972->rdev[i])) {
|
||||
err = PTR_ERR(lp3972->rdev[i]);
|
||||
|
@ -214,7 +214,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
|
||||
}
|
||||
rdev[i] = regulator_register(&max1586_reg[id], &client->dev,
|
||||
pdata->subdevs[i].platform_data,
|
||||
max1586);
|
||||
max1586, NULL);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(&client->dev, "failed to register %s\n",
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/max8649.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define MAX8649_DCDC_VMIN 750000 /* uV */
|
||||
#define MAX8649_DCDC_VMAX 1380000 /* uV */
|
||||
@ -49,9 +50,8 @@
|
||||
|
||||
struct max8649_regulator_info {
|
||||
struct regulator_dev *regulator;
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct mutex io_lock;
|
||||
struct regmap *regmap;
|
||||
|
||||
int vol_reg;
|
||||
unsigned mode:2; /* bit[1:0] = VID1, VID0 */
|
||||
@ -63,71 +63,6 @@ struct max8649_regulator_info {
|
||||
|
||||
/* I2C operations */
|
||||
|
||||
static inline int max8649_read_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
data = (unsigned char)reg;
|
||||
ret = i2c_master_send(i2c, &data, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_master_recv(i2c, dest, bytes);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int max8649_write_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *src)
|
||||
{
|
||||
unsigned char buf[bytes + 1];
|
||||
int ret;
|
||||
|
||||
buf[0] = (unsigned char)reg;
|
||||
memcpy(&buf[1], src, bytes);
|
||||
|
||||
ret = i2c_master_send(i2c, buf, bytes + 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8649_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->io_lock);
|
||||
ret = max8649_read_device(i2c, reg, 1, &data);
|
||||
mutex_unlock(&info->io_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return (int)data;
|
||||
}
|
||||
|
||||
static int max8649_set_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask, unsigned char data)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
|
||||
unsigned char value;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->io_lock);
|
||||
ret = max8649_read_device(i2c, reg, 1, &value);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
value &= ~mask;
|
||||
value |= data;
|
||||
ret = max8649_write_device(i2c, reg, 1, &value);
|
||||
out:
|
||||
mutex_unlock(&info->io_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int check_range(int min_uV, int max_uV)
|
||||
{
|
||||
if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX)
|
||||
@ -144,13 +79,14 @@ static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||
static int max8649_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
ret = regmap_read(info->regmap, info->vol_reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
data = (unsigned char)ret & MAX8649_VOL_MASK;
|
||||
data = (unsigned char)val & MAX8649_VOL_MASK;
|
||||
return max8649_list_voltage(rdev, data);
|
||||
}
|
||||
|
||||
@ -170,14 +106,14 @@ static int max8649_set_voltage(struct regulator_dev *rdev,
|
||||
mask = MAX8649_VOL_MASK;
|
||||
*selector = data & mask;
|
||||
|
||||
return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
|
||||
return regmap_update_bits(info->regmap, info->vol_reg, mask, data);
|
||||
}
|
||||
|
||||
/* EN_PD means pulldown on EN input */
|
||||
static int max8649_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD, 0);
|
||||
return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -187,38 +123,40 @@ static int max8649_enable(struct regulator_dev *rdev)
|
||||
static int max8649_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD,
|
||||
return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD,
|
||||
MAX8649_EN_PD);
|
||||
}
|
||||
|
||||
static int max8649_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_CONTROL);
|
||||
if (ret < 0)
|
||||
ret = regmap_read(info->regmap, MAX8649_CONTROL, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
return !((unsigned char)ret & MAX8649_EN_PD);
|
||||
return !((unsigned char)val & MAX8649_EN_PD);
|
||||
}
|
||||
|
||||
static int max8649_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int voltage, rate, ret;
|
||||
unsigned int val;
|
||||
|
||||
/* get voltage */
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
ret = regmap_read(info->regmap, info->vol_reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret &= MAX8649_VOL_MASK;
|
||||
val &= MAX8649_VOL_MASK;
|
||||
voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */
|
||||
|
||||
/* get rate */
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_RAMP);
|
||||
if (ret < 0)
|
||||
ret = regmap_read(info->regmap, MAX8649_RAMP, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = (ret & MAX8649_RAMP_MASK) >> 5;
|
||||
ret = (val & MAX8649_RAMP_MASK) >> 5;
|
||||
rate = (32 * 1000) >> ret; /* uV/uS */
|
||||
|
||||
return DIV_ROUND_UP(voltage, rate);
|
||||
@ -230,12 +168,12 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
max8649_set_bits(info->i2c, info->vol_reg, MAX8649_FORCE_PWM,
|
||||
MAX8649_FORCE_PWM);
|
||||
regmap_update_bits(info->regmap, info->vol_reg, MAX8649_FORCE_PWM,
|
||||
MAX8649_FORCE_PWM);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
max8649_set_bits(info->i2c, info->vol_reg,
|
||||
MAX8649_FORCE_PWM, 0);
|
||||
regmap_update_bits(info->regmap, info->vol_reg,
|
||||
MAX8649_FORCE_PWM, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -246,10 +184,13 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
static unsigned int max8649_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret & MAX8649_FORCE_PWM)
|
||||
ret = regmap_read(info->regmap, info->vol_reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (val & MAX8649_FORCE_PWM)
|
||||
return REGULATOR_MODE_FAST;
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
@ -275,11 +216,17 @@ static struct regulator_desc dcdc_desc = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct regmap_config max8649_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8649_platform_data *pdata = client->dev.platform_data;
|
||||
struct max8649_regulator_info *info = NULL;
|
||||
unsigned int val;
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
@ -289,9 +236,14 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->i2c = client;
|
||||
info->regmap = regmap_init_i2c(client, &max8649_regmap_config);
|
||||
if (IS_ERR(info->regmap)) {
|
||||
ret = PTR_ERR(info->regmap);
|
||||
dev_err(&client->dev, "Failed to allocate register map: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
info->dev = &client->dev;
|
||||
mutex_init(&info->io_lock);
|
||||
i2c_set_clientdata(client, info);
|
||||
|
||||
info->mode = pdata->mode;
|
||||
@ -312,8 +264,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
break;
|
||||
}
|
||||
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_CHIP_ID1);
|
||||
if (ret < 0) {
|
||||
ret = regmap_read(info->regmap, MAX8649_CHIP_ID1, &val);
|
||||
if (ret != 0) {
|
||||
dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n",
|
||||
ret);
|
||||
goto out;
|
||||
@ -321,33 +273,33 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", ret);
|
||||
|
||||
/* enable VID0 & VID1 */
|
||||
max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_VID_MASK, 0);
|
||||
regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_VID_MASK, 0);
|
||||
|
||||
/* enable/disable external clock synchronization */
|
||||
info->extclk = pdata->extclk;
|
||||
data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0;
|
||||
max8649_set_bits(info->i2c, info->vol_reg, MAX8649_SYNC_EXTCLK, data);
|
||||
regmap_update_bits(info->regmap, info->vol_reg, MAX8649_SYNC_EXTCLK, data);
|
||||
if (info->extclk) {
|
||||
/* set external clock frequency */
|
||||
info->extclk_freq = pdata->extclk_freq;
|
||||
max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
|
||||
info->extclk_freq << 6);
|
||||
regmap_update_bits(info->regmap, MAX8649_SYNC, MAX8649_EXT_MASK,
|
||||
info->extclk_freq << 6);
|
||||
}
|
||||
|
||||
if (pdata->ramp_timing) {
|
||||
info->ramp_timing = pdata->ramp_timing;
|
||||
max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_MASK,
|
||||
info->ramp_timing << 5);
|
||||
regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_MASK,
|
||||
info->ramp_timing << 5);
|
||||
}
|
||||
|
||||
info->ramp_down = pdata->ramp_down;
|
||||
if (info->ramp_down) {
|
||||
max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_DOWN,
|
||||
MAX8649_RAMP_DOWN);
|
||||
regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_DOWN,
|
||||
MAX8649_RAMP_DOWN);
|
||||
}
|
||||
|
||||
info->regulator = regulator_register(&dcdc_desc, &client->dev,
|
||||
pdata->regulator, info);
|
||||
pdata->regulator, info, NULL);
|
||||
if (IS_ERR(info->regulator)) {
|
||||
dev_err(info->dev, "failed to register regulator %s\n",
|
||||
dcdc_desc.name);
|
||||
@ -358,6 +310,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
dev_info(info->dev, "Max8649 regulator device is detected.\n");
|
||||
return 0;
|
||||
out:
|
||||
regmap_exit(info->regmap);
|
||||
fail:
|
||||
kfree(info);
|
||||
return ret;
|
||||
}
|
||||
@ -369,6 +323,7 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
|
||||
if (info) {
|
||||
if (info->regulator)
|
||||
regulator_unregister(info->regulator);
|
||||
regmap_exit(info->regmap);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
|
@ -449,7 +449,7 @@ static int __devinit max8660_probe(struct i2c_client *client,
|
||||
|
||||
rdev[i] = regulator_register(&max8660_reg[id], &client->dev,
|
||||
pdata->subdevs[i].platform_data,
|
||||
max8660);
|
||||
max8660, NULL);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(&client->dev, "failed to register %s\n",
|
||||
|
@ -24,9 +24,13 @@
|
||||
#define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */
|
||||
#define SD1_DVM_EN 6 /* SDV1 bit 6 */
|
||||
|
||||
/* bit definitions in SD & LDO control registers */
|
||||
#define OUT_ENABLE 0x1f /* Power U/D sequence as I2C */
|
||||
#define OUT_DISABLE 0x1e /* Power U/D sequence as I2C */
|
||||
/* bit definitions in LDO control registers */
|
||||
#define LDO_SEQ_I2C 0x7 /* Power U/D by i2c */
|
||||
#define LDO_SEQ_MASK 0x7 /* Power U/D sequence mask */
|
||||
#define LDO_SEQ_SHIFT 2 /* Power U/D sequence offset */
|
||||
#define LDO_I2C_EN 0x1 /* Enable by i2c */
|
||||
#define LDO_I2C_EN_MASK 0x1 /* Enable mask by i2c */
|
||||
#define LDO_I2C_EN_SHIFT 0 /* Enable offset by i2c */
|
||||
|
||||
struct max8925_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
@ -40,7 +44,6 @@ struct max8925_regulator_info {
|
||||
int vol_reg;
|
||||
int vol_shift;
|
||||
int vol_nbits;
|
||||
int enable_bit;
|
||||
int enable_reg;
|
||||
};
|
||||
|
||||
@ -98,8 +101,10 @@ static int max8925_enable(struct regulator_dev *rdev)
|
||||
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return max8925_set_bits(info->i2c, info->enable_reg,
|
||||
OUT_ENABLE << info->enable_bit,
|
||||
OUT_ENABLE << info->enable_bit);
|
||||
LDO_SEQ_MASK << LDO_SEQ_SHIFT |
|
||||
LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT,
|
||||
LDO_SEQ_I2C << LDO_SEQ_SHIFT |
|
||||
LDO_I2C_EN << LDO_I2C_EN_SHIFT);
|
||||
}
|
||||
|
||||
static int max8925_disable(struct regulator_dev *rdev)
|
||||
@ -107,20 +112,24 @@ static int max8925_disable(struct regulator_dev *rdev)
|
||||
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return max8925_set_bits(info->i2c, info->enable_reg,
|
||||
OUT_ENABLE << info->enable_bit,
|
||||
OUT_DISABLE << info->enable_bit);
|
||||
LDO_SEQ_MASK << LDO_SEQ_SHIFT |
|
||||
LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT,
|
||||
LDO_SEQ_I2C << LDO_SEQ_SHIFT);
|
||||
}
|
||||
|
||||
static int max8925_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
int ldo_seq, ret;
|
||||
|
||||
ret = max8925_reg_read(info->i2c, info->enable_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret & (1 << info->enable_bit);
|
||||
ldo_seq = (ret >> LDO_SEQ_SHIFT) & LDO_SEQ_MASK;
|
||||
if (ldo_seq != LDO_SEQ_I2C)
|
||||
return 1;
|
||||
else
|
||||
return ret & (LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT);
|
||||
}
|
||||
|
||||
static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV)
|
||||
@ -188,7 +197,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
|
||||
.vol_shift = 0, \
|
||||
.vol_nbits = 6, \
|
||||
.enable_reg = MAX8925_SDCTL##_id, \
|
||||
.enable_bit = 0, \
|
||||
}
|
||||
|
||||
#define MAX8925_LDO(_id, min, max, step) \
|
||||
@ -207,7 +215,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
|
||||
.vol_shift = 0, \
|
||||
.vol_nbits = 6, \
|
||||
.enable_reg = MAX8925_LDOCTL##_id, \
|
||||
.enable_bit = 0, \
|
||||
}
|
||||
|
||||
static struct max8925_regulator_info max8925_regulator_info[] = {
|
||||
@ -266,7 +273,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
||||
ri->chip = chip;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &pdev->dev,
|
||||
pdata->regulator[pdev->id], ri);
|
||||
pdata->regulator[pdev->id], ri, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
|
@ -208,7 +208,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
|
||||
max8952->pdata = pdata;
|
||||
|
||||
max8952->rdev = regulator_register(®ulator, max8952->dev,
|
||||
&pdata->reg_data, max8952);
|
||||
&pdata->reg_data, max8952, NULL);
|
||||
|
||||
if (IS_ERR(max8952->rdev)) {
|
||||
ret = PTR_ERR(max8952->rdev);
|
||||
|
@ -1146,7 +1146,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
regulators[id].n_voltages = 16;
|
||||
|
||||
rdev[i] = regulator_register(®ulators[id], max8997->dev,
|
||||
pdata->regulators[i].initdata, max8997);
|
||||
pdata->regulators[i].initdata, max8997, NULL);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(max8997->dev, "regulator init failed for %d\n",
|
||||
|
@ -847,7 +847,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
|
||||
regulators[index].n_voltages = count;
|
||||
}
|
||||
rdev[i] = regulator_register(®ulators[index], max8998->dev,
|
||||
pdata->regulators[i].initdata, max8998);
|
||||
pdata->regulators[i].initdata, max8998, NULL);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(max8998->dev, "regulator init failed\n");
|
||||
|
@ -344,7 +344,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id);
|
||||
|
||||
priv = kzalloc(sizeof(*priv) +
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
|
||||
pdata->num_regulators * sizeof(priv->regulators[0]),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
@ -357,7 +357,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
||||
init_data = &pdata->regulators[i];
|
||||
priv->regulators[i] = regulator_register(
|
||||
&mc13783_regulators[init_data->id].desc,
|
||||
&pdev->dev, init_data->init_data, priv);
|
||||
&pdev->dev, init_data->init_data, priv, NULL);
|
||||
|
||||
if (IS_ERR(priv->regulators[i])) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
@ -374,8 +374,6 @@ err:
|
||||
while (--i >= 0)
|
||||
regulator_unregister(priv->regulators[i]);
|
||||
|
||||
kfree(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -391,7 +389,6 @@ static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
|
||||
for (i = 0; i < pdata->num_regulators; i++)
|
||||
regulator_unregister(priv->regulators[i]);
|
||||
|
||||
kfree(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -527,18 +527,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
|
||||
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct mc13xxx_regulator_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
struct mc13xxx_regulator_init_data *init_data;
|
||||
struct mc13xxx_regulator_init_data *mc13xxx_data;
|
||||
int i, ret;
|
||||
int num_regulators = 0;
|
||||
u32 val;
|
||||
|
||||
priv = kzalloc(sizeof(*priv) +
|
||||
pdata->num_regulators * sizeof(priv->regulators[0]),
|
||||
num_regulators = mc13xxx_get_num_regulators_dt(pdev);
|
||||
if (num_regulators <= 0 && pdata)
|
||||
num_regulators = pdata->num_regulators;
|
||||
if (num_regulators <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
|
||||
num_regulators * sizeof(priv->regulators[0]),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->num_regulators = num_regulators;
|
||||
priv->mc13xxx_regulators = mc13892_regulators;
|
||||
priv->mc13xxx = mc13892;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
mc13xxx_lock(mc13892);
|
||||
ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
|
||||
@ -569,11 +578,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
|
||||
= mc13892_vcam_set_mode;
|
||||
mc13892_regulators[MC13892_VCAM].desc.ops->get_mode
|
||||
= mc13892_vcam_get_mode;
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
init_data = &pdata->regulators[i];
|
||||
|
||||
mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators,
|
||||
ARRAY_SIZE(mc13892_regulators));
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
struct regulator_init_data *init_data;
|
||||
struct regulator_desc *desc;
|
||||
struct device_node *node = NULL;
|
||||
int id;
|
||||
|
||||
if (mc13xxx_data) {
|
||||
id = mc13xxx_data[i].id;
|
||||
init_data = mc13xxx_data[i].init_data;
|
||||
node = mc13xxx_data[i].node;
|
||||
} else {
|
||||
id = pdata->regulators[i].id;
|
||||
init_data = pdata->regulators[i].init_data;
|
||||
}
|
||||
desc = &mc13892_regulators[id].desc;
|
||||
|
||||
priv->regulators[i] = regulator_register(
|
||||
&mc13892_regulators[init_data->id].desc,
|
||||
&pdev->dev, init_data->init_data, priv);
|
||||
desc, &pdev->dev, init_data, priv, node);
|
||||
|
||||
if (IS_ERR(priv->regulators[i])) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
@ -583,8 +608,6 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
while (--i >= 0)
|
||||
@ -592,7 +615,6 @@ err:
|
||||
|
||||
err_free:
|
||||
mc13xxx_unlock(mc13892);
|
||||
kfree(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -600,16 +622,13 @@ err_free:
|
||||
static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
|
||||
struct mc13xxx_regulator_platform_data *pdata =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
int i;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
for (i = 0; i < pdata->num_regulators; i++)
|
||||
for (i = 0; i < priv->num_regulators; i++)
|
||||
regulator_unregister(priv->regulators[i]);
|
||||
|
||||
kfree(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,14 @@
|
||||
#include <linux/mfd/mc13xxx.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include "mc13xxx.h"
|
||||
|
||||
static int mc13xxx_regulator_enable(struct regulator_dev *rdev)
|
||||
@ -236,6 +238,61 @@ int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *parent, *child;
|
||||
int num = 0;
|
||||
|
||||
of_node_get(pdev->dev.parent->of_node);
|
||||
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
|
||||
if (!parent)
|
||||
return -ENODEV;
|
||||
|
||||
for_each_child_of_node(parent, child)
|
||||
num++;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
|
||||
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
|
||||
int num_regulators)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
|
||||
struct mc13xxx_regulator_init_data *data, *p;
|
||||
struct device_node *parent, *child;
|
||||
int i;
|
||||
|
||||
of_node_get(pdev->dev.parent->of_node);
|
||||
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
p = data;
|
||||
|
||||
for_each_child_of_node(parent, child) {
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
if (!of_node_cmp(child->name,
|
||||
regulators[i].desc.name)) {
|
||||
p->id = i;
|
||||
p->init_data = of_get_regulator_init_data(
|
||||
&pdev->dev, child);
|
||||
p->node = child;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
|
||||
MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC");
|
||||
|
@ -29,6 +29,7 @@ struct mc13xxx_regulator_priv {
|
||||
struct mc13xxx *mc13xxx;
|
||||
u32 powermisc_pwgt_state;
|
||||
struct mc13xxx_regulator *mc13xxx_regulators;
|
||||
int num_regulators;
|
||||
struct regulator_dev *regulators[];
|
||||
};
|
||||
|
||||
@ -42,13 +43,32 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector);
|
||||
extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev);
|
||||
extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
|
||||
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
|
||||
int num_regulators);
|
||||
#else
|
||||
static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
|
||||
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
|
||||
int num_regulators)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern struct regulator_ops mc13xxx_regulator_ops;
|
||||
extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
|
||||
#define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \
|
||||
[prefix ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
@ -66,7 +86,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \
|
||||
[prefix ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
@ -81,7 +101,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \
|
||||
[prefix ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
87
drivers/regulator/of_regulator.c
Normal file
87
drivers/regulator/of_regulator.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* OF helpers for regulator framework
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
||||
* Rajendra Nayak <rnayak@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
static void of_get_regulation_constraints(struct device_node *np,
|
||||
struct regulator_init_data **init_data)
|
||||
{
|
||||
const __be32 *min_uV, *max_uV, *uV_offset;
|
||||
const __be32 *min_uA, *max_uA;
|
||||
struct regulation_constraints *constraints = &(*init_data)->constraints;
|
||||
|
||||
constraints->name = of_get_property(np, "regulator-name", NULL);
|
||||
|
||||
min_uV = of_get_property(np, "regulator-min-microvolt", NULL);
|
||||
if (min_uV)
|
||||
constraints->min_uV = be32_to_cpu(*min_uV);
|
||||
max_uV = of_get_property(np, "regulator-max-microvolt", NULL);
|
||||
if (max_uV)
|
||||
constraints->max_uV = be32_to_cpu(*max_uV);
|
||||
|
||||
/* Voltage change possible? */
|
||||
if (constraints->min_uV != constraints->max_uV)
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
|
||||
/* Only one voltage? Then make sure it's set. */
|
||||
if (constraints->min_uV == constraints->max_uV)
|
||||
constraints->apply_uV = true;
|
||||
|
||||
uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL);
|
||||
if (uV_offset)
|
||||
constraints->uV_offset = be32_to_cpu(*uV_offset);
|
||||
min_uA = of_get_property(np, "regulator-min-microamp", NULL);
|
||||
if (min_uA)
|
||||
constraints->min_uA = be32_to_cpu(*min_uA);
|
||||
max_uA = of_get_property(np, "regulator-max-microamp", NULL);
|
||||
if (max_uA)
|
||||
constraints->max_uA = be32_to_cpu(*max_uA);
|
||||
|
||||
/* Current change possible? */
|
||||
if (constraints->min_uA != constraints->max_uA)
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
|
||||
|
||||
if (of_find_property(np, "regulator-boot-on", NULL))
|
||||
constraints->boot_on = true;
|
||||
|
||||
if (of_find_property(np, "regulator-always-on", NULL))
|
||||
constraints->always_on = true;
|
||||
else /* status change should be possible if not always on. */
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_get_regulator_init_data - extract regulator_init_data structure info
|
||||
* @dev: device requesting for regulator_init_data
|
||||
*
|
||||
* 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 regulator_init_data *init_data;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
|
||||
if (!init_data)
|
||||
return NULL; /* Out of memory? */
|
||||
|
||||
of_get_regulation_constraints(node, &init_data);
|
||||
return init_data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
|
@ -277,7 +277,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
|
||||
void *pcap = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev,
|
||||
pdev->dev.platform_data, pcap);
|
||||
pdev->dev.platform_data, pcap, NULL);
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
|
@ -320,7 +320,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
|
||||
pcf = dev_to_pcf50633(pdev->dev.parent);
|
||||
|
||||
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
||||
pdev->dev.platform_data, pcf);
|
||||
pdev->dev.platform_data, pcf, NULL);
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
|
@ -151,7 +151,8 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
|
||||
/* Register regulator with framework */
|
||||
tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
|
||||
&tps6105x->client->dev,
|
||||
pdata->regulator_data, tps6105x);
|
||||
pdata->regulator_data, tps6105x,
|
||||
NULL);
|
||||
if (IS_ERR(tps6105x->regulator)) {
|
||||
ret = PTR_ERR(tps6105x->regulator);
|
||||
dev_err(&tps6105x->client->dev,
|
||||
|
@ -152,48 +152,21 @@ struct tps_driver_data {
|
||||
u8 core_regulator;
|
||||
};
|
||||
|
||||
static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
|
||||
{
|
||||
return regmap_update_bits(tps->regmap, reg, mask, mask);
|
||||
}
|
||||
|
||||
static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask)
|
||||
{
|
||||
return regmap_update_bits(tps->regmap, reg, mask, 0);
|
||||
}
|
||||
|
||||
static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(tps->regmap, reg, &val);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val)
|
||||
{
|
||||
return regmap_write(tps->regmap, reg, val);
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int data, dcdc = rdev_get_id(dev);
|
||||
int ret;
|
||||
u8 shift;
|
||||
|
||||
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
|
||||
return -EINVAL;
|
||||
|
||||
shift = TPS65023_NUM_REGULATOR - dcdc;
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data);
|
||||
|
||||
if (data < 0)
|
||||
return data;
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
else
|
||||
return (data & 1<<shift) ? 1 : 0;
|
||||
}
|
||||
@ -202,16 +175,17 @@ static int tps65023_ldo_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int data, ldo = rdev_get_id(dev);
|
||||
int ret;
|
||||
u8 shift;
|
||||
|
||||
if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data);
|
||||
|
||||
if (data < 0)
|
||||
return data;
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
else
|
||||
return (data & 1<<shift) ? 1 : 0;
|
||||
}
|
||||
@ -226,7 +200,7 @@ static int tps65023_dcdc_enable(struct regulator_dev *dev)
|
||||
return -EINVAL;
|
||||
|
||||
shift = TPS65023_NUM_REGULATOR - dcdc;
|
||||
return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
|
||||
return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift);
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_disable(struct regulator_dev *dev)
|
||||
@ -239,7 +213,7 @@ static int tps65023_dcdc_disable(struct regulator_dev *dev)
|
||||
return -EINVAL;
|
||||
|
||||
shift = TPS65023_NUM_REGULATOR - dcdc;
|
||||
return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
|
||||
return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0);
|
||||
}
|
||||
|
||||
static int tps65023_ldo_enable(struct regulator_dev *dev)
|
||||
@ -252,7 +226,7 @@ static int tps65023_ldo_enable(struct regulator_dev *dev)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
|
||||
return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
|
||||
return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift);
|
||||
}
|
||||
|
||||
static int tps65023_ldo_disable(struct regulator_dev *dev)
|
||||
@ -265,21 +239,22 @@ static int tps65023_ldo_disable(struct regulator_dev *dev)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
|
||||
return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
|
||||
return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0);
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int ret;
|
||||
int data, dcdc = rdev_get_id(dev);
|
||||
|
||||
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
|
||||
return -EINVAL;
|
||||
|
||||
if (dcdc == tps->core_regulator) {
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE);
|
||||
if (data < 0)
|
||||
return data;
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_DEF_CORE, &data);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
data &= (tps->info[dcdc]->table_len - 1);
|
||||
return tps->info[dcdc]->table[data] * 1000;
|
||||
} else
|
||||
@ -318,13 +293,13 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
|
||||
if (vsel == tps->info[dcdc]->table_len)
|
||||
goto failed;
|
||||
|
||||
ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
|
||||
ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, vsel);
|
||||
|
||||
/* Tell the chip that we have changed the value in DEFCORE
|
||||
* and its time to update the core voltage
|
||||
*/
|
||||
tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_GO);
|
||||
regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO);
|
||||
|
||||
return ret;
|
||||
|
||||
@ -336,13 +311,14 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int data, ldo = rdev_get_id(dev);
|
||||
int ret;
|
||||
|
||||
if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
|
||||
return -EINVAL;
|
||||
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
|
||||
if (data < 0)
|
||||
return data;
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
|
||||
data &= (tps->info[ldo]->table_len - 1);
|
||||
@ -354,6 +330,7 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int data, vsel, ldo = rdev_get_id(dev);
|
||||
int ret;
|
||||
|
||||
if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
|
||||
return -EINVAL;
|
||||
@ -377,13 +354,13 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
|
||||
if (data < 0)
|
||||
return data;
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1);
|
||||
data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)));
|
||||
return tps_65023_reg_write(tps, TPS65023_REG_LDO_CTRL, data);
|
||||
return regmap_write(tps->regmap, TPS65023_REG_LDO_CTRL, data);
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
|
||||
@ -496,7 +473,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
|
||||
/* Register the regulators */
|
||||
rdev = regulator_register(&tps->desc[i], &client->dev,
|
||||
init_data, tps);
|
||||
init_data, tps, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&client->dev, "failed to register %s\n",
|
||||
id->name);
|
||||
@ -511,12 +488,12 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
i2c_set_clientdata(client, tps);
|
||||
|
||||
/* Enable setting output voltage by I2C */
|
||||
tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_CORE_ADJ);
|
||||
regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ);
|
||||
|
||||
/* Enable setting output voltage by I2C */
|
||||
tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_CORE_ADJ);
|
||||
regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
|
||||
TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -599,7 +599,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
|
||||
tps->desc[i].owner = THIS_MODULE;
|
||||
|
||||
rdev = regulator_register(&tps->desc[i],
|
||||
tps6507x_dev->dev, init_data, tps);
|
||||
tps6507x_dev->dev, init_data, tps, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(tps6507x_dev->dev,
|
||||
"failed to register %s regulator\n",
|
||||
|
@ -651,7 +651,7 @@ static int __devinit pmic_probe(struct spi_device *spi)
|
||||
hw->desc[i].n_voltages = 1;
|
||||
|
||||
hw->rdev[i] = regulator_register(&hw->desc[i], dev,
|
||||
init_data, hw);
|
||||
init_data, hw, NULL);
|
||||
if (IS_ERR(hw->rdev[i])) {
|
||||
ret = PTR_ERR(hw->rdev[i]);
|
||||
hw->rdev[i] = NULL;
|
||||
|
@ -396,7 +396,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &pdev->dev,
|
||||
pdev->dev.platform_data, ri);
|
||||
pdev->dev.platform_data, ri, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
|
@ -25,30 +25,6 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/mfd/tps65910.h>
|
||||
|
||||
#define TPS65910_REG_VRTC 0
|
||||
#define TPS65910_REG_VIO 1
|
||||
#define TPS65910_REG_VDD1 2
|
||||
#define TPS65910_REG_VDD2 3
|
||||
#define TPS65910_REG_VDD3 4
|
||||
#define TPS65910_REG_VDIG1 5
|
||||
#define TPS65910_REG_VDIG2 6
|
||||
#define TPS65910_REG_VPLL 7
|
||||
#define TPS65910_REG_VDAC 8
|
||||
#define TPS65910_REG_VAUX1 9
|
||||
#define TPS65910_REG_VAUX2 10
|
||||
#define TPS65910_REG_VAUX33 11
|
||||
#define TPS65910_REG_VMMC 12
|
||||
|
||||
#define TPS65911_REG_VDDCTRL 4
|
||||
#define TPS65911_REG_LDO1 5
|
||||
#define TPS65911_REG_LDO2 6
|
||||
#define TPS65911_REG_LDO3 7
|
||||
#define TPS65911_REG_LDO4 8
|
||||
#define TPS65911_REG_LDO5 9
|
||||
#define TPS65911_REG_LDO6 10
|
||||
#define TPS65911_REG_LDO7 11
|
||||
#define TPS65911_REG_LDO8 12
|
||||
|
||||
#define TPS65910_SUPPLY_STATE_ENABLED 0x1
|
||||
|
||||
/* supported VIO voltages in milivolts */
|
||||
@ -885,8 +861,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
if (!pmic_plat_data)
|
||||
return -EINVAL;
|
||||
|
||||
reg_data = pmic_plat_data->tps65910_pmic_init_data;
|
||||
|
||||
pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
|
||||
if (!pmic)
|
||||
return -ENOMEM;
|
||||
@ -937,7 +911,16 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
goto err_free_info;
|
||||
}
|
||||
|
||||
for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) {
|
||||
for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS;
|
||||
i++, info++) {
|
||||
|
||||
reg_data = pmic_plat_data->tps65910_pmic_init_data[i];
|
||||
|
||||
/* Regulator API handles empty constraints but not NULL
|
||||
* constraints */
|
||||
if (!reg_data)
|
||||
continue;
|
||||
|
||||
/* Register the regulators */
|
||||
pmic->info[i] = info;
|
||||
|
||||
@ -965,7 +948,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
pmic->desc[i].owner = THIS_MODULE;
|
||||
|
||||
rdev = regulator_register(&pmic->desc[i],
|
||||
tps65910->dev, reg_data, pmic);
|
||||
tps65910->dev, reg_data, pmic, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(tps65910->dev,
|
||||
"failed to register %s regulator\n",
|
||||
|
@ -727,7 +727,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev)
|
||||
pmic->desc[i].owner = THIS_MODULE;
|
||||
range = tps65912_get_range(pmic, i);
|
||||
rdev = regulator_register(&pmic->desc[i],
|
||||
tps65912->dev, reg_data, pmic);
|
||||
tps65912->dev, reg_data, pmic, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(tps65912->dev,
|
||||
"failed to register %s regulator\n",
|
||||
|
@ -1112,7 +1112,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
|
||||
rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "can't register %s, %ld\n",
|
||||
info->desc.name, PTR_ERR(rdev));
|
||||
|
@ -185,18 +185,7 @@ static struct platform_driver regulator_userspace_consumer_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int __init regulator_userspace_consumer_init(void)
|
||||
{
|
||||
return platform_driver_register(®ulator_userspace_consumer_driver);
|
||||
}
|
||||
module_init(regulator_userspace_consumer_init);
|
||||
|
||||
static void __exit regulator_userspace_consumer_exit(void)
|
||||
{
|
||||
platform_driver_unregister(®ulator_userspace_consumer_driver);
|
||||
}
|
||||
module_exit(regulator_userspace_consumer_exit);
|
||||
module_platform_driver(regulator_userspace_consumer_driver);
|
||||
|
||||
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
|
||||
MODULE_DESCRIPTION("Userspace consumer for voltage and current regulators");
|
||||
|
@ -352,17 +352,7 @@ static struct platform_driver regulator_virtual_consumer_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init regulator_virtual_consumer_init(void)
|
||||
{
|
||||
return platform_driver_register(®ulator_virtual_consumer_driver);
|
||||
}
|
||||
module_init(regulator_virtual_consumer_init);
|
||||
|
||||
static void __exit regulator_virtual_consumer_exit(void)
|
||||
{
|
||||
platform_driver_unregister(®ulator_virtual_consumer_driver);
|
||||
}
|
||||
module_exit(regulator_virtual_consumer_exit);
|
||||
module_platform_driver(regulator_virtual_consumer_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("Virtual regulator consumer");
|
||||
|
@ -511,7 +511,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->dcdc[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL);
|
||||
dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
|
||||
GFP_KERNEL);
|
||||
if (dcdc == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -553,7 +554,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
|
||||
|
||||
dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
|
||||
pdata->dcdc[id], dcdc);
|
||||
pdata->dcdc[id], dcdc, NULL);
|
||||
if (IS_ERR(dcdc->regulator)) {
|
||||
ret = PTR_ERR(dcdc->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
|
||||
@ -590,7 +591,6 @@ err_regulator:
|
||||
err:
|
||||
if (dcdc->dvs_gpio)
|
||||
gpio_free(dcdc->dvs_gpio);
|
||||
kfree(dcdc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -605,7 +605,6 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
|
||||
regulator_unregister(dcdc->regulator);
|
||||
if (dcdc->dvs_gpio)
|
||||
gpio_free(dcdc->dvs_gpio);
|
||||
kfree(dcdc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -722,7 +721,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->dcdc[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL);
|
||||
dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
|
||||
GFP_KERNEL);
|
||||
if (dcdc == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -747,7 +747,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
dcdc->desc.owner = THIS_MODULE;
|
||||
|
||||
dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
|
||||
pdata->dcdc[id], dcdc);
|
||||
pdata->dcdc[id], dcdc, NULL);
|
||||
if (IS_ERR(dcdc->regulator)) {
|
||||
ret = PTR_ERR(dcdc->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
|
||||
@ -771,7 +771,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
err_regulator:
|
||||
regulator_unregister(dcdc->regulator);
|
||||
err:
|
||||
kfree(dcdc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -783,7 +782,6 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
|
||||
regulator_unregister(dcdc->regulator);
|
||||
kfree(dcdc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -874,7 +872,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
|
||||
dcdc->desc.owner = THIS_MODULE;
|
||||
|
||||
dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
|
||||
pdata->dcdc[id], dcdc);
|
||||
pdata->dcdc[id], dcdc, NULL);
|
||||
if (IS_ERR(dcdc->regulator)) {
|
||||
ret = PTR_ERR(dcdc->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
|
||||
@ -973,7 +971,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev)
|
||||
dcdc->desc.owner = THIS_MODULE;
|
||||
|
||||
dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
|
||||
pdata->epe[id], dcdc);
|
||||
pdata->epe[id], dcdc, NULL);
|
||||
if (IS_ERR(dcdc->regulator)) {
|
||||
ret = PTR_ERR(dcdc->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
|
||||
|
@ -162,7 +162,8 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->isink[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
isink = kzalloc(sizeof(struct wm831x_isink), GFP_KERNEL);
|
||||
isink = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_isink),
|
||||
GFP_KERNEL);
|
||||
if (isink == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -189,7 +190,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
||||
isink->desc.owner = THIS_MODULE;
|
||||
|
||||
isink->regulator = regulator_register(&isink->desc, &pdev->dev,
|
||||
pdata->isink[id], isink);
|
||||
pdata->isink[id], isink, NULL);
|
||||
if (IS_ERR(isink->regulator)) {
|
||||
ret = PTR_ERR(isink->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
|
||||
@ -213,7 +214,6 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
||||
err_regulator:
|
||||
regulator_unregister(isink->regulator);
|
||||
err:
|
||||
kfree(isink);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -226,7 +226,6 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
|
||||
free_irq(platform_get_irq(pdev, 0), isink);
|
||||
|
||||
regulator_unregister(isink->regulator);
|
||||
kfree(isink);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
if (ldo == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -351,7 +351,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.owner = THIS_MODULE;
|
||||
|
||||
ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
|
||||
pdata->ldo[id], ldo);
|
||||
pdata->ldo[id], ldo, NULL);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
|
||||
@ -376,7 +376,6 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
err_regulator:
|
||||
regulator_unregister(ldo->regulator);
|
||||
err:
|
||||
kfree(ldo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -388,7 +387,6 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
|
||||
regulator_unregister(ldo->regulator);
|
||||
kfree(ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -596,7 +594,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
if (ldo == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -621,7 +619,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.owner = THIS_MODULE;
|
||||
|
||||
ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
|
||||
pdata->ldo[id], ldo);
|
||||
pdata->ldo[id], ldo, NULL);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
|
||||
@ -645,7 +643,6 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
err_regulator:
|
||||
regulator_unregister(ldo->regulator);
|
||||
err:
|
||||
kfree(ldo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -655,7 +652,6 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
|
||||
regulator_unregister(ldo->regulator);
|
||||
kfree(ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -793,7 +789,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);
|
||||
if (ldo == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
@ -818,7 +814,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.owner = THIS_MODULE;
|
||||
|
||||
ldo->regulator = regulator_register(&ldo->desc, &pdev->dev,
|
||||
pdata->ldo[id], ldo);
|
||||
pdata->ldo[id], ldo, NULL);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
|
||||
@ -831,7 +827,6 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(ldo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -840,7 +835,6 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
|
||||
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(ldo->regulator);
|
||||
kfree(ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1428,7 +1428,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
|
||||
/* register regulator */
|
||||
rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
|
||||
pdev->dev.platform_data,
|
||||
dev_get_drvdata(&pdev->dev));
|
||||
dev_get_drvdata(&pdev->dev), NULL);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register %s\n",
|
||||
wm8350_reg[pdev->id].name);
|
||||
|
@ -326,7 +326,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
||||
pdev->dev.platform_data, wm8400);
|
||||
pdev->dev.platform_data, wm8400, NULL);
|
||||
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
@ -269,7 +269,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
ldo->is_enabled = true;
|
||||
|
||||
ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev,
|
||||
pdata->ldo[id].init_data, ldo);
|
||||
pdata->ldo[id].init_data, ldo, NULL);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
|
||||
|
@ -69,6 +69,7 @@ struct regulator_init_data;
|
||||
struct mc13xxx_regulator_init_data {
|
||||
int id;
|
||||
struct regulator_init_data *init_data;
|
||||
struct device_node *node;
|
||||
};
|
||||
|
||||
struct mc13xxx_regulator_platform_data {
|
||||
|
@ -740,6 +740,34 @@
|
||||
#define TPS65910_GPIO_STS BIT(1)
|
||||
#define TPS65910_GPIO_SET BIT(0)
|
||||
|
||||
/* Regulator Index Definitions */
|
||||
#define TPS65910_REG_VRTC 0
|
||||
#define TPS65910_REG_VIO 1
|
||||
#define TPS65910_REG_VDD1 2
|
||||
#define TPS65910_REG_VDD2 3
|
||||
#define TPS65910_REG_VDD3 4
|
||||
#define TPS65910_REG_VDIG1 5
|
||||
#define TPS65910_REG_VDIG2 6
|
||||
#define TPS65910_REG_VPLL 7
|
||||
#define TPS65910_REG_VDAC 8
|
||||
#define TPS65910_REG_VAUX1 9
|
||||
#define TPS65910_REG_VAUX2 10
|
||||
#define TPS65910_REG_VAUX33 11
|
||||
#define TPS65910_REG_VMMC 12
|
||||
|
||||
#define TPS65911_REG_VDDCTRL 4
|
||||
#define TPS65911_REG_LDO1 5
|
||||
#define TPS65911_REG_LDO2 6
|
||||
#define TPS65911_REG_LDO3 7
|
||||
#define TPS65911_REG_LDO4 8
|
||||
#define TPS65911_REG_LDO5 9
|
||||
#define TPS65911_REG_LDO6 10
|
||||
#define TPS65911_REG_LDO7 11
|
||||
#define TPS65911_REG_LDO8 12
|
||||
|
||||
/* Max number of TPS65910/11 regulators */
|
||||
#define TPS65910_NUM_REGS 13
|
||||
|
||||
/**
|
||||
* struct tps65910_board
|
||||
* Board platform data may be used to initialize regulators.
|
||||
@ -751,7 +779,7 @@ struct tps65910_board {
|
||||
int irq_base;
|
||||
int vmbch_threshold;
|
||||
int vmbch2_threshold;
|
||||
struct regulator_init_data *tps65910_pmic_init_data;
|
||||
struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -149,6 +149,8 @@ int regulator_bulk_enable(int num_consumers,
|
||||
struct regulator_bulk_data *consumers);
|
||||
int regulator_bulk_disable(int num_consumers,
|
||||
struct regulator_bulk_data *consumers);
|
||||
int regulator_bulk_force_disable(int num_consumers,
|
||||
struct regulator_bulk_data *consumers);
|
||||
void regulator_bulk_free(int num_consumers,
|
||||
struct regulator_bulk_data *consumers);
|
||||
|
||||
@ -212,6 +214,11 @@ static inline int regulator_disable(struct regulator *regulator)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int regulator_force_disable(struct regulator *regulator)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int regulator_disable_deferred(struct regulator *regulator,
|
||||
int ms)
|
||||
{
|
||||
@ -242,6 +249,12 @@ static inline int regulator_bulk_disable(int num_consumers,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int regulator_bulk_force_disable(int num_consumers,
|
||||
struct regulator_bulk_data *consumers)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void regulator_bulk_free(int num_consumers,
|
||||
struct regulator_bulk_data *consumers)
|
||||
{
|
||||
|
@ -154,6 +154,7 @@ enum regulator_type {
|
||||
* this type.
|
||||
*
|
||||
* @name: Identifying name for the regulator.
|
||||
* @supply_name: Identifying the regulator supply
|
||||
* @id: Numerical identifier for the regulator.
|
||||
* @n_voltages: Number of selectors available for ops.list_voltage().
|
||||
* @ops: Regulator operations table.
|
||||
@ -163,6 +164,7 @@ enum regulator_type {
|
||||
*/
|
||||
struct regulator_desc {
|
||||
const char *name;
|
||||
const char *supply_name;
|
||||
int id;
|
||||
unsigned n_voltages;
|
||||
struct regulator_ops *ops;
|
||||
@ -212,7 +214,7 @@ struct regulator_dev {
|
||||
|
||||
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||
struct device *dev, const struct regulator_init_data *init_data,
|
||||
void *driver_data);
|
||||
void *driver_data, struct device_node *of_node);
|
||||
void regulator_unregister(struct regulator_dev *rdev);
|
||||
|
||||
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
||||
|
22
include/linux/regulator/of_regulator.h
Normal file
22
include/linux/regulator/of_regulator.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* OpenFirmware regulator support routines
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_OF_REG_H
|
||||
#define __LINUX_OF_REG_H
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
extern struct regulator_init_data
|
||||
*of_get_regulator_init_data(struct device *dev,
|
||||
struct device_node *node);
|
||||
#else
|
||||
static inline struct regulator_init_data
|
||||
*of_get_regulator_init_data(struct device *dev,
|
||||
struct device_node *node)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#endif /* __LINUX_OF_REG_H */
|
@ -833,7 +833,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
|
||||
ldo->voltage = voltage;
|
||||
|
||||
ldo->dev = regulator_register(&ldo->desc, codec->dev,
|
||||
init_data, ldo);
|
||||
init_data, ldo, NULL);
|
||||
if (IS_ERR(ldo->dev)) {
|
||||
int ret = PTR_ERR(ldo->dev);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user