Blame view

drivers/regulator/lp3971.c 13.7 KB
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * Regulator driver for National Semiconductors LP3971 PMIC chip
   *
   *  Copyright (C) 2009 Samsung Electronics
   *  Author: Marek Szyprowski <m.szyprowski@samsung.com>
   *
   * Based on wm8350.c
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   */
  
  #include <linux/bug.h>
  #include <linux/err.h>
  #include <linux/i2c.h>
  #include <linux/kernel.h>
65602c32e   Paul Gortmaker   regulator: Add mo...
19
  #include <linux/module.h>
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
20
21
  #include <linux/regulator/driver.h>
  #include <linux/regulator/lp3971.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  
  struct lp3971 {
  	struct device *dev;
  	struct mutex io_lock;
  	struct i2c_client *i2c;
  	int num_regulators;
  	struct regulator_dev **rdev;
  };
  
  static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg);
  static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
  
  #define LP3971_SYS_CONTROL1_REG 0x07
  
  /* System control register 1 initial value,
     bits 4 and 5 are EPROM programmable */
  #define SYS_CONTROL1_INIT_VAL 0x40
  #define SYS_CONTROL1_INIT_MASK 0xCF
  
  #define LP3971_BUCK_VOL_ENABLE_REG 0x10
  #define LP3971_BUCK_VOL_CHANGE_REG 0x20
  
  /*	Voltage control registers shift:
  	LP3971_BUCK1 -> 0
  	LP3971_BUCK2 -> 4
  	LP3971_BUCK3 -> 6
  */
451a73cd4   Axel Lin   lp3971: Fix BUCK_...
50
  #define BUCK_VOL_CHANGE_SHIFT(x) (((!!x) << 2) | (x & ~0x01))
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
51
52
53
54
55
56
57
  #define BUCK_VOL_CHANGE_FLAG_GO 0x01
  #define BUCK_VOL_CHANGE_FLAG_TARGET 0x02
  #define BUCK_VOL_CHANGE_FLAG_MASK 0x03
  
  #define LP3971_BUCK1_BASE 0x23
  #define LP3971_BUCK2_BASE 0x29
  #define LP3971_BUCK3_BASE 0x32
6faa7e0a4   Tobias Klauser   regulator/lp3971:...
58
  static const int buck_base_addr[] = {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
59
60
61
62
63
64
65
  	LP3971_BUCK1_BASE,
  	LP3971_BUCK2_BASE,
  	LP3971_BUCK3_BASE,
  };
  
  #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
  #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
6faa7e0a4   Tobias Klauser   regulator/lp3971:...
66
  static const int buck_voltage_map[] = {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  	   0,  800,  850,  900,  950, 1000, 1050, 1100,
  	1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
  	1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
  	3000, 3300,
  };
  
  #define BUCK_TARGET_VOL_MASK 0x3f
  #define BUCK_TARGET_VOL_MIN_IDX 0x01
  #define BUCK_TARGET_VOL_MAX_IDX 0x19
  
  #define LP3971_BUCK_RAMP_REG(x)	(buck_base_addr[x]+2)
  
  #define LP3971_LDO_ENABLE_REG 0x12
  #define LP3971_LDO_VOL_CONTR_BASE 0x39
  
  /*	Voltage control registers:
  	LP3971_LDO1 -> LP3971_LDO_VOL_CONTR_BASE + 0
  	LP3971_LDO2 -> LP3971_LDO_VOL_CONTR_BASE + 0
  	LP3971_LDO3 -> LP3971_LDO_VOL_CONTR_BASE + 1
  	LP3971_LDO4 -> LP3971_LDO_VOL_CONTR_BASE + 1
  	LP3971_LDO5 -> LP3971_LDO_VOL_CONTR_BASE + 2
  */
  #define LP3971_LDO_VOL_CONTR_REG(x)	(LP3971_LDO_VOL_CONTR_BASE + (x >> 1))
  
  /*	Voltage control registers shift:
  	LP3971_LDO1 -> 0, LP3971_LDO2 -> 4
  	LP3971_LDO3 -> 0, LP3971_LDO4 -> 4
  	LP3971_LDO5 -> 0
  */
  #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
  #define LDO_VOL_CONTR_MASK 0x0f
6faa7e0a4   Tobias Klauser   regulator/lp3971:...
98
  static const int ldo45_voltage_map[] = {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
99
100
101
  	1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
  	1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
  };
