Commit 4992fa1f authored by Mark Brown's avatar Mark Brown

Merge tag 'topic/twl' into regulator-next

TWL specific changes, cross-merged with OMAP due to arch/arm wanting to
use the new ability to override the voltage set and get operations to
support the in-CPU voltage management.  The other changes are minor
fixes, the addition of a few new regulators and device tree support.
parents 115e4bfd 46eda3e9
TWL family of regulators
Required properties:
For twl6030 regulators/LDOs
- compatible:
- "ti,twl6030-vaux1" for VAUX1 LDO
- "ti,twl6030-vaux2" for VAUX2 LDO
- "ti,twl6030-vaux3" for VAUX3 LDO
- "ti,twl6030-vmmc" for VMMC LDO
- "ti,twl6030-vpp" for VPP LDO
- "ti,twl6030-vusim" for VUSIM LDO
- "ti,twl6030-vana" for VANA LDO
- "ti,twl6030-vcxio" for VCXIO LDO
- "ti,twl6030-vdac" for VDAC LDO
- "ti,twl6030-vusb" for VUSB LDO
- "ti,twl6030-v1v8" for V1V8 LDO
- "ti,twl6030-v2v1" for V2V1 LDO
- "ti,twl6030-clk32kg" for CLK32KG RESOURCE
- "ti,twl6030-vdd1" for VDD1 SMPS
- "ti,twl6030-vdd2" for VDD2 SMPS
- "ti,twl6030-vdd3" for VDD3 SMPS
For twl6025 regulators/LDOs
- compatible:
- "ti,twl6025-ldo1" for LDO1 LDO
- "ti,twl6025-ldo2" for LDO2 LDO
- "ti,twl6025-ldo3" for LDO3 LDO
- "ti,twl6025-ldo4" for LDO4 LDO
- "ti,twl6025-ldo5" for LDO5 LDO
- "ti,twl6025-ldo6" for LDO6 LDO
- "ti,twl6025-ldo7" for LDO7 LDO
- "ti,twl6025-ldoln" for LDOLN LDO
- "ti,twl6025-ldousb" for LDOUSB LDO
- "ti,twl6025-smps3" for SMPS3 SMPS
- "ti,twl6025-smps4" for SMPS4 SMPS
- "ti,twl6025-vio" for VIO SMPS
For twl4030 regulators/LDOs
- compatible:
- "ti,twl4030-vaux1" for VAUX1 LDO
- "ti,twl4030-vaux2" for VAUX2 LDO
- "ti,twl5030-vaux2" for VAUX2 LDO
- "ti,twl4030-vaux3" for VAUX3 LDO
- "ti,twl4030-vaux4" for VAUX4 LDO
- "ti,twl4030-vmmc1" for VMMC1 LDO
- "ti,twl4030-vmmc2" for VMMC2 LDO
- "ti,twl4030-vpll1" for VPLL1 LDO
- "ti,twl4030-vpll2" for VPLL2 LDO
- "ti,twl4030-vsim" for VSIM LDO
- "ti,twl4030-vdac" for VDAC LDO
- "ti,twl4030-vintana2" for VINTANA2 LDO
- "ti,twl4030-vio" for VIO LDO
- "ti,twl4030-vdd1" for VDD1 SMPS
- "ti,twl4030-vdd2" for VDD2 SMPS
- "ti,twl4030-vintana1" for VINTANA1 LDO
- "ti,twl4030-vintdig" for VINTDIG LDO
- "ti,twl4030-vusb1v5" for VUSB1V5 LDO
- "ti,twl4030-vusb1v8" for VUSB1V8 LDO
- "ti,twl4030-vusb3v1" for VUSB3V1 LDO
Optional properties:
- Any optional property defined in bindings/regulator/regulator.txt
Example:
xyz: regulator@0 {
compatible = "ti,twl6030-vaux1";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3000000>;
};
...@@ -621,6 +621,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, ...@@ -621,6 +621,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
unsigned num_consumers, unsigned long features) unsigned num_consumers, unsigned long features)
{ {
unsigned sub_chip_id; unsigned sub_chip_id;
struct twl_regulator_driver_data drv_data;
/* regulator framework demands init_data ... */ /* regulator framework demands init_data ... */
if (!pdata) if (!pdata)
return NULL; return NULL;
...@@ -630,7 +632,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, ...@@ -630,7 +632,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
pdata->num_consumer_supplies = num_consumers; pdata->num_consumer_supplies = num_consumers;
} }
pdata->driver_data = (void *)features; if (pdata->driver_data) {
/* If we have existing drv_data, just add the flags */
struct twl_regulator_driver_data *tmp;
tmp = pdata->driver_data;
tmp->features |= features;
} else {
/* add new driver data struct, used only during init */
drv_data.features = features;
drv_data.set_voltage = NULL;
drv_data.get_voltage = NULL;
drv_data.data = NULL;
pdata->driver_data = &drv_data;
}
/* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
...@@ -937,6 +951,31 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) ...@@ -937,6 +951,31 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
/* twl6030 regulators */ /* twl6030 regulators */
if (twl_has_regulator() && twl_class_is_6030() && if (twl_has_regulator() && twl_class_is_6030() &&
!(features & TWL6025_SUBCLASS)) { !(features & TWL6025_SUBCLASS)) {
child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
features);
if (IS_ERR(child))
return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc, child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
features); features);
if (IS_ERR(child)) if (IS_ERR(child))
......
...@@ -14,8 +14,11 @@ ...@@ -14,8 +14,11 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
...@@ -58,6 +61,16 @@ struct twlreg_info { ...@@ -58,6 +61,16 @@ struct twlreg_info {
/* chip specific features */ /* chip specific features */
unsigned long features; unsigned long features;
/*
* optional override functions for voltage set/get
* these are currently only used for SMPS regulators
*/
int (*get_voltage)(void *data);
int (*set_voltage)(void *data, int target_uV);
/* data passed from board for external get/set voltage */
void *data;
}; };
...@@ -522,15 +535,25 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, ...@@ -522,15 +535,25 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
struct twlreg_info *info = rdev_get_drvdata(rdev); struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, if (info->set_voltage) {
vsel); return info->set_voltage(info->data, min_uV);
} else {
twlreg_write(info, TWL_MODULE_PM_RECEIVER,
VREG_VOLTAGE_SMPS_4030, vsel);
}
return 0; return 0;
} }
static int twl4030smps_get_voltage(struct regulator_dev *rdev) static int twl4030smps_get_voltage(struct regulator_dev *rdev)
{ {
struct twlreg_info *info = rdev_get_drvdata(rdev); struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, int vsel;
if (info->get_voltage)
return info->get_voltage(info->data);
vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
VREG_VOLTAGE_SMPS_4030); VREG_VOLTAGE_SMPS_4030);
return vsel * 12500 + 600000; return vsel * 12500 + 600000;
...@@ -541,6 +564,32 @@ static struct regulator_ops twl4030smps_ops = { ...@@ -541,6 +564,32 @@ static struct regulator_ops twl4030smps_ops = {
.get_voltage = twl4030smps_get_voltage, .get_voltage = twl4030smps_get_voltage,
}; };
static int twl6030coresmps_set_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV, unsigned *selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
if (info->set_voltage)
return info->set_voltage(info->data, min_uV);
return -ENODEV;
}
static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
if (info->get_voltage)
return info->get_voltage(info->data);
return -ENODEV;
}
static struct regulator_ops twl6030coresmps_ops = {
.set_voltage = twl6030coresmps_set_voltage,
.get_voltage = twl6030coresmps_get_voltage,
};
static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
{ {
struct twlreg_info *info = rdev_get_drvdata(rdev); struct twlreg_info *info = rdev_get_drvdata(rdev);
...@@ -755,12 +804,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, ...@@ -755,12 +804,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
case 0: case 0:
if (min_uV == 0) if (min_uV == 0)
vsel = 0; vsel = 0;
else if ((min_uV >= 600000) && (max_uV <= 1300000)) { else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
int calc_uV;
vsel = (min_uV - 600000) / 125; vsel = (min_uV - 600000) / 125;
if (vsel % 100) if (vsel % 100)
vsel += 100; vsel += 100;
vsel /= 100; vsel /= 100;
vsel++; vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
} }
/* Values 1..57 for vsel are linear and can be calculated /* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear. * values 58..62 are non linear.
...@@ -781,12 +834,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, ...@@ -781,12 +834,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
case SMPS_OFFSET_EN: case SMPS_OFFSET_EN:
if (min_uV == 0) if (min_uV == 0)
vsel = 0; vsel = 0;
else if ((min_uV >= 700000) && (max_uV <= 1420000)) { else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
int calc_uV;
vsel = (min_uV - 700000) / 125; vsel = (min_uV - 700000) / 125;
if (vsel % 100) if (vsel % 100)
vsel += 100; vsel += 100;
vsel /= 100; vsel /= 100;
vsel++; vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
} }
/* Values 1..57 for vsel are linear and can be calculated /* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear. * values 58..62 are non linear.
...@@ -819,7 +876,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, ...@@ -819,7 +876,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
if (min_uV == 0) if (min_uV == 0)
vsel = 0; vsel = 0;
else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
vsel = (min_uV - 1852000) / 386; vsel = (min_uV - 2161000) / 386;
if (vsel % 100) if (vsel % 100)
vsel += 100; vsel += 100;
vsel /= 100; vsel /= 100;
...@@ -866,7 +923,8 @@ static struct regulator_ops twlsmps_ops = { ...@@ -866,7 +923,8 @@ static struct regulator_ops twlsmps_ops = {
TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \ TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
0x0, TWL6030, twl6030fixed_ops) 0x0, TWL6030, twl6030fixed_ops)
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
static struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \ .base = offset, \
.id = num, \ .id = num, \
.table_len = ARRAY_SIZE(label##_VSEL_table), \ .table_len = ARRAY_SIZE(label##_VSEL_table), \
...@@ -884,7 +942,7 @@ static struct regulator_ops twlsmps_ops = { ...@@ -884,7 +942,7 @@ static struct regulator_ops twlsmps_ops = {
} }
#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ #define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
{ \ static struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \ .base = offset, \
.id = num, \ .id = num, \
.delay = turnon_delay, \ .delay = turnon_delay, \
...@@ -898,7 +956,19 @@ static struct regulator_ops twlsmps_ops = { ...@@ -898,7 +956,19 @@ static struct regulator_ops twlsmps_ops = {
}, \ }, \
} }
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ #define TWL6030_ADJUSTABLE_SMPS(label) \
static struct twlreg_info TWL6030_INFO_##label = { \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
.ops = &twl6030coresmps_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static struct twlreg_info TWL6030_INFO_##label = { \
.base = offset, \ .base = offset, \
.min_mV = min_mVolts, \ .min_mV = min_mVolts, \
.max_mV = max_mVolts, \ .max_mV = max_mVolts, \
...@@ -912,7 +982,8 @@ static struct regulator_ops twlsmps_ops = { ...@@ -912,7 +982,8 @@ static struct regulator_ops twlsmps_ops = {
}, \ }, \
} }
#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static struct twlreg_info TWL6025_INFO_##label = { \
.base = offset, \ .base = offset, \
.min_mV = min_mVolts, \ .min_mV = min_mVolts, \
.max_mV = max_mVolts, \ .max_mV = max_mVolts, \
...@@ -927,7 +998,8 @@ static struct regulator_ops twlsmps_ops = { ...@@ -927,7 +998,8 @@ static struct regulator_ops twlsmps_ops = {
} }
#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
family, operations) { \ family, operations) \
static struct twlreg_info TWLFIXED_INFO_##label = { \
.base = offset, \ .base = offset, \
.id = num, \ .id = num, \
.min_mV = mVolts, \ .min_mV = mVolts, \
...@@ -943,7 +1015,8 @@ static struct regulator_ops twlsmps_ops = { ...@@ -943,7 +1015,8 @@ static struct regulator_ops twlsmps_ops = {
}, \ }, \
} }
#define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \ #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) \
static struct twlreg_info TWLRES_INFO_##label = { \
.base = offset, \ .base = offset, \
.delay = turnon_delay, \ .delay = turnon_delay, \
.desc = { \ .desc = { \
...@@ -955,7 +1028,8 @@ static struct regulator_ops twlsmps_ops = { ...@@ -955,7 +1028,8 @@ static struct regulator_ops twlsmps_ops = {
}, \ }, \
} }
#define TWL6025_ADJUSTABLE_SMPS(label, offset) { \ #define TWL6025_ADJUSTABLE_SMPS(label, offset) \
static struct twlreg_info TWLSMPS_INFO_##label = { \
.base = offset, \ .base = offset, \
.min_mV = 600, \ .min_mV = 600, \
.max_mV = 2100, \ .max_mV = 2100, \
...@@ -973,59 +1047,59 @@ static struct regulator_ops twlsmps_ops = { ...@@ -973,59 +1047,59 @@ static struct regulator_ops twlsmps_ops = {
* We list regulators here if systems need some level of * We list regulators here if systems need some level of
* software control over them after boot. * software control over them after boot.
*/ */
static struct twlreg_info twl_regs[] = { TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00);
TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00), TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00);
TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00), TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08);
TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08);
TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08);
TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08), TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08);
TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08), TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08);
TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08), /* VUSBCP is managed *only* by the USB subchip */
TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08), /* 6030 REG with base as PMC Slave Misc : 0x0030 */
TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08), /* Turnon-delay and remap configuration values for 6030 are not
TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08), verified since the specification is not public */
TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08), TWL6030_ADJUSTABLE_SMPS(VDD1);
TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08), TWL6030_ADJUSTABLE_SMPS(VDD2);
/* VUSBCP is managed *only* by the USB subchip */ TWL6030_ADJUSTABLE_SMPS(VDD3);
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300);
/* 6030 REG with base as PMC Slave Misc : 0x0030 */ TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300);
/* Turnon-delay and remap configuration values for 6030 are not TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300);
verified since the specification is not public */ TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300), /* 6025 are renamed compared to 6030 versions */
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300);
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300);
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0), TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300);
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0), TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300);
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0), TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0), TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);
TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0), TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);
TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300);
/* 6025 are renamed compared to 6030 versions */ TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08);
TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300), TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300), TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300), TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08);
TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300), TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08);
TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300), TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);
TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300), TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);
TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0);
TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34), TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0);
TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10), TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34);
TWL6025_ADJUSTABLE_SMPS(VIO, 0x16), TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10);
}; TWL6025_ADJUSTABLE_SMPS(VIO, 0x16);
static u8 twl_get_smps_offset(void) static u8 twl_get_smps_offset(void)
{ {
...@@ -1045,29 +1119,116 @@ static u8 twl_get_smps_mult(void) ...@@ -1045,29 +1119,116 @@ static u8 twl_get_smps_mult(void)
return value; return value;
} }
#define TWL_OF_MATCH(comp, family, label) \
{ \
.compatible = comp, \
.data = &family##_INFO_##label, \
}
#define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label)
#define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
#define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
#define TWLRES_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLRES, label)
#define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
static const struct of_device_id twl_of_match[] __devinitconst = {
TWL4030_OF_MATCH("ti,twl4030-vaux1", VAUX1),
TWL4030_OF_MATCH("ti,twl4030-vaux2", VAUX2_4030),
TWL4030_OF_MATCH("ti,twl5030-vaux2", VAUX2),
TWL4030_OF_MATCH("ti,twl4030-vaux3", VAUX3),
TWL4030_OF_MATCH("ti,twl4030-vaux4", VAUX4),
TWL4030_OF_MATCH("ti,twl4030-vmmc1", VMMC1),
TWL4030_OF_MATCH("ti,twl4030-vmmc2", VMMC2),
TWL4030_OF_MATCH("ti,twl4030-vpll1", VPLL1),
TWL4030_OF_MATCH("ti,twl4030-vpll2", VPLL2),
TWL4030_OF_MATCH("ti,twl4030-vsim", VSIM),
TWL4030_OF_MATCH("ti,twl4030-vdac", VDAC),
TWL4030_OF_MATCH("ti,twl4030-vintana2", VINTANA2),
TWL4030_OF_MATCH("ti,twl4030-vio", VIO),
TWL4030_OF_MATCH("ti,twl4030-vdd1", VDD1),
TWL4030_OF_MATCH("ti,twl4030-vdd2", VDD2),
TWL6030_OF_MATCH("ti,twl6030-vdd1", VDD1),
TWL6030_OF_MATCH("ti,twl6030-vdd2", VDD2),
TWL6030_OF_MATCH("ti,twl6030-vdd3", VDD3),
TWL6030_OF_MATCH("ti,twl6030-vaux1", VAUX1_6030),
TWL6030_OF_MATCH("ti,twl6030-vaux2", VAUX2_6030),
TWL6030_OF_MATCH("ti,twl6030-vaux3", VAUX3_6030),
TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC),
TWL6030_OF_MATCH("ti,twl6030-vpp", VPP),
TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM),
TWL6025_OF_MATCH("ti,twl6025-ldo2", LDO2),
TWL6025_OF_MATCH("ti,twl6025-ldo4", LDO4),
TWL6025_OF_MATCH("ti,twl6025-ldo3", LDO3),
TWL6025_OF_MATCH("ti,twl6025-ldo5", LDO5),
TWL6025_OF_MATCH("ti,twl6025-ldo1", LDO1),
TWL6025_OF_MATCH("ti,twl6025-ldo7", LDO7),
TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6),
TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN),
TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB),
TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2),
TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),
TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8),
TWLFIXED_OF_MATCH("ti,twl4030-vusb3v1", VUSB3V1),
TWLFIXED_OF_MATCH("ti,twl6030-vana", VANA),
TWLFIXED_OF_MATCH("ti,twl6030-vcxio", VCXIO),
TWLFIXED_OF_MATCH("ti,twl6030-vdac", VDAC),
TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
TWLRES_OF_MATCH("ti,twl6030-clk32kg", CLK32KG),
TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
{},
};
MODULE_DEVICE_TABLE(of, twl_of_match);
static int __devinit twlreg_probe(struct platform_device *pdev) static int __devinit twlreg_probe(struct platform_device *pdev)
{ {
int i; int i, id;
struct twlreg_info *info; struct twlreg_info *info;
struct regulator_init_data *initdata; struct regulator_init_data *initdata;
struct regulation_constraints *c; struct regulation_constraints *c;
struct regulator_dev *rdev; struct regulator_dev *rdev;
struct twl_regulator_driver_data *drvdata;
for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { const struct of_device_id *match;
if (twl_regs[i].desc.id != pdev->id)
continue; match = of_match_device(twl_of_match, &pdev->dev);
info = twl_regs + i; if (match) {
break; info = match->data;
id = info->desc.id;
initdata = of_get_regulator_init_data(&pdev->dev,
pdev->dev.of_node);
drvdata = NULL;
} else {
id = pdev->id;
initdata = pdev->dev.platform_data;
for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
info = twl_of_match[i].data;
if (!info || info->desc.id != id)
continue;
break;
}
drvdata = initdata->driver_data;
if (!drvdata)
return -EINVAL;
} }
if (!info) if (!info)
return -ENODEV; return -ENODEV;
initdata = pdev->dev.platform_data;
if (!initdata) if (!initdata)
return -EINVAL; return -EINVAL;
/* copy the features into regulator data */ if (drvdata) {
info->features = (unsigned long)initdata->driver_data; /* copy the driver data into regulator data */
info->features = drvdata->features;
info->data = drvdata->data;
info->set_voltage = drvdata->set_voltage;
info->get_voltage = drvdata->get_voltage;
}
/* Constrain board-specific capabilities according to what /* Constrain board-specific capabilities according to what
* this driver and the chip itself can actually do. * this driver and the chip itself can actually do.
...@@ -1077,7 +1238,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) ...@@ -1077,7 +1238,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS; | REGULATOR_CHANGE_STATUS;
switch (pdev->id) { switch (id) {
case TWL4030_REG_VIO: case TWL4030_REG_VIO:
case TWL4030_REG_VDD1: case TWL4030_REG_VDD1:
case TWL4030_REG_VDD2: case TWL4030_REG_VDD2:
...@@ -1091,7 +1252,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) ...@@ -1091,7 +1252,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
break; break;
} }
switch (pdev->id) { switch (id) {
case TWL6025_REG_SMPS3: case TWL6025_REG_SMPS3:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
info->flags |= SMPS_EXTENDED_EN; info->flags |= SMPS_EXTENDED_EN;
...@@ -1112,7 +1273,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev) ...@@ -1112,7 +1273,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
break; break;
} }
rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, NULL); rdev = regulator_register(&info->desc, &pdev->dev, initdata, info,
pdev->dev.of_node);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "can't register %s, %ld\n", dev_err(&pdev->dev, "can't register %s, %ld\n",
info->desc.name, PTR_ERR(rdev)); info->desc.name, PTR_ERR(rdev));
...@@ -1149,8 +1311,11 @@ static struct platform_driver twlreg_driver = { ...@@ -1149,8 +1311,11 @@ static struct platform_driver twlreg_driver = {
/* NOTE: short name, to work around driver model truncation of /* NOTE: short name, to work around driver model truncation of
* "twl_regulator.12" (and friends) to "twl_regulator.1". * "twl_regulator.12" (and friends) to "twl_regulator.1".
*/ */
.driver.name = "twl_reg", .driver = {
.driver.owner = THIS_MODULE, .name = "twl_reg",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(twl_of_match),
},
}; };
static int __init twlreg_init(void) static int __init twlreg_init(void)
......
...@@ -712,6 +712,9 @@ struct twl4030_platform_data { ...@@ -712,6 +712,9 @@ struct twl4030_platform_data {
struct regulator_init_data *vaux1; struct regulator_init_data *vaux1;
struct regulator_init_data *vaux2; struct regulator_init_data *vaux2;
struct regulator_init_data *vaux3; struct regulator_init_data *vaux3;
struct regulator_init_data *vdd1;
struct regulator_init_data *vdd2;
struct regulator_init_data *vdd3;
/* TWL4030 LDO regulators */ /* TWL4030 LDO regulators */
struct regulator_init_data *vpll1; struct regulator_init_data *vpll1;
struct regulator_init_data *vpll2; struct regulator_init_data *vpll2;
...@@ -720,8 +723,6 @@ struct twl4030_platform_data { ...@@ -720,8 +723,6 @@ struct twl4030_platform_data {
struct regulator_init_data *vsim; struct regulator_init_data *vsim;
struct regulator_init_data *vaux4; struct regulator_init_data *vaux4;
struct regulator_init_data *vio; struct regulator_init_data *vio;
struct regulator_init_data *vdd1;
struct regulator_init_data *vdd2;
struct regulator_init_data *vintana1; struct regulator_init_data *vintana1;
struct regulator_init_data *vintana2; struct regulator_init_data *vintana2;
struct regulator_init_data *vintdig; struct regulator_init_data *vintdig;
...@@ -733,6 +734,8 @@ struct twl4030_platform_data { ...@@ -733,6 +734,8 @@ struct twl4030_platform_data {
struct regulator_init_data *vcxio; struct regulator_init_data *vcxio;
struct regulator_init_data *vusb; struct regulator_init_data *vusb;
struct regulator_init_data *clk32kg; struct regulator_init_data *clk32kg;
struct regulator_init_data *v1v8;
struct regulator_init_data *v2v1;
/* TWL6025 LDO regulators */ /* TWL6025 LDO regulators */
struct regulator_init_data *ldo1; struct regulator_init_data *ldo1;
struct regulator_init_data *ldo2; struct regulator_init_data *ldo2;
...@@ -749,6 +752,13 @@ struct twl4030_platform_data { ...@@ -749,6 +752,13 @@ struct twl4030_platform_data {
struct regulator_init_data *vio6025; struct regulator_init_data *vio6025;
}; };
struct twl_regulator_driver_data {
int (*set_voltage)(void *data, int target_uV);
int (*get_voltage)(void *data);
void *data;
unsigned long features;
};
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
int twl4030_sih_setup(int module); int twl4030_sih_setup(int module);
......
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