blob: 49bcdb034895e3757fe44f8d85f3f209e8267277 [file] [log] [blame]
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +02001/*
2 * Regulator driver for National Semiconductors LP3971 PMIC chip
3 *
4 * Copyright (C) 2009 Samsung Electronics
5 * Author: Marek Szyprowski <m.szyprowski@samsung.com>
6 *
7 * Based on wm8350.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/bug.h>
16#include <linux/err.h>
17#include <linux/i2c.h>
18#include <linux/kernel.h>
Paul Gortmaker65602c32011-07-17 16:28:23 -040019#include <linux/module.h>
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +020020#include <linux/regulator/driver.h>
21#include <linux/regulator/lp3971.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +020023
24struct lp3971 {
25 struct device *dev;
26 struct mutex io_lock;
27 struct i2c_client *i2c;
28 int num_regulators;
29 struct regulator_dev **rdev;
30};
31
32static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg);
33static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
34
35#define LP3971_SYS_CONTROL1_REG 0x07
36
37/* System control register 1 initial value,
38 bits 4 and 5 are EPROM programmable */
39#define SYS_CONTROL1_INIT_VAL 0x40
40#define SYS_CONTROL1_INIT_MASK 0xCF
41
42#define LP3971_BUCK_VOL_ENABLE_REG 0x10
43#define LP3971_BUCK_VOL_CHANGE_REG 0x20
44
45/* Voltage control registers shift:
46 LP3971_BUCK1 -> 0
47 LP3971_BUCK2 -> 4
48 LP3971_BUCK3 -> 6
49*/
Axel Lin451a73c2010-03-11 09:50:07 +080050#define BUCK_VOL_CHANGE_SHIFT(x) (((!!x) << 2) | (x & ~0x01))
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +020051#define BUCK_VOL_CHANGE_FLAG_GO 0x01
52#define BUCK_VOL_CHANGE_FLAG_TARGET 0x02
53#define BUCK_VOL_CHANGE_FLAG_MASK 0x03
54
55#define LP3971_BUCK1_BASE 0x23
56#define LP3971_BUCK2_BASE 0x29
57#define LP3971_BUCK3_BASE 0x32
58
Tobias Klauser6faa7e02009-12-23 14:13:17 +010059static const int buck_base_addr[] = {
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +020060 LP3971_BUCK1_BASE,
61 LP3971_BUCK2_BASE,
62 LP3971_BUCK3_BASE,
63};
64
65#define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
66#define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
67
Tobias Klauser6faa7e02009-12-23 14:13:17 +010068static const int buck_voltage_map[] = {
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +020069 0, 800, 850, 900, 950, 1000, 1050, 1100,
70 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
71 1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
72 3000, 3300,
73};
74
75#define BUCK_TARGET_VOL_MASK 0x3f
76#define BUCK_TARGET_VOL_MIN_IDX 0x01
77#define BUCK_TARGET_VOL_MAX_IDX 0x19
78
79#define LP3971_BUCK_RAMP_REG(x) (buck_base_addr[x]+2)
80
81#define LP3971_LDO_ENABLE_REG 0x12
82#define LP3971_LDO_VOL_CONTR_BASE 0x39
83
84/* Voltage control registers:
85 LP3971_LDO1 -> LP3971_LDO_VOL_CONTR_BASE + 0
86 LP3971_LDO2 -> LP3971_LDO_VOL_CONTR_BASE + 0
87 LP3971_LDO3 -> LP3971_LDO_VOL_CONTR_BASE + 1
88 LP3971_LDO4 -> LP3971_LDO_VOL_CONTR_BASE + 1
89 LP3971_LDO5 -> LP3971_LDO_VOL_CONTR_BASE + 2
90*/
91#define LP3971_LDO_VOL_CONTR_REG(x) (LP3971_LDO_VOL_CONTR_BASE + (x >> 1))
92
93/* Voltage control registers shift:
94 LP3971_LDO1 -> 0, LP3971_LDO2 -> 4
95 LP3971_LDO3 -> 0, LP3971_LDO4 -> 4
96 LP3971_LDO5 -> 0
97*/
98#define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
99#define LDO_VOL_CONTR_MASK 0x0f
100
Tobias Klauser6faa7e02009-12-23 14:13:17 +0100101static const int ldo45_voltage_map[] = {
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200102 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
103 1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
104};
105
Tobias Klauser6faa7e02009-12-23 14:13:17 +0100106static const int ldo123_voltage_map[] = {
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200107 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
108 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
109};
110
Tobias Klauser6faa7e02009-12-23 14:13:17 +0100111static const int *ldo_voltage_map[] = {
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200112 ldo123_voltage_map, /* LDO1 */
113 ldo123_voltage_map, /* LDO2 */
114 ldo123_voltage_map, /* LDO3 */
115 ldo45_voltage_map, /* LDO4 */
116 ldo45_voltage_map, /* LDO5 */
117};
118
119#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
120
121#define LDO_VOL_MIN_IDX 0x00
122#define LDO_VOL_MAX_IDX 0x0f
123
124static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
125{
126 int ldo = rdev_get_id(dev) - LP3971_LDO1;
Axel Lindd8e2312012-03-23 10:49:54 +0800127
128 if (index > LDO_VOL_MAX_IDX)
129 return -EINVAL;
130
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200131 return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
132}
133
134static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
135{
136 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
137 int ldo = rdev_get_id(dev) - LP3971_LDO1;
138 u16 mask = 1 << (1 + ldo);
139 u16 val;
140
141 val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG);
142 return (val & mask) != 0;
143}
144
145static int lp3971_ldo_enable(struct regulator_dev *dev)
146{
147 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
148 int ldo = rdev_get_id(dev) - LP3971_LDO1;
149 u16 mask = 1 << (1 + ldo);
150
151 return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask);
152}
153
154static int lp3971_ldo_disable(struct regulator_dev *dev)
155{
156 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
157 int ldo = rdev_get_id(dev) - LP3971_LDO1;
158 u16 mask = 1 << (1 + ldo);
159
160 return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0);
161}
162
163static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
164{
165 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
166 int ldo = rdev_get_id(dev) - LP3971_LDO1;
167 u16 val, reg;
168
169 reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
170 val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
171
172 return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
173}
174
Axel Lindd8e2312012-03-23 10:49:54 +0800175static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
176 unsigned int selector)
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200177{
178 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
179 int ldo = rdev_get_id(dev) - LP3971_LDO1;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000180
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200181 return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
Axel Lincdb868f2010-03-09 16:53:59 +0800182 LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
Axel Lindd8e2312012-03-23 10:49:54 +0800183 selector << LDO_VOL_CONTR_SHIFT(ldo));
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200184}
185
186static struct regulator_ops lp3971_ldo_ops = {
187 .list_voltage = lp3971_ldo_list_voltage,
188 .is_enabled = lp3971_ldo_is_enabled,
189 .enable = lp3971_ldo_enable,
190 .disable = lp3971_ldo_disable,
191 .get_voltage = lp3971_ldo_get_voltage,
Axel Lindd8e2312012-03-23 10:49:54 +0800192 .set_voltage_sel = lp3971_ldo_set_voltage_sel,
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200193};
194
195static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
196{
Axel Lindd8e2312012-03-23 10:49:54 +0800197 if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX)
198 return -EINVAL;
199
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200200 return 1000 * buck_voltage_map[index];
201}
202
203static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
204{
205 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
206 int buck = rdev_get_id(dev) - LP3971_DCDC1;
207 u16 mask = 1 << (buck * 2);
208 u16 val;
209
210 val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG);
211 return (val & mask) != 0;
212}
213
214static int lp3971_dcdc_enable(struct regulator_dev *dev)
215{
216 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
217 int buck = rdev_get_id(dev) - LP3971_DCDC1;
218 u16 mask = 1 << (buck * 2);
219
220 return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask);
221}
222
223static int lp3971_dcdc_disable(struct regulator_dev *dev)
224{
225 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
226 int buck = rdev_get_id(dev) - LP3971_DCDC1;
227 u16 mask = 1 << (buck * 2);
228
229 return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0);
230}
231
232static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
233{
234 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
235 int buck = rdev_get_id(dev) - LP3971_DCDC1;
236 u16 reg;
237 int val;
238
239 reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck));
240 reg &= BUCK_TARGET_VOL_MASK;
241
242 if (reg <= BUCK_TARGET_VOL_MAX_IDX)
243 val = 1000 * buck_voltage_map[reg];
244 else {
245 val = 0;
246 dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
247 }
248
249 return val;
250}
251
Axel Lindd8e2312012-03-23 10:49:54 +0800252static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
253 unsigned int selector)
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200254{
255 struct lp3971 *lp3971 = rdev_get_drvdata(dev);
256 int buck = rdev_get_id(dev) - LP3971_DCDC1;
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200257 int ret;
258
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200259 ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
Axel Lindd8e2312012-03-23 10:49:54 +0800260 BUCK_TARGET_VOL_MASK, selector);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200261 if (ret)
262 return ret;
263
264 ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
265 BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
266 BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck));
267 if (ret)
268 return ret;
269
270 return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
271 BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
272 0 << BUCK_VOL_CHANGE_SHIFT(buck));
273}
274
275static struct regulator_ops lp3971_dcdc_ops = {
276 .list_voltage = lp3971_dcdc_list_voltage,
277 .is_enabled = lp3971_dcdc_is_enabled,
278 .enable = lp3971_dcdc_enable,
279 .disable = lp3971_dcdc_disable,
280 .get_voltage = lp3971_dcdc_get_voltage,
Axel Lindd8e2312012-03-23 10:49:54 +0800281 .set_voltage_sel = lp3971_dcdc_set_voltage_sel,
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200282};
283
284static struct regulator_desc regulators[] = {
285 {
286 .name = "LDO1",
287 .id = LP3971_LDO1,
288 .ops = &lp3971_ldo_ops,
289 .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
290 .type = REGULATOR_VOLTAGE,
291 .owner = THIS_MODULE,
292 },
293 {
294 .name = "LDO2",
295 .id = LP3971_LDO2,
296 .ops = &lp3971_ldo_ops,
297 .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
298 .type = REGULATOR_VOLTAGE,
299 .owner = THIS_MODULE,
300 },
301 {
302 .name = "LDO3",
303 .id = LP3971_LDO3,
304 .ops = &lp3971_ldo_ops,
305 .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
306 .type = REGULATOR_VOLTAGE,
307 .owner = THIS_MODULE,
308 },
309 {
310 .name = "LDO4",
311 .id = LP3971_LDO4,
312 .ops = &lp3971_ldo_ops,
313 .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
314 .type = REGULATOR_VOLTAGE,
315 .owner = THIS_MODULE,
316 },
317 {
318 .name = "LDO5",
319 .id = LP3971_LDO5,
320 .ops = &lp3971_ldo_ops,
321 .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
322 .type = REGULATOR_VOLTAGE,
323 .owner = THIS_MODULE,
324 },
325 {
326 .name = "DCDC1",
327 .id = LP3971_DCDC1,
328 .ops = &lp3971_dcdc_ops,
329 .n_voltages = ARRAY_SIZE(buck_voltage_map),
330 .type = REGULATOR_VOLTAGE,
331 .owner = THIS_MODULE,
332 },
333 {
334 .name = "DCDC2",
335 .id = LP3971_DCDC2,
336 .ops = &lp3971_dcdc_ops,
337 .n_voltages = ARRAY_SIZE(buck_voltage_map),
338 .type = REGULATOR_VOLTAGE,
339 .owner = THIS_MODULE,
340 },
341 {
342 .name = "DCDC3",
343 .id = LP3971_DCDC3,
344 .ops = &lp3971_dcdc_ops,
345 .n_voltages = ARRAY_SIZE(buck_voltage_map),
346 .type = REGULATOR_VOLTAGE,
347 .owner = THIS_MODULE,
348 },
349};
350
351static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
352 u16 *dest)
353{
354 int ret;
355
356 if (count != 1)
357 return -EIO;
358 ret = i2c_smbus_read_byte_data(i2c, reg);
Axel Lin27ef7f02010-08-06 08:09:14 +0800359 if (ret < 0)
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200360 return -EIO;
361
362 *dest = ret;
363 return 0;
364}
365
366static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count,
367 const u16 *src)
368{
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200369 if (count != 1)
370 return -EIO;
Axel Lin1bddc2f2010-08-09 17:01:21 +0800371 return i2c_smbus_write_byte_data(i2c, reg, *src);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200372}
373
374static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg)
375{
376 u16 val = 0;
377
378 mutex_lock(&lp3971->io_lock);
379
380 lp3971_i2c_read(lp3971->i2c, reg, 1, &val);
381
382 dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x\n", (int)reg,
383 (unsigned)val&0xff);
384
385 mutex_unlock(&lp3971->io_lock);
386
387 return val & 0xff;
388}
389
390static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
391{
392 u16 tmp;
393 int ret;
394
395 mutex_lock(&lp3971->io_lock);
396
397 ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp);
398 tmp = (tmp & ~mask) | val;
399 if (ret == 0) {
400 ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp);
401 dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg,
402 (unsigned)val&0xff);
403 }
404 mutex_unlock(&lp3971->io_lock);
405
406 return ret;
407}
408
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800409static int __devinit setup_regulators(struct lp3971 *lp3971,
410 struct lp3971_platform_data *pdata)
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200411{
412 int i, err;
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800413
414 lp3971->num_regulators = pdata->num_regulators;
415 lp3971->rdev = kcalloc(pdata->num_regulators,
416 sizeof(struct regulator_dev *), GFP_KERNEL);
Dan Carpenter67e46f32010-03-07 15:36:45 +0300417 if (!lp3971->rdev) {
418 err = -ENOMEM;
419 goto err_nomem;
420 }
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200421
422 /* Instantiate the regulators */
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800423 for (i = 0; i < pdata->num_regulators; i++) {
424 struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
425 lp3971->rdev[i] = regulator_register(&regulators[reg->id],
Rajendra Nayak2c043bc2011-11-18 16:47:19 +0530426 lp3971->dev, reg->initdata, lp3971, NULL);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200427
Julia Lawalld662fc82009-11-21 22:18:44 +0100428 if (IS_ERR(lp3971->rdev[i])) {
429 err = PTR_ERR(lp3971->rdev[i]);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200430 dev_err(lp3971->dev, "regulator init failed: %d\n",
431 err);
432 goto error;
433 }
434 }
435
436 return 0;
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800437
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200438error:
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800439 while (--i >= 0)
440 regulator_unregister(lp3971->rdev[i]);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200441 kfree(lp3971->rdev);
442 lp3971->rdev = NULL;
Dan Carpenter67e46f32010-03-07 15:36:45 +0300443err_nomem:
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200444 return err;
445}
446
447static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
448 const struct i2c_device_id *id)
449{
450 struct lp3971 *lp3971;
451 struct lp3971_platform_data *pdata = i2c->dev.platform_data;
452 int ret;
453 u16 val;
454
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800455 if (!pdata) {
456 dev_dbg(&i2c->dev, "No platform init data supplied\n");
457 return -ENODEV;
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200458 }
459
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800460 lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
461 if (lp3971 == NULL)
462 return -ENOMEM;
463
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200464 lp3971->i2c = i2c;
465 lp3971->dev = &i2c->dev;
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200466
467 mutex_init(&lp3971->io_lock);
468
469 /* Detect LP3971 */
470 ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val);
471 if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL)
472 ret = -ENODEV;
473 if (ret < 0) {
474 dev_err(&i2c->dev, "failed to detect device\n");
475 goto err_detect;
476 }
477
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800478 ret = setup_regulators(lp3971, pdata);
479 if (ret < 0)
480 goto err_detect;
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200481
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800482 i2c_set_clientdata(i2c, lp3971);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200483 return 0;
484
485err_detect:
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200486 kfree(lp3971);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200487 return ret;
488}
489
490static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
491{
492 struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
493 int i;
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800494
Dmitry Torokhovebbed042010-02-23 23:38:17 -0800495 for (i = 0; i < lp3971->num_regulators; i++)
496 regulator_unregister(lp3971->rdev[i]);
497
498 kfree(lp3971->rdev);
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200499 kfree(lp3971);
500
501 return 0;
502}
503
504static const struct i2c_device_id lp3971_i2c_id[] = {
505 { "lp3971", 0 },
506 { }
507};
508MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
509
510static struct i2c_driver lp3971_i2c_driver = {
511 .driver = {
512 .name = "LP3971",
513 .owner = THIS_MODULE,
514 },
515 .probe = lp3971_i2c_probe,
Liam Girdwood6113c3a2009-05-19 11:44:37 +0100516 .remove = __devexit_p(lp3971_i2c_remove),
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200517 .id_table = lp3971_i2c_id,
518};
519
520static int __init lp3971_module_init(void)
521{
Wolfram Sang12a1d932009-09-18 22:44:45 +0200522 int ret;
Marek Szyprowski0cbdf7b2009-05-19 07:33:55 +0200523
524 ret = i2c_add_driver(&lp3971_i2c_driver);
525 if (ret != 0)
526 pr_err("Failed to register I2C driver: %d\n", ret);
527
528 return ret;
529}
530module_init(lp3971_module_init);
531
532static void __exit lp3971_module_exit(void)
533{
534 i2c_del_driver(&lp3971_i2c_driver);
535}
536module_exit(lp3971_module_exit);
537
538MODULE_LICENSE("GPL");
539MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");
540MODULE_DESCRIPTION("LP3971 PMIC driver");