6faa7e0a4   Tobias Klauser   regulator/lp3971:...
102
  static const int ldo123_voltage_map[] = {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
103
104
105
  	1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
  	2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
  };
6faa7e0a4   Tobias Klauser   regulator/lp3971:...
106
  static const int *ldo_voltage_map[] = {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  	ldo123_voltage_map, /* LDO1 */
  	ldo123_voltage_map, /* LDO2 */
  	ldo123_voltage_map, /* LDO3 */
  	ldo45_voltage_map, /* LDO4 */
  	ldo45_voltage_map, /* LDO5 */
  };
  
  #define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
  
  #define LDO_VOL_MIN_IDX 0x00
  #define LDO_VOL_MAX_IDX 0x0f
  
  static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
  {
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
  }
  
  static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	u16 mask = 1 << (1 + ldo);
  	u16 val;
  
  	val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG);
  	return (val & mask) != 0;
  }
  
  static int lp3971_ldo_enable(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	u16 mask = 1 << (1 + ldo);
  
  	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask);
  }
  
  static int lp3971_ldo_disable(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	u16 mask = 1 << (1 + ldo);
  
  	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0);
  }
  
  static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	u16 val, reg;
  
  	reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
  	val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
  
  	return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
  }
  
  static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
3a93f2a9f   Mark Brown   regulator: Report...
167
168
  				  int min_uV, int max_uV,
  				  unsigned int *selector)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int ldo = rdev_get_id(dev) - LP3971_LDO1;
  	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
  	const int *vol_map = LDO_VOL_VALUE_MAP(ldo);
  	u16 val;
  
  	if (min_vol < vol_map[LDO_VOL_MIN_IDX] ||
  	    min_vol > vol_map[LDO_VOL_MAX_IDX])
  		return -EINVAL;
  
  	for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++)
  		if (vol_map[val] >= min_vol)
  			break;
62737d445   Roel Kluin   regulator/lp3971:...
183
  	if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
184
  		return -EINVAL;
3a93f2a9f   Mark Brown   regulator: Report...
185
  	*selector = val;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
186
  	return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
cdb868f58   Axel Lin   lp3971: Fix setti...
187
188
  			LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
  			val << LDO_VOL_CONTR_SHIFT(ldo));
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  }
  
  static struct regulator_ops lp3971_ldo_ops = {
  	.list_voltage = lp3971_ldo_list_voltage,
  	.is_enabled = lp3971_ldo_is_enabled,
  	.enable = lp3971_ldo_enable,
  	.disable = lp3971_ldo_disable,
  	.get_voltage = lp3971_ldo_get_voltage,
  	.set_voltage = lp3971_ldo_set_voltage,
  };
  
  static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
  {
  	return 1000 * buck_voltage_map[index];
  }
  
  static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int buck = rdev_get_id(dev) - LP3971_DCDC1;
  	u16 mask = 1 << (buck * 2);
  	u16 val;
  
  	val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG);
  	return (val & mask) != 0;
  }
  
  static int lp3971_dcdc_enable(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int buck = rdev_get_id(dev) - LP3971_DCDC1;
  	u16 mask = 1 << (buck * 2);
  
  	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask);
  }
  
  static int lp3971_dcdc_disable(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int buck = rdev_get_id(dev) - LP3971_DCDC1;
  	u16 mask = 1 << (buck * 2);
  
  	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0);
  }
  
  static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int buck = rdev_get_id(dev) - LP3971_DCDC1;
  	u16 reg;
  	int val;
  
  	reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck));
  	reg &= BUCK_TARGET_VOL_MASK;
  
  	if (reg <= BUCK_TARGET_VOL_MAX_IDX)
  		val = 1000 * buck_voltage_map[reg];
  	else {
  		val = 0;
  		dev_warn(&dev->dev, "chip reported incorrect voltage value.
  ");
  	}
  
  	return val;
  }
  
  static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
3a93f2a9f   Mark Brown   regulator: Report...
256
257
  				   int min_uV, int max_uV,
  				   unsigned int *selector)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  {
  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
  	int buck = rdev_get_id(dev) - LP3971_DCDC1;
  	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
  	const int *vol_map = buck_voltage_map;
  	u16 val;
  	int ret;
  
  	if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
  	    min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
  		return -EINVAL;
  
  	for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX;
  	     val++)
  		if (vol_map[val] >= min_vol)
  			break;
