blob: 9fb4c7b81753d99ff8effaa781f2d8b5930261d8 [file] [log] [blame]
Anuj Aggarwal30e65992009-08-21 00:39:31 +05301/*
2 * tps65023-regulator.c
3 *
4 * Supports TPS65023 Regulator
5 *
6 * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
13 * whether express or implied; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/err.h>
22#include <linux/platform_device.h>
23#include <linux/regulator/driver.h>
24#include <linux/regulator/machine.h>
25#include <linux/i2c.h>
26#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Mark Brown90923352011-06-18 01:18:51 +010028#include <linux/regmap.h>
Anuj Aggarwal30e65992009-08-21 00:39:31 +053029
30/* Register definitions */
31#define TPS65023_REG_VERSION 0
32#define TPS65023_REG_PGOODZ 1
33#define TPS65023_REG_MASK 2
34#define TPS65023_REG_REG_CTRL 3
35#define TPS65023_REG_CON_CTRL 4
36#define TPS65023_REG_CON_CTRL2 5
37#define TPS65023_REG_DEF_CORE 6
38#define TPS65023_REG_DEFSLEW 7
39#define TPS65023_REG_LDO_CTRL 8
40
41/* PGOODZ bitfields */
42#define TPS65023_PGOODZ_PWRFAILZ BIT(7)
43#define TPS65023_PGOODZ_LOWBATTZ BIT(6)
44#define TPS65023_PGOODZ_VDCDC1 BIT(5)
45#define TPS65023_PGOODZ_VDCDC2 BIT(4)
46#define TPS65023_PGOODZ_VDCDC3 BIT(3)
47#define TPS65023_PGOODZ_LDO2 BIT(2)
48#define TPS65023_PGOODZ_LDO1 BIT(1)
49
50/* MASK bitfields */
51#define TPS65023_MASK_PWRFAILZ BIT(7)
52#define TPS65023_MASK_LOWBATTZ BIT(6)
53#define TPS65023_MASK_VDCDC1 BIT(5)
54#define TPS65023_MASK_VDCDC2 BIT(4)
55#define TPS65023_MASK_VDCDC3 BIT(3)
56#define TPS65023_MASK_LDO2 BIT(2)
57#define TPS65023_MASK_LDO1 BIT(1)
58
59/* REG_CTRL bitfields */
60#define TPS65023_REG_CTRL_VDCDC1_EN BIT(5)
61#define TPS65023_REG_CTRL_VDCDC2_EN BIT(4)
62#define TPS65023_REG_CTRL_VDCDC3_EN BIT(3)
63#define TPS65023_REG_CTRL_LDO2_EN BIT(2)
64#define TPS65023_REG_CTRL_LDO1_EN BIT(1)
65
Marcus Folkessonfc999b82011-08-04 13:33:49 +020066/* REG_CTRL2 bitfields */
67#define TPS65023_REG_CTRL2_GO BIT(7)
68#define TPS65023_REG_CTRL2_CORE_ADJ BIT(6)
69#define TPS65023_REG_CTRL2_DCDC2 BIT(2)
Marcus Folkessonf068ad82011-08-08 20:29:32 +020070#define TPS65023_REG_CTRL2_DCDC1 BIT(1)
71#define TPS65023_REG_CTRL2_DCDC3 BIT(0)
72
Anuj Aggarwal30e65992009-08-21 00:39:31 +053073/* LDO_CTRL bitfields */
74#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
75#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4))
76
77/* Number of step-down converters available */
78#define TPS65023_NUM_DCDC 3
79/* Number of LDO voltage regulators available */
80#define TPS65023_NUM_LDO 2
81/* Number of total regulators available */
82#define TPS65023_NUM_REGULATOR (TPS65023_NUM_DCDC + TPS65023_NUM_LDO)
83
84/* DCDCs */
85#define TPS65023_DCDC_1 0
86#define TPS65023_DCDC_2 1
87#define TPS65023_DCDC_3 2
88/* LDOs */
89#define TPS65023_LDO_1 3
90#define TPS65023_LDO_2 4
91
92#define TPS65023_MAX_REG_ID TPS65023_LDO_2
93
94/* Supported voltage values for regulators */
Marcus Folkesson1c3ede02011-08-08 20:29:34 +020095static const u16 VCORE_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +053096 800, 825, 850, 875,
97 900, 925, 950, 975,
98 1000, 1025, 1050, 1075,
99 1100, 1125, 1150, 1175,
100 1200, 1225, 1250, 1275,
101 1300, 1325, 1350, 1375,
102 1400, 1425, 1450, 1475,
103 1500, 1525, 1550, 1600,
104};
105
Marcus Folkesson437afd22011-08-08 20:29:35 +0200106/* Supported voltage values for LDO regulators for tps65020 */
107static const u16 TPS65020_LDO1_VSEL_table[] = {
108 1000, 1050, 1100, 1300,
109 1800, 2500, 3000, 3300,
110};
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200111
Marcus Folkesson437afd22011-08-08 20:29:35 +0200112static const u16 TPS65020_LDO2_VSEL_table[] = {
113 1000, 1050, 1100, 1300,
114 1800, 2500, 3000, 3300,
115};
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200116
117/* Supported voltage values for LDO regulators
118 * for tps65021 and tps65023 */
119static const u16 TPS65023_LDO1_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530120 1000, 1100, 1300, 1800,
121 2200, 2600, 2800, 3150,
122};
123
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200124static const u16 TPS65023_LDO2_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530125 1050, 1200, 1300, 1800,
126 2500, 2800, 3000, 3300,
127};
128
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530129/* Regulator specific details */
130struct tps_info {
131 const char *name;
132 unsigned min_uV;
133 unsigned max_uV;
134 bool fixed;
135 u8 table_len;
136 const u16 *table;
137};
138
139/* PMIC details */
140struct tps_pmic {
141 struct regulator_desc desc[TPS65023_NUM_REGULATOR];
142 struct i2c_client *client;
143 struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
144 const struct tps_info *info[TPS65023_NUM_REGULATOR];
Mark Brown90923352011-06-18 01:18:51 +0100145 struct regmap *regmap;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200146 u8 core_regulator;
147};
148
149/* Struct passed as driver data */
150struct tps_driver_data {
151 const struct tps_info *info;
152 u8 core_regulator;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530153};
154
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530155static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
156{
Mark Brown90923352011-06-18 01:18:51 +0100157 return regmap_update_bits(tps->regmap, reg, mask, mask);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530158}
159
160static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask)
161{
Mark Brown90923352011-06-18 01:18:51 +0100162 return regmap_update_bits(tps->regmap, reg, mask, 0);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530163}
164
165static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg)
166{
Mark Brown90923352011-06-18 01:18:51 +0100167 unsigned int val;
168 int ret;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530169
Mark Brown90923352011-06-18 01:18:51 +0100170 ret = regmap_read(tps->regmap, reg, &val);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530171
Mark Brown90923352011-06-18 01:18:51 +0100172 if (ret != 0)
173 return ret;
174 else
175 return val;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530176}
177
178static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val)
179{
Mark Brown90923352011-06-18 01:18:51 +0100180 return regmap_write(tps->regmap, reg, val);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530181}
182
183static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
184{
185 struct tps_pmic *tps = rdev_get_drvdata(dev);
186 int data, dcdc = rdev_get_id(dev);
187 u8 shift;
188
189 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
190 return -EINVAL;
191
192 shift = TPS65023_NUM_REGULATOR - dcdc;
193 data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
194
195 if (data < 0)
196 return data;
197 else
198 return (data & 1<<shift) ? 1 : 0;
199}
200
201static int tps65023_ldo_is_enabled(struct regulator_dev *dev)
202{
203 struct tps_pmic *tps = rdev_get_drvdata(dev);
204 int data, ldo = rdev_get_id(dev);
205 u8 shift;
206
207 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
208 return -EINVAL;
209
210 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
211 data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
212
213 if (data < 0)
214 return data;
215 else
216 return (data & 1<<shift) ? 1 : 0;
217}
218
219static int tps65023_dcdc_enable(struct regulator_dev *dev)
220{
221 struct tps_pmic *tps = rdev_get_drvdata(dev);
222 int dcdc = rdev_get_id(dev);
223 u8 shift;
224
225 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
226 return -EINVAL;
227
228 shift = TPS65023_NUM_REGULATOR - dcdc;
229 return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
230}
231
232static int tps65023_dcdc_disable(struct regulator_dev *dev)
233{
234 struct tps_pmic *tps = rdev_get_drvdata(dev);
235 int dcdc = rdev_get_id(dev);
236 u8 shift;
237
238 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
239 return -EINVAL;
240
241 shift = TPS65023_NUM_REGULATOR - dcdc;
242 return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
243}
244
245static int tps65023_ldo_enable(struct regulator_dev *dev)
246{
247 struct tps_pmic *tps = rdev_get_drvdata(dev);
248 int ldo = rdev_get_id(dev);
249 u8 shift;
250
251 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
252 return -EINVAL;
253
254 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
255 return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
256}
257
258static int tps65023_ldo_disable(struct regulator_dev *dev)
259{
260 struct tps_pmic *tps = rdev_get_drvdata(dev);
261 int ldo = rdev_get_id(dev);
262 u8 shift;
263
264 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
265 return -EINVAL;
266
267 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
268 return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
269}
270
271static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
272{
273 struct tps_pmic *tps = rdev_get_drvdata(dev);
274 int data, dcdc = rdev_get_id(dev);
275
276 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
277 return -EINVAL;
278
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200279 if (dcdc == tps->core_regulator) {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530280 data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE);
281 if (data < 0)
282 return data;
283 data &= (tps->info[dcdc]->table_len - 1);
284 return tps->info[dcdc]->table[data] * 1000;
285 } else
286 return tps->info[dcdc]->min_uV;
287}
288
289static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000290 int min_uV, int max_uV,
291 unsigned *selector)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530292{
293 struct tps_pmic *tps = rdev_get_drvdata(dev);
294 int dcdc = rdev_get_id(dev);
295 int vsel;
Marcus Folkessoncc17ef32011-08-08 20:29:33 +0200296 int ret;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530297
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200298 if (dcdc != tps->core_regulator)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530299 return -EINVAL;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530300 if (min_uV < tps->info[dcdc]->min_uV
301 || min_uV > tps->info[dcdc]->max_uV)
302 return -EINVAL;
303 if (max_uV < tps->info[dcdc]->min_uV
304 || max_uV > tps->info[dcdc]->max_uV)
305 return -EINVAL;
306
307 for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
308 int mV = tps->info[dcdc]->table[vsel];
309 int uV = mV * 1000;
310
311 /* Break at the first in-range value */
312 if (min_uV <= uV && uV <= max_uV)
313 break;
314 }
315
Mark Brown3a93f2a2010-11-10 14:38:29 +0000316 *selector = vsel;
317
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530318 if (vsel == tps->info[dcdc]->table_len)
Marcus Folkessoncc17ef32011-08-08 20:29:33 +0200319 goto failed;
320
321 ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
322
323 /* Tell the chip that we have changed the value in DEFCORE
324 * and its time to update the core voltage
325 */
326 tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2,
327 TPS65023_REG_CTRL2_GO);
328
329 return ret;
330
331failed:
332 return -EINVAL;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530333}
334
335static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
336{
337 struct tps_pmic *tps = rdev_get_drvdata(dev);
338 int data, ldo = rdev_get_id(dev);
339
340 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
341 return -EINVAL;
342
343 data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
344 if (data < 0)
345 return data;
346
347 data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
348 data &= (tps->info[ldo]->table_len - 1);
349 return tps->info[ldo]->table[data] * 1000;
350}
351
352static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000353 int min_uV, int max_uV, unsigned *selector)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530354{
355 struct tps_pmic *tps = rdev_get_drvdata(dev);
356 int data, vsel, ldo = rdev_get_id(dev);
357
358 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
359 return -EINVAL;
360
361 if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
362 return -EINVAL;
363 if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
364 return -EINVAL;
365
366 for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) {
367 int mV = tps->info[ldo]->table[vsel];
368 int uV = mV * 1000;
369
370 /* Break at the first in-range value */
371 if (min_uV <= uV && uV <= max_uV)
372 break;
373 }
374
375 if (vsel == tps->info[ldo]->table_len)
376 return -EINVAL;
377
Mark Brown3a93f2a2010-11-10 14:38:29 +0000378 *selector = vsel;
379
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530380 data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
381 if (data < 0)
382 return data;
383
384 data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1);
385 data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)));
386 return tps_65023_reg_write(tps, TPS65023_REG_LDO_CTRL, data);
387}
388
389static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
390 unsigned selector)
391{
392 struct tps_pmic *tps = rdev_get_drvdata(dev);
393 int dcdc = rdev_get_id(dev);
394
395 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
396 return -EINVAL;
397
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200398 if (dcdc == tps->core_regulator) {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530399 if (selector >= tps->info[dcdc]->table_len)
400 return -EINVAL;
401 else
402 return tps->info[dcdc]->table[selector] * 1000;
403 } else
404 return tps->info[dcdc]->min_uV;
405}
406
407static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
408 unsigned selector)
409{
410 struct tps_pmic *tps = rdev_get_drvdata(dev);
411 int ldo = rdev_get_id(dev);
412
413 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
414 return -EINVAL;
415
416 if (selector >= tps->info[ldo]->table_len)
417 return -EINVAL;
418 else
419 return tps->info[ldo]->table[selector] * 1000;
420}
421
422/* Operations permitted on VDCDCx */
423static struct regulator_ops tps65023_dcdc_ops = {
424 .is_enabled = tps65023_dcdc_is_enabled,
425 .enable = tps65023_dcdc_enable,
426 .disable = tps65023_dcdc_disable,
427 .get_voltage = tps65023_dcdc_get_voltage,
428 .set_voltage = tps65023_dcdc_set_voltage,
429 .list_voltage = tps65023_dcdc_list_voltage,
430};
431
432/* Operations permitted on LDOx */
433static struct regulator_ops tps65023_ldo_ops = {
434 .is_enabled = tps65023_ldo_is_enabled,
435 .enable = tps65023_ldo_enable,
436 .disable = tps65023_ldo_disable,
437 .get_voltage = tps65023_ldo_get_voltage,
438 .set_voltage = tps65023_ldo_set_voltage,
439 .list_voltage = tps65023_ldo_list_voltage,
440};
441
Mark Brown90923352011-06-18 01:18:51 +0100442static struct regmap_config tps65023_regmap_config = {
443 .reg_bits = 8,
444 .val_bits = 8,
445};
446
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800447static int __devinit tps_65023_probe(struct i2c_client *client,
448 const struct i2c_device_id *id)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530449{
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200450 const struct tps_driver_data *drv_data = (void *)id->driver_data;
451 const struct tps_info *info = drv_data->info;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530452 struct regulator_init_data *init_data;
453 struct regulator_dev *rdev;
454 struct tps_pmic *tps;
455 int i;
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800456 int error;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530457
458 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
459 return -EIO;
460
461 /**
462 * init_data points to array of regulator_init structures
463 * coming from the board-evm file.
464 */
465 init_data = client->dev.platform_data;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530466 if (!init_data)
467 return -EIO;
468
469 tps = kzalloc(sizeof(*tps), GFP_KERNEL);
470 if (!tps)
471 return -ENOMEM;
472
Mark Brown90923352011-06-18 01:18:51 +0100473 tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config);
474 if (IS_ERR(tps->regmap)) {
475 error = PTR_ERR(tps->regmap);
476 dev_err(&client->dev, "Failed to allocate register map: %d\n",
477 error);
478 goto fail_alloc;
479 }
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530480
481 /* common for all regulators */
482 tps->client = client;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200483 tps->core_regulator = drv_data->core_regulator;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530484
485 for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
486 /* Store regulator specific information */
487 tps->info[i] = info;
488
489 tps->desc[i].name = info->name;
Axel Lin77fa44d2011-05-12 13:47:50 +0800490 tps->desc[i].id = i;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200491 tps->desc[i].n_voltages = info->table_len;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530492 tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
493 &tps65023_ldo_ops : &tps65023_dcdc_ops);
494 tps->desc[i].type = REGULATOR_VOLTAGE;
495 tps->desc[i].owner = THIS_MODULE;
496
497 /* Register the regulators */
498 rdev = regulator_register(&tps->desc[i], &client->dev,
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800499 init_data, tps);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530500 if (IS_ERR(rdev)) {
501 dev_err(&client->dev, "failed to register %s\n",
502 id->name);
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800503 error = PTR_ERR(rdev);
504 goto fail;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530505 }
506
507 /* Save regulator for cleanup */
508 tps->rdev[i] = rdev;
509 }
510
511 i2c_set_clientdata(client, tps);
512
Marcus Folkessonfc999b82011-08-04 13:33:49 +0200513 /* Enable setting output voltage by I2C */
514 tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
515 TPS65023_REG_CTRL2_CORE_ADJ);
516
Marcus Folkessonf068ad82011-08-08 20:29:32 +0200517 /* Enable setting output voltage by I2C */
518 tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
519 TPS65023_REG_CTRL2_CORE_ADJ);
520
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530521 return 0;
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800522
523 fail:
524 while (--i >= 0)
525 regulator_unregister(tps->rdev[i]);
526
Mark Brown90923352011-06-18 01:18:51 +0100527 regmap_exit(tps->regmap);
528 fail_alloc:
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800529 kfree(tps);
530 return error;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530531}
532
533/**
534 * tps_65023_remove - TPS65023 driver i2c remove handler
535 * @client: i2c driver client device structure
536 *
537 * Unregister TPS driver as an i2c client device driver
538 */
539static int __devexit tps_65023_remove(struct i2c_client *client)
540{
541 struct tps_pmic *tps = i2c_get_clientdata(client);
542 int i;
543
544 for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
545 regulator_unregister(tps->rdev[i]);
546
Mark Brown90923352011-06-18 01:18:51 +0100547 regmap_exit(tps->regmap);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530548 kfree(tps);
549
550 return 0;
551}
552
Marcus Folkesson437afd22011-08-08 20:29:35 +0200553static const struct tps_info tps65020_regs[] = {
554 {
555 .name = "VDCDC1",
556 .min_uV = 3300000,
557 .max_uV = 3300000,
558 .fixed = 1,
559 },
560 {
561 .name = "VDCDC2",
562 .min_uV = 1800000,
563 .max_uV = 1800000,
564 .fixed = 1,
565 },
566 {
567 .name = "VDCDC3",
568 .min_uV = 800000,
569 .max_uV = 1600000,
570 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
571 .table = VCORE_VSEL_table,
572 },
573
574 {
575 .name = "LDO1",
576 .min_uV = 1000000,
577 .max_uV = 3150000,
578 .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
579 .table = TPS65020_LDO1_VSEL_table,
580 },
581 {
582 .name = "LDO2",
583 .min_uV = 1050000,
584 .max_uV = 3300000,
585 .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
586 .table = TPS65020_LDO2_VSEL_table,
587 },
588};
589
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200590static const struct tps_info tps65021_regs[] = {
591 {
592 .name = "VDCDC1",
593 .min_uV = 3300000,
594 .max_uV = 3300000,
595 .fixed = 1,
596 },
597 {
598 .name = "VDCDC2",
599 .min_uV = 1800000,
600 .max_uV = 1800000,
601 .fixed = 1,
602 },
603 {
604 .name = "VDCDC3",
605 .min_uV = 800000,
606 .max_uV = 1600000,
607 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
608 .table = VCORE_VSEL_table,
609 },
610 {
611 .name = "LDO1",
612 .min_uV = 1000000,
613 .max_uV = 3150000,
614 .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
615 .table = TPS65023_LDO1_VSEL_table,
616 },
617 {
618 .name = "LDO2",
619 .min_uV = 1050000,
620 .max_uV = 3300000,
621 .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
622 .table = TPS65023_LDO2_VSEL_table,
623 },
624};
625
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530626static const struct tps_info tps65023_regs[] = {
627 {
628 .name = "VDCDC1",
629 .min_uV = 800000,
630 .max_uV = 1600000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200631 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
632 .table = VCORE_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530633 },
634 {
635 .name = "VDCDC2",
636 .min_uV = 3300000,
637 .max_uV = 3300000,
638 .fixed = 1,
639 },
640 {
641 .name = "VDCDC3",
642 .min_uV = 1800000,
643 .max_uV = 1800000,
644 .fixed = 1,
645 },
646 {
647 .name = "LDO1",
648 .min_uV = 1000000,
649 .max_uV = 3150000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200650 .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
651 .table = TPS65023_LDO1_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530652 },
653 {
654 .name = "LDO2",
655 .min_uV = 1050000,
656 .max_uV = 3300000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200657 .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
658 .table = TPS65023_LDO2_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530659 },
660};
661
Marcus Folkesson437afd22011-08-08 20:29:35 +0200662static struct tps_driver_data tps65020_drv_data = {
663 .info = tps65020_regs,
664 .core_regulator = TPS65023_DCDC_3,
665};
666
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200667static struct tps_driver_data tps65021_drv_data = {
668 .info = tps65021_regs,
669 .core_regulator = TPS65023_DCDC_3,
670};
671
672static struct tps_driver_data tps65023_drv_data = {
673 .info = tps65023_regs,
674 .core_regulator = TPS65023_DCDC_1,
675};
676
Liam Girdwood9e108d32009-08-24 10:31:34 +0100677static const struct i2c_device_id tps_65023_id[] = {
678 {.name = "tps65023",
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200679 .driver_data = (unsigned long) &tps65023_drv_data},
Marek Vasut1880a2f2010-06-24 15:49:49 +0200680 {.name = "tps65021",
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200681 .driver_data = (unsigned long) &tps65021_drv_data,},
Marcus Folkesson437afd22011-08-08 20:29:35 +0200682 {.name = "tps65020",
683 .driver_data = (unsigned long) &tps65020_drv_data},
Liam Girdwood9e108d32009-08-24 10:31:34 +0100684 { },
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530685};
686
687MODULE_DEVICE_TABLE(i2c, tps_65023_id);
688
689static struct i2c_driver tps_65023_i2c_driver = {
690 .driver = {
691 .name = "tps65023",
692 .owner = THIS_MODULE,
693 },
694 .probe = tps_65023_probe,
695 .remove = __devexit_p(tps_65023_remove),
Liam Girdwood9e108d32009-08-24 10:31:34 +0100696 .id_table = tps_65023_id,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530697};
698
699/**
700 * tps_65023_init
701 *
702 * Module init function
703 */
704static int __init tps_65023_init(void)
705{
706 return i2c_add_driver(&tps_65023_i2c_driver);
707}
708subsys_initcall(tps_65023_init);
709
710/**
711 * tps_65023_cleanup
712 *
713 * Module exit function
714 */
715static void __exit tps_65023_cleanup(void)
716{
717 i2c_del_driver(&tps_65023_i2c_driver);
718}
719module_exit(tps_65023_cleanup);
720
721MODULE_AUTHOR("Texas Instruments");
722MODULE_DESCRIPTION("TPS65023 voltage regulator driver");
Liam Girdwood9e108d32009-08-24 10:31:34 +0100723MODULE_LICENSE("GPL v2");