blob: b02c670863532b6ff107d2b8f52c12164081eeea [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)
70#define TPS65023_REG_CTRL2_DCDC1 BIT(2)
71#define TPS65023_REG_CTRL2_DCDC3 BIT(0)
72
Marcus Folkessonf068ad82011-08-08 20:29:32 +020073/* REG_CTRL2 bitfields */
74#define TPS65023_REG_CTRL2_GO BIT(7)
75#define TPS65023_REG_CTRL2_CORE_ADJ BIT(6)
76#define TPS65023_REG_CTRL2_DCDC2 BIT(2)
77#define TPS65023_REG_CTRL2_DCDC1 BIT(1)
78#define TPS65023_REG_CTRL2_DCDC3 BIT(0)
79
Anuj Aggarwal30e65992009-08-21 00:39:31 +053080/* LDO_CTRL bitfields */
81#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
82#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4))
83
84/* Number of step-down converters available */
85#define TPS65023_NUM_DCDC 3
86/* Number of LDO voltage regulators available */
87#define TPS65023_NUM_LDO 2
88/* Number of total regulators available */
89#define TPS65023_NUM_REGULATOR (TPS65023_NUM_DCDC + TPS65023_NUM_LDO)
90
91/* DCDCs */
92#define TPS65023_DCDC_1 0
93#define TPS65023_DCDC_2 1
94#define TPS65023_DCDC_3 2
95/* LDOs */
96#define TPS65023_LDO_1 3
97#define TPS65023_LDO_2 4
98
99#define TPS65023_MAX_REG_ID TPS65023_LDO_2
100
101/* Supported voltage values for regulators */
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200102static const u16 VCORE_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530103 800, 825, 850, 875,
104 900, 925, 950, 975,
105 1000, 1025, 1050, 1075,
106 1100, 1125, 1150, 1175,
107 1200, 1225, 1250, 1275,
108 1300, 1325, 1350, 1375,
109 1400, 1425, 1450, 1475,
110 1500, 1525, 1550, 1600,
111};
112
Marcus Folkesson437afd22011-08-08 20:29:35 +0200113/* Supported voltage values for LDO regulators for tps65020 */
114static const u16 TPS65020_LDO1_VSEL_table[] = {
115 1000, 1050, 1100, 1300,
116 1800, 2500, 3000, 3300,
117};
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200118
Marcus Folkesson437afd22011-08-08 20:29:35 +0200119static const u16 TPS65020_LDO2_VSEL_table[] = {
120 1000, 1050, 1100, 1300,
121 1800, 2500, 3000, 3300,
122};
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200123
124/* Supported voltage values for LDO regulators
125 * for tps65021 and tps65023 */
126static const u16 TPS65023_LDO1_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530127 1000, 1100, 1300, 1800,
128 2200, 2600, 2800, 3150,
129};
130
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200131static const u16 TPS65023_LDO2_VSEL_table[] = {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530132 1050, 1200, 1300, 1800,
133 2500, 2800, 3000, 3300,
134};
135
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530136/* Regulator specific details */
137struct tps_info {
138 const char *name;
139 unsigned min_uV;
140 unsigned max_uV;
141 bool fixed;
142 u8 table_len;
143 const u16 *table;
144};
145
146/* PMIC details */
147struct tps_pmic {
148 struct regulator_desc desc[TPS65023_NUM_REGULATOR];
149 struct i2c_client *client;
150 struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
151 const struct tps_info *info[TPS65023_NUM_REGULATOR];
Mark Brown90923352011-06-18 01:18:51 +0100152 struct regmap *regmap;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200153 u8 core_regulator;
154};
155
156/* Struct passed as driver data */
157struct tps_driver_data {
158 const struct tps_info *info;
159 u8 core_regulator;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530160};
161
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530162static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
163{
Mark Brown90923352011-06-18 01:18:51 +0100164 return regmap_update_bits(tps->regmap, reg, mask, mask);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530165}
166
167static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask)
168{
Mark Brown90923352011-06-18 01:18:51 +0100169 return regmap_update_bits(tps->regmap, reg, mask, 0);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530170}
171
172static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg)
173{
Mark Brown90923352011-06-18 01:18:51 +0100174 unsigned int val;
175 int ret;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530176
Mark Brown90923352011-06-18 01:18:51 +0100177 ret = regmap_read(tps->regmap, reg, &val);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530178
Mark Brown90923352011-06-18 01:18:51 +0100179 if (ret != 0)
180 return ret;
181 else
182 return val;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530183}
184
185static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val)
186{
Mark Brown90923352011-06-18 01:18:51 +0100187 return regmap_write(tps->regmap, reg, val);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530188}
189
190static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
191{
192 struct tps_pmic *tps = rdev_get_drvdata(dev);
193 int data, dcdc = rdev_get_id(dev);
194 u8 shift;
195
196 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
197 return -EINVAL;
198
199 shift = TPS65023_NUM_REGULATOR - dcdc;
200 data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
201
202 if (data < 0)
203 return data;
204 else
205 return (data & 1<<shift) ? 1 : 0;
206}
207
208static int tps65023_ldo_is_enabled(struct regulator_dev *dev)
209{
210 struct tps_pmic *tps = rdev_get_drvdata(dev);
211 int data, ldo = rdev_get_id(dev);
212 u8 shift;
213
214 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
215 return -EINVAL;
216
217 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
218 data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL);
219
220 if (data < 0)
221 return data;
222 else
223 return (data & 1<<shift) ? 1 : 0;
224}
225
226static int tps65023_dcdc_enable(struct regulator_dev *dev)
227{
228 struct tps_pmic *tps = rdev_get_drvdata(dev);
229 int dcdc = rdev_get_id(dev);
230 u8 shift;
231
232 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
233 return -EINVAL;
234
235 shift = TPS65023_NUM_REGULATOR - dcdc;
236 return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
237}
238
239static int tps65023_dcdc_disable(struct regulator_dev *dev)
240{
241 struct tps_pmic *tps = rdev_get_drvdata(dev);
242 int dcdc = rdev_get_id(dev);
243 u8 shift;
244
245 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
246 return -EINVAL;
247
248 shift = TPS65023_NUM_REGULATOR - dcdc;
249 return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
250}
251
252static int tps65023_ldo_enable(struct regulator_dev *dev)
253{
254 struct tps_pmic *tps = rdev_get_drvdata(dev);
255 int ldo = rdev_get_id(dev);
256 u8 shift;
257
258 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
259 return -EINVAL;
260
261 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
262 return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
263}
264
265static int tps65023_ldo_disable(struct regulator_dev *dev)
266{
267 struct tps_pmic *tps = rdev_get_drvdata(dev);
268 int ldo = rdev_get_id(dev);
269 u8 shift;
270
271 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
272 return -EINVAL;
273
274 shift = (ldo == TPS65023_LDO_1 ? 1 : 2);
275 return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift);
276}
277
278static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
279{
280 struct tps_pmic *tps = rdev_get_drvdata(dev);
281 int data, dcdc = rdev_get_id(dev);
282
283 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
284 return -EINVAL;
285
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200286 if (dcdc == tps->core_regulator) {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530287 data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE);
288 if (data < 0)
289 return data;
290 data &= (tps->info[dcdc]->table_len - 1);
291 return tps->info[dcdc]->table[data] * 1000;
292 } else
293 return tps->info[dcdc]->min_uV;
294}
295
296static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000297 int min_uV, int max_uV,
298 unsigned *selector)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530299{
300 struct tps_pmic *tps = rdev_get_drvdata(dev);
301 int dcdc = rdev_get_id(dev);
302 int vsel;
Marcus Folkessoncc17ef32011-08-08 20:29:33 +0200303 int ret;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530304
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200305 if (dcdc != tps->core_regulator)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530306 return -EINVAL;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530307 if (min_uV < tps->info[dcdc]->min_uV
308 || min_uV > tps->info[dcdc]->max_uV)
309 return -EINVAL;
310 if (max_uV < tps->info[dcdc]->min_uV
311 || max_uV > tps->info[dcdc]->max_uV)
312 return -EINVAL;
313
314 for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
315 int mV = tps->info[dcdc]->table[vsel];
316 int uV = mV * 1000;
317
318 /* Break at the first in-range value */
319 if (min_uV <= uV && uV <= max_uV)
320 break;
321 }
322
Mark Brown3a93f2a2010-11-10 14:38:29 +0000323 *selector = vsel;
324
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530325 if (vsel == tps->info[dcdc]->table_len)
Marcus Folkessoncc17ef32011-08-08 20:29:33 +0200326 goto failed;
327
328 ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
329
330 /* Tell the chip that we have changed the value in DEFCORE
331 * and its time to update the core voltage
332 */
333 tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2,
334 TPS65023_REG_CTRL2_GO);
335
336 return ret;
337
338failed:
339 return -EINVAL;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530340}
341
342static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
343{
344 struct tps_pmic *tps = rdev_get_drvdata(dev);
345 int data, ldo = rdev_get_id(dev);
346
347 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
348 return -EINVAL;
349
350 data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
351 if (data < 0)
352 return data;
353
354 data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
355 data &= (tps->info[ldo]->table_len - 1);
356 return tps->info[ldo]->table[data] * 1000;
357}
358
359static int tps65023_ldo_set_voltage(struct regulator_dev *dev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000360 int min_uV, int max_uV, unsigned *selector)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530361{
362 struct tps_pmic *tps = rdev_get_drvdata(dev);
363 int data, vsel, ldo = rdev_get_id(dev);
364
365 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
366 return -EINVAL;
367
368 if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
369 return -EINVAL;
370 if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
371 return -EINVAL;
372
373 for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) {
374 int mV = tps->info[ldo]->table[vsel];
375 int uV = mV * 1000;
376
377 /* Break at the first in-range value */
378 if (min_uV <= uV && uV <= max_uV)
379 break;
380 }
381
382 if (vsel == tps->info[ldo]->table_len)
383 return -EINVAL;
384
Mark Brown3a93f2a2010-11-10 14:38:29 +0000385 *selector = vsel;
386
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530387 data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL);
388 if (data < 0)
389 return data;
390
391 data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1);
392 data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)));
393 return tps_65023_reg_write(tps, TPS65023_REG_LDO_CTRL, data);
394}
395
396static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
397 unsigned selector)
398{
399 struct tps_pmic *tps = rdev_get_drvdata(dev);
400 int dcdc = rdev_get_id(dev);
401
402 if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
403 return -EINVAL;
404
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200405 if (dcdc == tps->core_regulator) {
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530406 if (selector >= tps->info[dcdc]->table_len)
407 return -EINVAL;
408 else
409 return tps->info[dcdc]->table[selector] * 1000;
410 } else
411 return tps->info[dcdc]->min_uV;
412}
413
414static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
415 unsigned selector)
416{
417 struct tps_pmic *tps = rdev_get_drvdata(dev);
418 int ldo = rdev_get_id(dev);
419
420 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
421 return -EINVAL;
422
423 if (selector >= tps->info[ldo]->table_len)
424 return -EINVAL;
425 else
426 return tps->info[ldo]->table[selector] * 1000;
427}
428
429/* Operations permitted on VDCDCx */
430static struct regulator_ops tps65023_dcdc_ops = {
431 .is_enabled = tps65023_dcdc_is_enabled,
432 .enable = tps65023_dcdc_enable,
433 .disable = tps65023_dcdc_disable,
434 .get_voltage = tps65023_dcdc_get_voltage,
435 .set_voltage = tps65023_dcdc_set_voltage,
436 .list_voltage = tps65023_dcdc_list_voltage,
437};
438
439/* Operations permitted on LDOx */
440static struct regulator_ops tps65023_ldo_ops = {
441 .is_enabled = tps65023_ldo_is_enabled,
442 .enable = tps65023_ldo_enable,
443 .disable = tps65023_ldo_disable,
444 .get_voltage = tps65023_ldo_get_voltage,
445 .set_voltage = tps65023_ldo_set_voltage,
446 .list_voltage = tps65023_ldo_list_voltage,
447};
448
Mark Brown90923352011-06-18 01:18:51 +0100449static struct regmap_config tps65023_regmap_config = {
450 .reg_bits = 8,
451 .val_bits = 8,
452};
453
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800454static int __devinit tps_65023_probe(struct i2c_client *client,
455 const struct i2c_device_id *id)
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530456{
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200457 const struct tps_driver_data *drv_data = (void *)id->driver_data;
458 const struct tps_info *info = drv_data->info;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530459 struct regulator_init_data *init_data;
460 struct regulator_dev *rdev;
461 struct tps_pmic *tps;
462 int i;
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800463 int error;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530464
465 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
466 return -EIO;
467
468 /**
469 * init_data points to array of regulator_init structures
470 * coming from the board-evm file.
471 */
472 init_data = client->dev.platform_data;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530473 if (!init_data)
474 return -EIO;
475
476 tps = kzalloc(sizeof(*tps), GFP_KERNEL);
477 if (!tps)
478 return -ENOMEM;
479
Mark Brown90923352011-06-18 01:18:51 +0100480 tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config);
481 if (IS_ERR(tps->regmap)) {
482 error = PTR_ERR(tps->regmap);
483 dev_err(&client->dev, "Failed to allocate register map: %d\n",
484 error);
485 goto fail_alloc;
486 }
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530487
488 /* common for all regulators */
489 tps->client = client;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200490 tps->core_regulator = drv_data->core_regulator;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530491
492 for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
493 /* Store regulator specific information */
494 tps->info[i] = info;
495
496 tps->desc[i].name = info->name;
Axel Lin77fa44d2011-05-12 13:47:50 +0800497 tps->desc[i].id = i;
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200498 tps->desc[i].n_voltages = info->table_len;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530499 tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
500 &tps65023_ldo_ops : &tps65023_dcdc_ops);
501 tps->desc[i].type = REGULATOR_VOLTAGE;
502 tps->desc[i].owner = THIS_MODULE;
503
504 /* Register the regulators */
505 rdev = regulator_register(&tps->desc[i], &client->dev,
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800506 init_data, tps);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530507 if (IS_ERR(rdev)) {
508 dev_err(&client->dev, "failed to register %s\n",
509 id->name);
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800510 error = PTR_ERR(rdev);
511 goto fail;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530512 }
513
514 /* Save regulator for cleanup */
515 tps->rdev[i] = rdev;
516 }
517
518 i2c_set_clientdata(client, tps);
519
Marcus Folkessonfc999b82011-08-04 13:33:49 +0200520 /* Enable setting output voltage by I2C */
521 tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
522 TPS65023_REG_CTRL2_CORE_ADJ);
523
Marcus Folkessonf068ad82011-08-08 20:29:32 +0200524 /* Enable setting output voltage by I2C */
525 tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
526 TPS65023_REG_CTRL2_CORE_ADJ);
527
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530528 return 0;
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800529
530 fail:
531 while (--i >= 0)
532 regulator_unregister(tps->rdev[i]);
533
Mark Brown90923352011-06-18 01:18:51 +0100534 regmap_exit(tps->regmap);
535 fail_alloc:
Dmitry Torokhov54d13ab2010-02-23 23:38:06 -0800536 kfree(tps);
537 return error;
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530538}
539
540/**
541 * tps_65023_remove - TPS65023 driver i2c remove handler
542 * @client: i2c driver client device structure
543 *
544 * Unregister TPS driver as an i2c client device driver
545 */
546static int __devexit tps_65023_remove(struct i2c_client *client)
547{
548 struct tps_pmic *tps = i2c_get_clientdata(client);
549 int i;
550
551 for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
552 regulator_unregister(tps->rdev[i]);
553
Mark Brown90923352011-06-18 01:18:51 +0100554 regmap_exit(tps->regmap);
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530555 kfree(tps);
556
557 return 0;
558}
559
Marcus Folkesson437afd22011-08-08 20:29:35 +0200560static const struct tps_info tps65020_regs[] = {
561 {
562 .name = "VDCDC1",
563 .min_uV = 3300000,
564 .max_uV = 3300000,
565 .fixed = 1,
566 },
567 {
568 .name = "VDCDC2",
569 .min_uV = 1800000,
570 .max_uV = 1800000,
571 .fixed = 1,
572 },
573 {
574 .name = "VDCDC3",
575 .min_uV = 800000,
576 .max_uV = 1600000,
577 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
578 .table = VCORE_VSEL_table,
579 },
580
581 {
582 .name = "LDO1",
583 .min_uV = 1000000,
584 .max_uV = 3150000,
585 .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
586 .table = TPS65020_LDO1_VSEL_table,
587 },
588 {
589 .name = "LDO2",
590 .min_uV = 1050000,
591 .max_uV = 3300000,
592 .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
593 .table = TPS65020_LDO2_VSEL_table,
594 },
595};
596
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200597static const struct tps_info tps65021_regs[] = {
598 {
599 .name = "VDCDC1",
600 .min_uV = 3300000,
601 .max_uV = 3300000,
602 .fixed = 1,
603 },
604 {
605 .name = "VDCDC2",
606 .min_uV = 1800000,
607 .max_uV = 1800000,
608 .fixed = 1,
609 },
610 {
611 .name = "VDCDC3",
612 .min_uV = 800000,
613 .max_uV = 1600000,
614 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
615 .table = VCORE_VSEL_table,
616 },
617 {
618 .name = "LDO1",
619 .min_uV = 1000000,
620 .max_uV = 3150000,
621 .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
622 .table = TPS65023_LDO1_VSEL_table,
623 },
624 {
625 .name = "LDO2",
626 .min_uV = 1050000,
627 .max_uV = 3300000,
628 .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
629 .table = TPS65023_LDO2_VSEL_table,
630 },
631};
632
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530633static const struct tps_info tps65023_regs[] = {
634 {
635 .name = "VDCDC1",
636 .min_uV = 800000,
637 .max_uV = 1600000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200638 .table_len = ARRAY_SIZE(VCORE_VSEL_table),
639 .table = VCORE_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530640 },
641 {
642 .name = "VDCDC2",
643 .min_uV = 3300000,
644 .max_uV = 3300000,
645 .fixed = 1,
646 },
647 {
648 .name = "VDCDC3",
649 .min_uV = 1800000,
650 .max_uV = 1800000,
651 .fixed = 1,
652 },
653 {
654 .name = "LDO1",
655 .min_uV = 1000000,
656 .max_uV = 3150000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200657 .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
658 .table = TPS65023_LDO1_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530659 },
660 {
661 .name = "LDO2",
662 .min_uV = 1050000,
663 .max_uV = 3300000,
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200664 .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
665 .table = TPS65023_LDO2_VSEL_table,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530666 },
667};
668
Marcus Folkesson437afd22011-08-08 20:29:35 +0200669static struct tps_driver_data tps65020_drv_data = {
670 .info = tps65020_regs,
671 .core_regulator = TPS65023_DCDC_3,
672};
673
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200674static struct tps_driver_data tps65021_drv_data = {
675 .info = tps65021_regs,
676 .core_regulator = TPS65023_DCDC_3,
677};
678
679static struct tps_driver_data tps65023_drv_data = {
680 .info = tps65023_regs,
681 .core_regulator = TPS65023_DCDC_1,
682};
683
Liam Girdwood9e108d32009-08-24 10:31:34 +0100684static const struct i2c_device_id tps_65023_id[] = {
685 {.name = "tps65023",
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200686 .driver_data = (unsigned long) &tps65023_drv_data},
Marek Vasut1880a2f2010-06-24 15:49:49 +0200687 {.name = "tps65021",
Marcus Folkesson1c3ede02011-08-08 20:29:34 +0200688 .driver_data = (unsigned long) &tps65021_drv_data,},
Marcus Folkesson437afd22011-08-08 20:29:35 +0200689 {.name = "tps65020",
690 .driver_data = (unsigned long) &tps65020_drv_data},
Liam Girdwood9e108d32009-08-24 10:31:34 +0100691 { },
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530692};
693
694MODULE_DEVICE_TABLE(i2c, tps_65023_id);
695
696static struct i2c_driver tps_65023_i2c_driver = {
697 .driver = {
698 .name = "tps65023",
699 .owner = THIS_MODULE,
700 },
701 .probe = tps_65023_probe,
702 .remove = __devexit_p(tps_65023_remove),
Liam Girdwood9e108d32009-08-24 10:31:34 +0100703 .id_table = tps_65023_id,
Anuj Aggarwal30e65992009-08-21 00:39:31 +0530704};
705
706/**
707 * tps_65023_init
708 *
709 * Module init function
710 */
711static int __init tps_65023_init(void)
712{
713 return i2c_add_driver(&tps_65023_i2c_driver);
714}
715subsys_initcall(tps_65023_init);
716
717/**
718 * tps_65023_cleanup
719 *
720 * Module exit function
721 */
722static void __exit tps_65023_cleanup(void)
723{
724 i2c_del_driver(&tps_65023_i2c_driver);
725}
726module_exit(tps_65023_cleanup);
727
728MODULE_AUTHOR("Texas Instruments");
729MODULE_DESCRIPTION("TPS65023 voltage regulator driver");
Liam Girdwood9e108d32009-08-24 10:31:34 +0100730MODULE_LICENSE("GPL v2");