62737d445   Roel Kluin   regulator/lp3971:...
274
  	if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
275
  		return -EINVAL;
3a93f2a9f   Mark Brown   regulator: Report...
276
  	*selector = val;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  	ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
  	       BUCK_TARGET_VOL_MASK, val);
  	if (ret)
  		return ret;
  
  	ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
  	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
  	       BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck));
  	if (ret)
  		return ret;
  
  	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
  	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
  	       0 << BUCK_VOL_CHANGE_SHIFT(buck));
  }
  
  static struct regulator_ops lp3971_dcdc_ops = {
  	.list_voltage = lp3971_dcdc_list_voltage,
  	.is_enabled = lp3971_dcdc_is_enabled,
  	.enable = lp3971_dcdc_enable,
  	.disable = lp3971_dcdc_disable,
  	.get_voltage = lp3971_dcdc_get_voltage,
  	.set_voltage = lp3971_dcdc_set_voltage,
  };
  
  static struct regulator_desc regulators[] = {
  	{
  		.name = "LDO1",
  		.id = LP3971_LDO1,
  		.ops = &lp3971_ldo_ops,
  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "LDO2",
  		.id = LP3971_LDO2,
  		.ops = &lp3971_ldo_ops,
  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "LDO3",
  		.id = LP3971_LDO3,
  		.ops = &lp3971_ldo_ops,
  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "LDO4",
  		.id = LP3971_LDO4,
  		.ops = &lp3971_ldo_ops,
  		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "LDO5",
  		.id = LP3971_LDO5,
  		.ops = &lp3971_ldo_ops,
  		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "DCDC1",
  		.id = LP3971_DCDC1,
  		.ops = &lp3971_dcdc_ops,
  		.n_voltages = ARRAY_SIZE(buck_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "DCDC2",
  		.id = LP3971_DCDC2,
  		.ops = &lp3971_dcdc_ops,
  		.n_voltages = ARRAY_SIZE(buck_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "DCDC3",
  		.id = LP3971_DCDC3,
  		.ops = &lp3971_dcdc_ops,
  		.n_voltages = ARRAY_SIZE(buck_voltage_map),
  		.type = REGULATOR_VOLTAGE,
  		.owner = THIS_MODULE,
  	},
  };
  
  static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
  	u16 *dest)
  {
  	int ret;
  
  	if (count != 1)
  		return -EIO;
  	ret = i2c_smbus_read_byte_data(i2c, reg);
27ef7f00c   Axel Lin   regulator: lp3971...
377
  	if (ret < 0)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
378
379
380
381
382
383
384
385
386
  		return -EIO;
  
  	*dest = ret;
  	return 0;
  }
  
  static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count,
  	const u16 *src)
  {
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
387
388
  	if (count != 1)
  		return -EIO;
1bddc2f5c   Axel Lin   regulator: lp3971...
389
  	return i2c_smbus_write_byte_data(i2c, reg, *src);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  }
  
  static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg)
  {
  	u16 val = 0;
  
  	mutex_lock(&lp3971->io_lock);
  
  	lp3971_i2c_read(lp3971->i2c, reg, 1, &val);
  
  	dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x
  ", (int)reg,
  		(unsigned)val&0xff);
  
  	mutex_unlock(&lp3971->io_lock);
  
  	return val & 0xff;
  }
  
  static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
  {
  	u16 tmp;
  	int ret;
  
  	mutex_lock(&lp3971->io_lock);
  
  	ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp);
  	tmp = (tmp & ~mask) | val;
  	if (ret == 0) {
  		ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp);
  		dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x
  ", (int)reg,
  			(unsigned)val&0xff);
  	}
  	mutex_unlock(&lp3971->io_lock);
  
  	return ret;
  }
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
428
429
  static int __devinit setup_regulators(struct lp3971 *lp3971,
  				      struct lp3971_platform_data *pdata)
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
430
431
  {
  	int i, err;
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
432
433
434
435
  
  	lp3971->num_regulators = pdata->num_regulators;
  	lp3971->rdev = kcalloc(pdata->num_regulators,
  				sizeof(struct regulator_dev *), GFP_KERNEL);
67e46f347   Dan Carpenter   regulator: handle...
436
437
438
439
  	if (!lp3971->rdev) {
  		err = -ENOMEM;
  		goto err_nomem;
  	}
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
440
441
  
  	/* Instantiate the regulators */
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
442
443
444
  	for (i = 0; i < pdata->num_regulators; i++) {
  		struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
  		lp3971->rdev[i] = regulator_register(&regulators[reg->id],
2c043bcbf   Rajendra Nayak   regulator: pass a...
445
  				lp3971->dev, reg->initdata, lp3971, NULL);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
446

d662fc82d   Julia Lawall   drivers/regulator...
447
448
  		if (IS_ERR(lp3971->rdev[i])) {
  			err = PTR_ERR(lp3971->rdev[i]);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
449
450
451
452
453
454
455
456
  			dev_err(lp3971->dev, "regulator init failed: %d
  ",
  				err);
  			goto error;
  		}
  	}
  
  	return 0;
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
457

0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
458
  error:
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
459
460
  	while (--i >= 0)
  		regulator_unregister(lp3971->rdev[i]);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
461
462
  	kfree(lp3971->rdev);
  	lp3971->rdev = NULL;
67e46f347   Dan Carpenter   regulator: handle...
463
  err_nomem:
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
464
465
466
467
468
469
470
471
472
473
  	return err;
  }
  
  static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
  			    const struct i2c_device_id *id)
  {
  	struct lp3971 *lp3971;
  	struct lp3971_platform_data *pdata = i2c->dev.platform_data;
  	int ret;
  	u16 val;
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
474
475
476
477
  	if (!pdata) {
  		dev_dbg(&i2c->dev, "No platform init data supplied
  ");
  		return -ENODEV;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
478
  	}
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
479
480
481
  	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
  	if (lp3971 == NULL)
  		return -ENOMEM;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
482
483
  	lp3971->i2c = i2c;
  	lp3971->dev = &i2c->dev;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
484
485
486
487
488
489
490
491
492
493
494
495
  
  	mutex_init(&lp3971->io_lock);
  
  	/* Detect LP3971 */
  	ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val);
  	if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL)
  		ret = -ENODEV;
  	if (ret < 0) {
  		dev_err(&i2c->dev, "failed to detect device
  ");
  		goto err_detect;
  	}
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
496
497
498
  	ret = setup_regulators(lp3971, pdata);
  	if (ret < 0)
  		goto err_detect;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
499

ebbed04fe   Dmitry Torokhov   Regulators: lp397...
500
  	i2c_set_clientdata(i2c, lp3971);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
501
502
503
  	return 0;
  
  err_detect:
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
504
  	kfree(lp3971);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
505
506
507
508
509
510
511
  	return ret;
  }
  
  static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
  {
  	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
  	int i;
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
512

0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
513
  	for (i = 0; i < lp3971->num_regulators; i++)
ebbed04fe   Dmitry Torokhov   Regulators: lp397...
514
  		regulator_unregister(lp3971->rdev[i]);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
515
  	kfree(lp3971->rdev);
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  	kfree(lp3971);
  
  	return 0;
  }
  
  static const struct i2c_device_id lp3971_i2c_id[] = {
         { "lp3971", 0 },
         { }
  };
  MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
  
  static struct i2c_driver lp3971_i2c_driver = {
  	.driver = {
  		.name = "LP3971",
  		.owner = THIS_MODULE,
  	},
  	.probe    = lp3971_i2c_probe,
6113c3a5a   Liam Girdwood   regulator: lp3971...
533
  	.remove   = __devexit_p(lp3971_i2c_remove),
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
534
535
536
537
538
  	.id_table = lp3971_i2c_id,
  };
  
  static int __init lp3971_module_init(void)
  {
12a1d933a   Wolfram Sang   regulator/lp3971:...
539
  	int ret;
0cbdf7bce   Marek Szyprowski   LP3971 PMIC regul...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  
  	ret = i2c_add_driver(&lp3971_i2c_driver);
  	if (ret != 0)
  		pr_err("Failed to register I2C driver: %d
  ", ret);
  
  	return ret;
  }
  module_init(lp3971_module_init);
  
  static void __exit lp3971_module_exit(void)
  {
  	i2c_del_driver(&lp3971_i2c_driver);
  }
  module_exit(lp3971_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");
  MODULE_DESCRIPTION("LP3971 PMIC driver");