Commit 8735bc2f authored by Linus Walleij's avatar Linus Walleij Committed by Mark Brown

regulator: ab3100: device tree support

This implements device tree support for the AB3100 regulators
driver. The initial settings are moved out of platform data
and into the driver for the device tree case, as it appears
that there is no way to supply this as AUXDATA for an I2C
device. The style and bindings are heavily inspired by
Lee Jones' style for AB8500.
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 9b318353
...@@ -753,6 +753,7 @@ static struct mfd_cell ab3100_devs[] = { ...@@ -753,6 +753,7 @@ static struct mfd_cell ab3100_devs[] = {
}, },
{ {
.name = "ab3100-regulators", .name = "ab3100-regulators",
.of_compatible = "stericsson,ab3100-regulators",
.id = -1, .id = -1,
}, },
{ {
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/mfd/ab3100.h> #include <linux/mfd/ab3100.h>
#include <linux/mfd/abx500.h> #include <linux/mfd/abx500.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>
/* LDO registers and some handy masking definitions for AB3100 */ /* LDO registers and some handy masking definitions for AB3100 */
#define AB3100_LDO_A 0x40 #define AB3100_LDO_A 0x40
...@@ -345,7 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) ...@@ -345,7 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
{ {
struct ab3100_regulator *abreg = rdev_get_drvdata(reg); struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
return abreg->plfdata->external_voltage; if (abreg->plfdata)
return abreg->plfdata->external_voltage;
else
/* TODO: encode external voltage into device tree */
return 0;
} }
static struct regulator_ops regulator_ops_fixed = { static struct regulator_ops regulator_ops_fixed = {
...@@ -490,6 +496,8 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { ...@@ -490,6 +496,8 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
static int ab3100_regulator_register(struct platform_device *pdev, static int ab3100_regulator_register(struct platform_device *pdev,
struct ab3100_platform_data *plfdata, struct ab3100_platform_data *plfdata,
struct regulator_init_data *init_data,
struct device_node *np,
int id) int id)
{ {
struct regulator_desc *desc; struct regulator_desc *desc;
...@@ -518,9 +526,11 @@ static int ab3100_regulator_register(struct platform_device *pdev, ...@@ -518,9 +526,11 @@ static int ab3100_regulator_register(struct platform_device *pdev,
*/ */
reg->dev = &pdev->dev; reg->dev = &pdev->dev;
if (plfdata) { if (plfdata) {
/* This will be replaced by device tree data */
reg->plfdata = plfdata; reg->plfdata = plfdata;
config.init_data = &plfdata->reg_constraints[i]; config.init_data = &plfdata->reg_constraints[i];
} else if (np) {
config.of_node = np;
config.init_data = init_data;
} }
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.driver_data = reg; config.driver_data = reg;
...@@ -540,15 +550,103 @@ static int ab3100_regulator_register(struct platform_device *pdev, ...@@ -540,15 +550,103 @@ static int ab3100_regulator_register(struct platform_device *pdev,
return 0; return 0;
} }
static struct of_regulator_match ab3100_regulator_matches[] = {
{ .name = "ab3100_ldo_a", .driver_data = (void *) AB3100_LDO_A, },
{ .name = "ab3100_ldo_c", .driver_data = (void *) AB3100_LDO_C, },
{ .name = "ab3100_ldo_d", .driver_data = (void *) AB3100_LDO_D, },
{ .name = "ab3100_ldo_e", .driver_data = (void *) AB3100_LDO_E, },
{ .name = "ab3100_ldo_f", .driver_data = (void *) AB3100_LDO_F },
{ .name = "ab3100_ldo_g", .driver_data = (void *) AB3100_LDO_G },
{ .name = "ab3100_ldo_h", .driver_data = (void *) AB3100_LDO_H },
{ .name = "ab3100_ldo_k", .driver_data = (void *) AB3100_LDO_K },
{ .name = "ab3100_ext", .driver_data = (void *) AB3100_LDO_EXT },
{ .name = "ab3100_buck", .driver_data = (void *) AB3100_BUCK },
};
/* /*
* NOTE: the following functions are regulators pluralis - it is the * Initial settings of ab3100 registers.
* binding to the AB3100 core driver and the parent platform device * Common for below LDO regulator settings are that
* for all the different regulators. * bit 7-5 controls voltage. Bit 4 turns regulator ON(1) or OFF(0).
* Bit 3-2 controls sleep enable and bit 1-0 controls sleep mode.
*/ */
/* LDO_A 0x16: 2.75V, ON, SLEEP_A, SLEEP OFF GND */
#define LDO_A_SETTING 0x16
/* LDO_C 0x10: 2.65V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_C_SETTING 0x10
/* LDO_D 0x10: 2.65V, ON, sleep mode not used */
#define LDO_D_SETTING 0x10
/* LDO_E 0x10: 1.8V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_E_SETTING 0x10
/* LDO_E SLEEP 0x00: 1.8V, not used, SLEEP_A or B, not used */
#define LDO_E_SLEEP_SETTING 0x00
/* LDO_F 0xD0: 2.5V, ON, SLEEP_A or B, SLEEP full power */
#define LDO_F_SETTING 0xD0
/* LDO_G 0x00: 2.85V, OFF, SLEEP_A or B, SLEEP full power */
#define LDO_G_SETTING 0x00
/* LDO_H 0x18: 2.75V, ON, SLEEP_B, SLEEP full power */
#define LDO_H_SETTING 0x18
/* LDO_K 0x00: 2.75V, OFF, SLEEP_A or B, SLEEP full power */
#define LDO_K_SETTING 0x00
/* LDO_EXT 0x00: Voltage not set, OFF, not used, not used */
#define LDO_EXT_SETTING 0x00
/* BUCK 0x7D: 1.2V, ON, SLEEP_A and B, SLEEP low power */
#define BUCK_SETTING 0x7D
/* BUCK SLEEP 0xAC: 1.05V, Not used, SLEEP_A and B, Not used */
#define BUCK_SLEEP_SETTING 0xAC
static const u8 ab3100_reg_initvals[] = {
LDO_A_SETTING,
LDO_C_SETTING,
LDO_E_SETTING,
LDO_E_SLEEP_SETTING,
LDO_F_SETTING,
LDO_G_SETTING,
LDO_H_SETTING,
LDO_K_SETTING,
LDO_EXT_SETTING,
BUCK_SETTING,
BUCK_SLEEP_SETTING,
LDO_D_SETTING,
};
static int
ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
{
int err, i;
/*
* Set up the regulator registers, as was previously done with
* platform data.
*/
/* Set up regulators */
for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
err = abx500_set_register_interruptible(&pdev->dev, 0,
ab3100_reg_init_order[i],
ab3100_reg_initvals[i]);
if (err) {
dev_err(&pdev->dev, "regulator initialization failed with error %d\n",
err);
return err;
}
}
for (i = 0; i < ARRAY_SIZE(ab3100_regulator_matches); i++) {
err = ab3100_regulator_register(
pdev, NULL, ab3100_regulator_matches[i].init_data,
ab3100_regulator_matches[i].of_node,
(int) ab3100_regulator_matches[i].driver_data);
if (err)
return err;
}
return 0;
}
static int ab3100_regulators_probe(struct platform_device *pdev) static int ab3100_regulators_probe(struct platform_device *pdev)
{ {
struct ab3100_platform_data *plfdata = pdev->dev.platform_data; struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
int err = 0; int err = 0;
u8 data; u8 data;
int i; int i;
...@@ -567,6 +665,18 @@ static int ab3100_regulators_probe(struct platform_device *pdev) ...@@ -567,6 +665,18 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
dev_notice(&pdev->dev, dev_notice(&pdev->dev,
"chip is in inactive mode (Cold start)\n"); "chip is in inactive mode (Cold start)\n");
if (np) {
err = of_regulator_match(&pdev->dev, np,
ab3100_regulator_matches,
ARRAY_SIZE(ab3100_regulator_matches));
if (err < 0) {
dev_err(&pdev->dev,
"Error parsing regulator init data: %d\n", err);
return err;
}
return ab3100_regulator_of_probe(pdev, np);
}
/* Set up regulators */ /* Set up regulators */
for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
err = abx500_set_register_interruptible(&pdev->dev, 0, err = abx500_set_register_interruptible(&pdev->dev, 0,
...@@ -583,7 +693,8 @@ static int ab3100_regulators_probe(struct platform_device *pdev) ...@@ -583,7 +693,8 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
for (i = 0; i < AB3100_NUM_REGULATORS; i++) { for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
struct regulator_desc *desc = &ab3100_regulator_desc[i]; struct regulator_desc *desc = &ab3100_regulator_desc[i];
err = ab3100_regulator_register(pdev, plfdata, desc->id); err = ab3100_regulator_register(pdev, plfdata, NULL, NULL,
desc->id);
if (err) if (err)
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment