diff options
author | Rajendra Nayak <rnayak@ti.com> | 2009-12-13 16:19:23 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2009-12-13 18:26:20 -0500 |
commit | 441a450554dada1c59fc06fdf068cb0eeba53c6d (patch) | |
tree | 95243a824de1ead21b95bbd36bb85a82be09eeca /drivers/regulator | |
parent | a6b49ffd2d4bba53ad172b1e78ee51fe15ab195e (diff) |
regulator: Add support for twl6030 regulators
This patch updates the regulator driver to add support
for TWL6030 PMIC specific LDO regulators.
SMPS resources are not yet supported for TWL6030 and
also .set_mode and .get_status for LDO's are yet to
be implemented for TWL6030.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Balaji T K <balajitk@ti.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 2 | ||||
-rw-r--r-- | drivers/regulator/twl-regulator.c | 116 |
2 files changed, 96 insertions, 22 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bcbb161bde0b..7cfdd65bebb4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -70,7 +70,7 @@ config REGULATOR_MAX1586 | |||
70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. | 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. |
71 | 71 | ||
72 | config REGULATOR_TWL4030 | 72 | config REGULATOR_TWL4030 |
73 | bool "TI TWL4030/TWL5030/TPS695x0 PMIC" | 73 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
74 | depends on TWL4030_CORE | 74 | depends on TWL4030_CORE |
75 | help | 75 | help |
76 | This driver supports the voltage regulators provided by | 76 | This driver supports the voltage regulators provided by |
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 8e1b68a20ef0..7ea1c3a31081 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -52,27 +52,38 @@ struct twlreg_info { | |||
52 | * The first three registers of all power resource banks help hardware to | 52 | * The first three registers of all power resource banks help hardware to |
53 | * manage the various resource groups. | 53 | * manage the various resource groups. |
54 | */ | 54 | */ |
55 | /* Common offset in TWL4030/6030 */ | ||
55 | #define VREG_GRP 0 | 56 | #define VREG_GRP 0 |
57 | /* TWL4030 register offsets */ | ||
56 | #define VREG_TYPE 1 | 58 | #define VREG_TYPE 1 |
57 | #define VREG_REMAP 2 | 59 | #define VREG_REMAP 2 |
58 | #define VREG_DEDICATED 3 /* LDO control */ | 60 | #define VREG_DEDICATED 3 /* LDO control */ |
59 | 61 | /* TWL6030 register offsets */ | |
62 | #define VREG_TRANS 1 | ||
63 | #define VREG_STATE 2 | ||
64 | #define VREG_VOLTAGE 3 | ||
65 | /* TWL6030 Misc register offsets */ | ||
66 | #define VREG_BC_ALL 1 | ||
67 | #define VREG_BC_REF 2 | ||
68 | #define VREG_BC_PROC 3 | ||
69 | #define VREG_BC_CLK_RST 4 | ||
60 | 70 | ||
61 | static inline int | 71 | static inline int |
62 | twlreg_read(struct twlreg_info *info, unsigned offset) | 72 | twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) |
63 | { | 73 | { |
64 | u8 value; | 74 | u8 value; |
65 | int status; | 75 | int status; |
66 | 76 | ||
67 | status = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, | 77 | status = twl_i2c_read_u8(slave_subgp, |
68 | &value, info->base + offset); | 78 | &value, info->base + offset); |
69 | return (status < 0) ? status : value; | 79 | return (status < 0) ? status : value; |
70 | } | 80 | } |
71 | 81 | ||
72 | static inline int | 82 | static inline int |
73 | twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) | 83 | twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, |
84 | u8 value) | ||
74 | { | 85 | { |
75 | return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, | 86 | return twl_i2c_write_u8(slave_subgp, |
76 | value, info->base + offset); | 87 | value, info->base + offset); |
77 | } | 88 | } |
78 | 89 | ||
@@ -82,17 +93,22 @@ twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) | |||
82 | 93 | ||
83 | static int twlreg_grp(struct regulator_dev *rdev) | 94 | static int twlreg_grp(struct regulator_dev *rdev) |
84 | { | 95 | { |
85 | return twlreg_read(rdev_get_drvdata(rdev), VREG_GRP); | 96 | return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER, |
97 | VREG_GRP); | ||
86 | } | 98 | } |
87 | 99 | ||
88 | /* | 100 | /* |
89 | * Enable/disable regulators by joining/leaving the P1 (processor) group. | 101 | * Enable/disable regulators by joining/leaving the P1 (processor) group. |
90 | * We assume nobody else is updating the DEV_GRP registers. | 102 | * We assume nobody else is updating the DEV_GRP registers. |
91 | */ | 103 | */ |
92 | 104 | /* definition for 4030 family */ | |
93 | #define P3_GRP BIT(7) /* "peripherals" */ | 105 | #define P3_GRP_4030 BIT(7) /* "peripherals" */ |
94 | #define P2_GRP BIT(6) /* secondary processor, modem, etc */ | 106 | #define P2_GRP_4030 BIT(6) /* secondary processor, modem, etc */ |
95 | #define P1_GRP BIT(5) /* CPU/Linux */ | 107 | #define P1_GRP_4030 BIT(5) /* CPU/Linux */ |
108 | /* definition for 6030 family */ | ||
109 | #define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ | ||
110 | #define P2_GRP_6030 BIT(1) /* "peripherals" */ | ||
111 | #define P1_GRP_6030 BIT(0) /* CPU/Linux */ | ||
96 | 112 | ||
97 | static int twlreg_is_enabled(struct regulator_dev *rdev) | 113 | static int twlreg_is_enabled(struct regulator_dev *rdev) |
98 | { | 114 | { |
@@ -101,7 +117,11 @@ static int twlreg_is_enabled(struct regulator_dev *rdev) | |||
101 | if (state < 0) | 117 | if (state < 0) |
102 | return state; | 118 | return state; |
103 | 119 | ||
104 | return (state & P1_GRP) != 0; | 120 | if (twl_class_is_4030()) |
121 | state &= P1_GRP_4030; | ||
122 | else | ||
123 | state &= P1_GRP_6030; | ||
124 | return state; | ||
105 | } | 125 | } |
106 | 126 | ||
107 | static int twlreg_enable(struct regulator_dev *rdev) | 127 | static int twlreg_enable(struct regulator_dev *rdev) |
@@ -109,12 +129,16 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
109 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 129 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
110 | int grp; | 130 | int grp; |
111 | 131 | ||
112 | grp = twlreg_read(info, VREG_GRP); | 132 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
113 | if (grp < 0) | 133 | if (grp < 0) |
114 | return grp; | 134 | return grp; |
115 | 135 | ||
116 | grp |= P1_GRP; | 136 | if (twl_class_is_4030()) |
117 | return twlreg_write(info, VREG_GRP, grp); | 137 | grp |= P1_GRP_4030; |
138 | else | ||
139 | grp |= P1_GRP_6030; | ||
140 | |||
141 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
118 | } | 142 | } |
119 | 143 | ||
120 | static int twlreg_disable(struct regulator_dev *rdev) | 144 | static int twlreg_disable(struct regulator_dev *rdev) |
@@ -122,18 +146,25 @@ static int twlreg_disable(struct regulator_dev *rdev) | |||
122 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 146 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
123 | int grp; | 147 | int grp; |
124 | 148 | ||
125 | grp = twlreg_read(info, VREG_GRP); | 149 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
126 | if (grp < 0) | 150 | if (grp < 0) |
127 | return grp; | 151 | return grp; |
128 | 152 | ||
129 | grp &= ~P1_GRP; | 153 | if (twl_class_is_4030()) |
130 | return twlreg_write(info, VREG_GRP, grp); | 154 | grp &= ~P1_GRP_4030; |
155 | else | ||
156 | grp &= ~P1_GRP_6030; | ||
157 | |||
158 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
131 | } | 159 | } |
132 | 160 | ||
133 | static int twlreg_get_status(struct regulator_dev *rdev) | 161 | static int twlreg_get_status(struct regulator_dev *rdev) |
134 | { | 162 | { |
135 | int state = twlreg_grp(rdev); | 163 | int state = twlreg_grp(rdev); |
136 | 164 | ||
165 | if (twl_class_is_6030()) | ||
166 | return 0; /* FIXME return for 6030 regulator */ | ||
167 | |||
137 | if (state < 0) | 168 | if (state < 0) |
138 | return state; | 169 | return state; |
139 | state &= 0x0f; | 170 | state &= 0x0f; |
@@ -152,6 +183,9 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
152 | unsigned message; | 183 | unsigned message; |
153 | int status; | 184 | int status; |
154 | 185 | ||
186 | if (twl_class_is_6030()) | ||
187 | return 0; /* FIXME return for 6030 regulator */ | ||
188 | |||
155 | /* We can only set the mode through state machine commands... */ | 189 | /* We can only set the mode through state machine commands... */ |
156 | switch (mode) { | 190 | switch (mode) { |
157 | case REGULATOR_MODE_NORMAL: | 191 | case REGULATOR_MODE_NORMAL: |
@@ -168,7 +202,7 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
168 | status = twlreg_grp(rdev); | 202 | status = twlreg_grp(rdev); |
169 | if (status < 0) | 203 | if (status < 0) |
170 | return status; | 204 | return status; |
171 | if (!(status & (P3_GRP | P2_GRP | P1_GRP))) | 205 | if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) |
172 | return -EACCES; | 206 | return -EACCES; |
173 | 207 | ||
174 | status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, | 208 | status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, |
@@ -260,7 +294,29 @@ static const u16 VSIM_VSEL_table[] = { | |||
260 | static const u16 VDAC_VSEL_table[] = { | 294 | static const u16 VDAC_VSEL_table[] = { |
261 | 1200, 1300, 1800, 1800, | 295 | 1200, 1300, 1800, 1800, |
262 | }; | 296 | }; |
263 | 297 | static const u16 VAUX1_6030_VSEL_table[] = { | |
298 | 1000, 1300, 1800, 2500, | ||
299 | 2800, 2900, 3000, 3000, | ||
300 | }; | ||
301 | static const u16 VAUX2_6030_VSEL_table[] = { | ||
302 | 1200, 1800, 2500, 2750, | ||
303 | 2800, 2800, 2800, 2800, | ||
304 | }; | ||
305 | static const u16 VAUX3_6030_VSEL_table[] = { | ||
306 | 1000, 1200, 1300, 1800, | ||
307 | 2500, 2800, 3000, 3000, | ||
308 | }; | ||
309 | static const u16 VMMC_VSEL_table[] = { | ||
310 | 1200, 1800, 2800, 2900, | ||
311 | 3000, 3000, 3000, 3000, | ||
312 | }; | ||
313 | static const u16 VPP_VSEL_table[] = { | ||
314 | 1800, 1900, 2000, 2100, | ||
315 | 2200, 2300, 2400, 2500, | ||
316 | }; | ||
317 | static const u16 VUSIM_VSEL_table[] = { | ||
318 | 1200, 1800, 2500, 2900, | ||
319 | }; | ||
264 | 320 | ||
265 | static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) | 321 | static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) |
266 | { | 322 | { |
@@ -288,7 +344,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
288 | 344 | ||
289 | /* use the first in-range value */ | 345 | /* use the first in-range value */ |
290 | if (min_uV <= uV && uV <= max_uV) | 346 | if (min_uV <= uV && uV <= max_uV) |
291 | return twlreg_write(info, VREG_DEDICATED, vsel); | 347 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, |
348 | VREG_VOLTAGE, vsel); | ||
292 | } | 349 | } |
293 | 350 | ||
294 | return -EDOM; | 351 | return -EDOM; |
@@ -297,7 +354,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
297 | static int twlldo_get_voltage(struct regulator_dev *rdev) | 354 | static int twlldo_get_voltage(struct regulator_dev *rdev) |
298 | { | 355 | { |
299 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 356 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
300 | int vsel = twlreg_read(info, VREG_DEDICATED); | 357 | int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, |
358 | VREG_VOLTAGE); | ||
301 | 359 | ||
302 | if (vsel < 0) | 360 | if (vsel < 0) |
303 | return vsel; | 361 | return vsel; |
@@ -360,6 +418,10 @@ static struct regulator_ops twlfixed_ops = { | |||
360 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) | 418 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) |
361 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ | 419 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ |
362 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) | 420 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) |
421 | #define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ | ||
422 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) | ||
423 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ | ||
424 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) | ||
363 | 425 | ||
364 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ | 426 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ |
365 | .base = offset, \ | 427 | .base = offset, \ |
@@ -420,6 +482,18 @@ static struct twlreg_info twl_regs[] = { | |||
420 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), | 482 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), |
421 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), | 483 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), |
422 | /* VUSBCP is managed *only* by the USB subchip */ | 484 | /* VUSBCP is managed *only* by the USB subchip */ |
485 | |||
486 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ | ||
487 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), | ||
488 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), | ||
489 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), | ||
490 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), | ||
491 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), | ||
492 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), | ||
493 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), | ||
494 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), | ||
495 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), | ||
496 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) | ||
423 | }; | 497 | }; |
424 | 498 | ||
425 | static int twlreg_probe(struct platform_device *pdev) | 499 | static int twlreg_probe(struct platform_device *pdev) |