From a33b6e5a8fb5fadeef206bacef13117e8a3080c4 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 3 Feb 2012 12:54:38 +0530 Subject: regulator: twl6030: Fix voltage selection logic The voltage selection logic for the twl6030 smps fails if min:max is such that min < 1300mV and max > 1300mV although this is in valid range for a regulator e.g. [x, 1350] where x < 1300. Fixing the voltage selection logic such that first it will check for min_uV for a range and then calculated value will be checked against max_uV. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 181a2cf..e5d2223 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -755,12 +755,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, case 0: if (min_uV == 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; if (vsel % 100) vsel += 100; vsel /= 100; 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 58..62 are non linear. @@ -781,12 +785,16 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, case SMPS_OFFSET_EN: if (min_uV == 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; if (vsel % 100) vsel += 100; vsel /= 100; 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 58..62 are non linear. @@ -819,7 +827,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, if (min_uV == 0) vsel = 0; else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { - vsel = (min_uV - 1852000) / 386; + vsel = (min_uV - 2161000) / 386; if (vsel % 100) vsel += 100; vsel /= 100; -- cgit v0.10.2 From 63bfff4e20211b464cbea6e79e5fd36df227c154 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 16 Feb 2012 12:27:52 +0200 Subject: regulator: twl4030: add support for external voltage get/set This is needed for SMPS regulators, which use the OMAP voltage processor for voltage get/set functions instead of the normal I2C channel. For this purpose, regulator_init_data->driver_data contents are expanded, it is now a struct which contains function pointers for the set/get voltage operations, a data pointer for these, and the previously used features bitmask. Signed-off-by: Tero Kristo Acked-by: Samuel Ortiz [for the MFD part] Signed-off-by: Mark Brown diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e04e04d..fae5f76 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -619,6 +619,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, unsigned num_consumers, unsigned long features) { unsigned sub_chip_id; + struct twl_regulator_driver_data drv_data; + /* regulator framework demands init_data ... */ if (!pdata) return NULL; @@ -628,7 +630,19 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, 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 */ sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index e5d2223..7ff8bb22 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -58,6 +58,16 @@ struct twlreg_info { /* chip specific 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 +532,25 @@ twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); - twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, - vsel); + if (info->set_voltage) { + return info->set_voltage(info->data, min_uV); + } else { + twlreg_write(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE_SMPS_4030, vsel); + } + return 0; } static int twl4030smps_get_voltage(struct regulator_dev *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); return vsel * 12500 + 600000; @@ -1060,6 +1080,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; + struct twl_regulator_driver_data *drvdata; for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { if (twl_regs[i].desc.id != pdev->id) @@ -1074,8 +1095,16 @@ static int __devinit twlreg_probe(struct platform_device *pdev) if (!initdata) return -EINVAL; - /* copy the features into regulator data */ - info->features = (unsigned long)initdata->driver_data; + drvdata = initdata->driver_data; + + if (!drvdata) + return -EINVAL; + + /* 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 * this driver and the chip itself can actually do. diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 78d3465..08a82d3 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -749,6 +749,13 @@ struct twl4030_platform_data { 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); -- cgit v0.10.2 From 34a38440689b06a515104d668494e0ff8a4e1537 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Tue, 28 Feb 2012 15:09:10 +0530 Subject: regulator: twl6030: add support for vdd1, vdd2 and vdd3 regulators vdd1 and vdd2 are now common regulators for twl4030 and twl6030. Also added vdd3 as a new regulator for twl6030. twl6030 vdd1...vdd3 smps regulator voltages can only be controlled through the smartreflex voltage channel, thus the support for the voltage_get and set is minimal and requires external controller. Signed-off-by: Tero Kristo Signed-off-by: Rajendra Nayak Acked-by: Samuel Ortiz Signed-off-by: Mark Brown diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index fae5f76..c788e36 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -949,6 +949,21 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) /* twl6030 regulators */ if (twl_has_regulator() && twl_class_is_6030() && !(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_VMMC, pdata->vmmc, features); if (IS_ERR(child)) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7ff8bb22..8611282 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -561,6 +561,32 @@ static struct regulator_ops twl4030smps_ops = { .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) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -926,6 +952,16 @@ static struct regulator_ops twlsmps_ops = { }, \ } +#define TWL6030_ADJUSTABLE_SMPS(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) { \ .base = offset, \ .min_mV = min_mVolts, \ @@ -1027,6 +1063,9 @@ static struct twlreg_info twl_regs[] = { /* 6030 REG with base as PMC Slave Misc : 0x0030 */ /* Turnon-delay and remap configuration values for 6030 are not verified since the specification is not public */ + TWL6030_ADJUSTABLE_SMPS(VDD1), + TWL6030_ADJUSTABLE_SMPS(VDD2), + TWL6030_ADJUSTABLE_SMPS(VDD3), TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300), diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 08a82d3..f66c031 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -712,6 +712,9 @@ struct twl4030_platform_data { struct regulator_init_data *vaux1; struct regulator_init_data *vaux2; struct regulator_init_data *vaux3; + struct regulator_init_data *vdd1; + struct regulator_init_data *vdd2; + struct regulator_init_data *vdd3; /* TWL4030 LDO regulators */ struct regulator_init_data *vpll1; struct regulator_init_data *vpll2; @@ -720,8 +723,6 @@ struct twl4030_platform_data { struct regulator_init_data *vsim; struct regulator_init_data *vaux4; struct regulator_init_data *vio; - struct regulator_init_data *vdd1; - struct regulator_init_data *vdd2; struct regulator_init_data *vintana1; struct regulator_init_data *vintana2; struct regulator_init_data *vintdig; -- cgit v0.10.2 From 2098e95ce9bb039ff2e7bf836df358d18a176139 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 28 Feb 2012 15:09:11 +0530 Subject: regulator: twl: adapt twl-regulator driver to dt Modify the twl regulator driver to extract the regulator_init_data from device tree when passed, instead of getting it through platform_data structures (on non-DT builds) Also add documentation for TWL regulator specific bindings. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt new file mode 100644 index 0000000..ba9d2cc --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -0,0 +1,66 @@ +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-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>; + }; diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 8611282..2a13211 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -14,8 +14,11 @@ #include #include #include +#include +#include #include #include +#include #include @@ -920,7 +923,8 @@ static struct regulator_ops twlsmps_ops = { TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \ 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, \ .id = num, \ .table_len = ARRAY_SIZE(label##_VSEL_table), \ @@ -938,7 +942,7 @@ static struct regulator_ops twlsmps_ops = { } #define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ - { \ +static struct twlreg_info TWL4030_INFO_##label = { \ .base = offset, \ .id = num, \ .delay = turnon_delay, \ @@ -952,7 +956,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } -#define TWL6030_ADJUSTABLE_SMPS(label) { \ +#define TWL6030_ADJUSTABLE_SMPS(label) \ +static struct twlreg_info TWL6030_INFO_##label = { \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ @@ -962,7 +967,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } -#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ +#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ +static struct twlreg_info TWL6030_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -976,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, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ @@ -991,7 +998,8 @@ static struct regulator_ops twlsmps_ops = { } #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, \ .id = num, \ .min_mV = mVolts, \ @@ -1007,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, \ .delay = turnon_delay, \ .desc = { \ @@ -1019,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, \ .min_mV = 600, \ .max_mV = 2100, \ @@ -1037,62 +1047,57 @@ static struct regulator_ops twlsmps_ops = { * We list regulators here if systems need some level of * software control over them after boot. */ -static struct twlreg_info twl_regs[] = { - TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00), - TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00), - TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08), - TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08), - TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08), - TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08), - TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08), - TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08), - TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08), - TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08), - TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08), - /* VUSBCP is managed *only* by the USB subchip */ - - /* 6030 REG with base as PMC Slave Misc : 0x0030 */ - /* Turnon-delay and remap configuration values for 6030 are not - verified since the specification is not public */ - TWL6030_ADJUSTABLE_SMPS(VDD1), - TWL6030_ADJUSTABLE_SMPS(VDD2), - TWL6030_ADJUSTABLE_SMPS(VDD3), - TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300), - TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300), - TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300), - TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300), - TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300), - TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300), - TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0), - TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0), - TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0), - TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0), - TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0), - - /* 6025 are renamed compared to 6030 versions */ - TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300), - TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300), - - TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34), - TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10), - TWL6025_ADJUSTABLE_SMPS(VIO, 0x16), -}; +TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00); +TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00); +TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08); +TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08); +TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08); +TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08); +/* VUSBCP is managed *only* by the USB subchip */ +/* 6030 REG with base as PMC Slave Misc : 0x0030 */ +/* Turnon-delay and remap configuration values for 6030 are not + verified since the specification is not public */ +TWL6030_ADJUSTABLE_SMPS(VDD1); +TWL6030_ADJUSTABLE_SMPS(VDD2); +TWL6030_ADJUSTABLE_SMPS(VDD3); +TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300); +TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300); +TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300); +TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300); +TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300); +TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300); +/* 6025 are renamed compared to 6030 versions */ +TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); +TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); +TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); +TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); +TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); +TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08); +TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0); +TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0); +TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); +TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); +TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0); +TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); +TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); +TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); static u8 twl_get_smps_offset(void) { @@ -1112,38 +1117,114 @@ static u8 twl_get_smps_mult(void) 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), + 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) { - int i; + int i, id; struct twlreg_info *info; struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; struct twl_regulator_driver_data *drvdata; - - for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) { - if (twl_regs[i].desc.id != pdev->id) - continue; - info = twl_regs + i; - break; + const struct of_device_id *match; + + match = of_match_device(twl_of_match, &pdev->dev); + if (match) { + 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) return -ENODEV; - initdata = pdev->dev.platform_data; if (!initdata) return -EINVAL; - drvdata = initdata->driver_data; - - if (!drvdata) - return -EINVAL; - - /* 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; + if (drvdata) { + /* 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 * this driver and the chip itself can actually do. @@ -1153,7 +1234,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS; - switch (pdev->id) { + switch (id) { case TWL4030_REG_VIO: case TWL4030_REG_VDD1: case TWL4030_REG_VDD2: @@ -1167,7 +1248,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - switch (pdev->id) { + switch (id) { case TWL6025_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; @@ -1188,7 +1269,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev) 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)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); @@ -1225,8 +1307,11 @@ static struct platform_driver twlreg_driver = { /* NOTE: short name, to work around driver model truncation of * "twl_regulator.12" (and friends) to "twl_regulator.1". */ - .driver.name = "twl_reg", - .driver.owner = THIS_MODULE, + .driver = { + .name = "twl_reg", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl_of_match), + }, }; static int __init twlreg_init(void) -- cgit v0.10.2 From e9d47fa4ebb9382bc3282fc13ad28a4e2a1a089e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 28 Feb 2012 15:09:12 +0530 Subject: regulator: twl-regulator: Add fixed LDO for V1V8, V2V1 supply V1V8 supply most common use is to provide VIO for the system. V2V1 supply is used on SDP4430/PandaBoards to provide 2.1V to twl6040, and also as an input to VCXIO_IN, VDAC_IN of twl6030. Also update the bindings documentation with the new compatible property for these additional LDOs. Signed-off-by: Peter Ujfalusi Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index ba9d2cc..0c3395d 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -13,6 +13,8 @@ For twl6030 regulators/LDOs - "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 diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 2a13211..9cdfc38 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1094,6 +1094,8 @@ TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0); TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0); TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); +TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); +TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0); TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); @@ -1173,6 +1175,8 @@ static const struct of_device_id twl_of_match[] __devinitconst = { 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), -- cgit v0.10.2 From 46eda3e96a65b378041c79c51ff2e02009f7e2d0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 28 Feb 2012 15:09:13 +0530 Subject: mfd: twl-core: regulator configuration for twl6030 V1V8, V2V1 SMPS To be able to attach consumers to these supplies from board files we need to have regulator_init_data for them. Signed-off-by: Peter Ujfalusi Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index c788e36..d3cf5e8 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -964,6 +964,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long 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, features); if (IS_ERR(child)) diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index f66c031..7fcab23 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -734,6 +734,8 @@ struct twl4030_platform_data { struct regulator_init_data *vcxio; struct regulator_init_data *vusb; struct regulator_init_data *clk32kg; + struct regulator_init_data *v1v8; + struct regulator_init_data *v2v1; /* TWL6025 LDO regulators */ struct regulator_init_data *ldo1; struct regulator_init_data *ldo2; -- cgit v0.10.2