blob: b088b6c228c84d3ad1ba5afdc5f86b2a14824d91 [file] [log] [blame]
Linus Walleijd619bc12009-09-09 11:31:00 +02001/*
2 * drivers/regulator/ab3100.c
3 *
4 * Copyright (C) 2008-2009 ST-Ericsson AB
5 * License terms: GNU General Public License (GPL) version 2
6 * Low-level control of the AB3100 IC Low Dropout (LDO)
7 * regulators, external regulator and buck converter
8 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
9 * Author: Linus Walleij <linus.walleij@stericsson.com>
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/err.h>
Linus Walleijd619bc12009-09-09 11:31:00 +020016#include <linux/platform_device.h>
17#include <linux/regulator/driver.h>
Linus Walleij812f9e92010-05-01 18:26:07 +020018#include <linux/mfd/abx500.h>
Linus Walleijd619bc12009-09-09 11:31:00 +020019
20/* LDO registers and some handy masking definitions for AB3100 */
21#define AB3100_LDO_A 0x40
22#define AB3100_LDO_C 0x41
23#define AB3100_LDO_D 0x42
24#define AB3100_LDO_E 0x43
25#define AB3100_LDO_E_SLEEP 0x44
26#define AB3100_LDO_F 0x45
27#define AB3100_LDO_G 0x46
28#define AB3100_LDO_H 0x47
29#define AB3100_LDO_H_SLEEP_MODE 0
30#define AB3100_LDO_H_SLEEP_EN 2
31#define AB3100_LDO_ON 4
32#define AB3100_LDO_H_VSEL_AC 5
33#define AB3100_LDO_K 0x48
34#define AB3100_LDO_EXT 0x49
35#define AB3100_BUCK 0x4A
36#define AB3100_BUCK_SLEEP 0x4B
37#define AB3100_REG_ON_MASK 0x10
38
39/**
40 * struct ab3100_regulator
41 * A struct passed around the individual regulator functions
42 * @platform_device: platform device holding this regulator
Mattias Wallinfa661252010-05-01 18:26:20 +020043 * @dev: handle to the device
Linus Walleijd619bc12009-09-09 11:31:00 +020044 * @plfdata: AB3100 platform data passed in at probe time
45 * @regreg: regulator register number in the AB3100
46 * @fixed_voltage: a fixed voltage for this regulator, if this
47 * 0 the voltages array is used instead.
Linus Walleijd619bc12009-09-09 11:31:00 +020048 */
49struct ab3100_regulator {
50 struct regulator_dev *rdev;
Mattias Wallinfa661252010-05-01 18:26:20 +020051 struct device *dev;
Linus Walleijd619bc12009-09-09 11:31:00 +020052 struct ab3100_platform_data *plfdata;
53 u8 regreg;
54 int fixed_voltage;
Linus Walleijd619bc12009-09-09 11:31:00 +020055};
56
57/* The order in which registers are initialized */
58static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
59 AB3100_LDO_A,
60 AB3100_LDO_C,
61 AB3100_LDO_E,
62 AB3100_LDO_E_SLEEP,
63 AB3100_LDO_F,
64 AB3100_LDO_G,
65 AB3100_LDO_H,
66 AB3100_LDO_K,
67 AB3100_LDO_EXT,
68 AB3100_BUCK,
69 AB3100_BUCK_SLEEP,
70 AB3100_LDO_D,
71};
72
73/* Preset (hardware defined) voltages for these regulators */
74#define LDO_A_VOLTAGE 2750000
75#define LDO_C_VOLTAGE 2650000
76#define LDO_D_VOLTAGE 2650000
77
Axel Lina3beb742012-05-20 10:31:58 +080078static const unsigned int ldo_e_buck_typ_voltages[] = {
Linus Walleijd619bc12009-09-09 11:31:00 +020079 1800000,
80 1400000,
81 1300000,
82 1200000,
83 1100000,
84 1050000,
85 900000,
86};
87
Axel Lina3beb742012-05-20 10:31:58 +080088static const unsigned int ldo_f_typ_voltages[] = {
Linus Walleijd619bc12009-09-09 11:31:00 +020089 1800000,
90 1400000,
91 1300000,
92 1200000,
93 1100000,
94 1050000,
95 2500000,
96 2650000,
97};
98
Axel Lina3beb742012-05-20 10:31:58 +080099static const unsigned int ldo_g_typ_voltages[] = {
Linus Walleijd619bc12009-09-09 11:31:00 +0200100 2850000,
101 2750000,
102 1800000,
103 1500000,
104};
105
Axel Lina3beb742012-05-20 10:31:58 +0800106static const unsigned int ldo_h_typ_voltages[] = {
Linus Walleijd619bc12009-09-09 11:31:00 +0200107 2750000,
108 1800000,
109 1500000,
110 1200000,
111};
112
Axel Lina3beb742012-05-20 10:31:58 +0800113static const unsigned int ldo_k_typ_voltages[] = {
Linus Walleijd619bc12009-09-09 11:31:00 +0200114 2750000,
115 1800000,
116};
117
118
119/* The regulator devices */
120static struct ab3100_regulator
121ab3100_regulators[AB3100_NUM_REGULATORS] = {
122 {
123 .regreg = AB3100_LDO_A,
124 .fixed_voltage = LDO_A_VOLTAGE,
125 },
126 {
127 .regreg = AB3100_LDO_C,
128 .fixed_voltage = LDO_C_VOLTAGE,
129 },
130 {
131 .regreg = AB3100_LDO_D,
132 .fixed_voltage = LDO_D_VOLTAGE,
133 },
134 {
135 .regreg = AB3100_LDO_E,
Linus Walleijd619bc12009-09-09 11:31:00 +0200136 },
137 {
138 .regreg = AB3100_LDO_F,
Linus Walleijd619bc12009-09-09 11:31:00 +0200139 },
140 {
141 .regreg = AB3100_LDO_G,
Linus Walleijd619bc12009-09-09 11:31:00 +0200142 },
143 {
144 .regreg = AB3100_LDO_H,
Linus Walleijd619bc12009-09-09 11:31:00 +0200145 },
146 {
147 .regreg = AB3100_LDO_K,
Linus Walleijd619bc12009-09-09 11:31:00 +0200148 },
149 {
150 .regreg = AB3100_LDO_EXT,
151 /* No voltages for the external regulator */
152 },
153 {
154 .regreg = AB3100_BUCK,
Linus Walleijd619bc12009-09-09 11:31:00 +0200155 },
156};
157
158/*
159 * General functions for enable, disable and is_enabled used for
160 * LDO: A,C,E,F,G,H,K,EXT and BUCK
161 */
162static int ab3100_enable_regulator(struct regulator_dev *reg)
163{
164 struct ab3100_regulator *abreg = reg->reg_data;
165 int err;
166 u8 regval;
167
Mattias Wallinfa661252010-05-01 18:26:20 +0200168 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
Linus Walleijd619bc12009-09-09 11:31:00 +0200169 &regval);
170 if (err) {
171 dev_warn(&reg->dev, "failed to get regid %d value\n",
172 abreg->regreg);
173 return err;
174 }
175
176 /* The regulator is already on, no reason to go further */
177 if (regval & AB3100_REG_ON_MASK)
178 return 0;
179
180 regval |= AB3100_REG_ON_MASK;
181
Mattias Wallinfa661252010-05-01 18:26:20 +0200182 err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
Linus Walleijd619bc12009-09-09 11:31:00 +0200183 regval);
184 if (err) {
185 dev_warn(&reg->dev, "failed to set regid %d value\n",
186 abreg->regreg);
187 return err;
188 }
189
Linus Walleijd619bc12009-09-09 11:31:00 +0200190 return 0;
191}
192
193static int ab3100_disable_regulator(struct regulator_dev *reg)
194{
195 struct ab3100_regulator *abreg = reg->reg_data;
196 int err;
197 u8 regval;
198
199 /*
200 * LDO D is a special regulator. When it is disabled, the entire
201 * system is shut down. So this is handled specially.
202 */
Linus Walleij176f45b2009-10-28 17:30:15 +0100203 pr_info("Called ab3100_disable_regulator\n");
Linus Walleijd619bc12009-09-09 11:31:00 +0200204 if (abreg->regreg == AB3100_LDO_D) {
Linus Walleijd619bc12009-09-09 11:31:00 +0200205 dev_info(&reg->dev, "disabling LDO D - shut down system\n");
Linus Walleijd619bc12009-09-09 11:31:00 +0200206 /* Setting LDO D to 0x00 cuts the power to the SoC */
Mattias Wallinfa661252010-05-01 18:26:20 +0200207 return abx500_set_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200208 AB3100_LDO_D, 0x00U);
Linus Walleijd619bc12009-09-09 11:31:00 +0200209 }
210
211 /*
212 * All other regulators are handled here
213 */
Mattias Wallinfa661252010-05-01 18:26:20 +0200214 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
Linus Walleijd619bc12009-09-09 11:31:00 +0200215 &regval);
216 if (err) {
217 dev_err(&reg->dev, "unable to get register 0x%x\n",
218 abreg->regreg);
219 return err;
220 }
221 regval &= ~AB3100_REG_ON_MASK;
Mattias Wallinfa661252010-05-01 18:26:20 +0200222 return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
Linus Walleijd619bc12009-09-09 11:31:00 +0200223 regval);
224}
225
226static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
227{
228 struct ab3100_regulator *abreg = reg->reg_data;
229 u8 regval;
230 int err;
231
Mattias Wallinfa661252010-05-01 18:26:20 +0200232 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
Linus Walleijd619bc12009-09-09 11:31:00 +0200233 &regval);
234 if (err) {
235 dev_err(&reg->dev, "unable to get register 0x%x\n",
236 abreg->regreg);
237 return err;
238 }
239
240 return regval & AB3100_REG_ON_MASK;
241}
242
Linus Walleijd619bc12009-09-09 11:31:00 +0200243static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
244{
245 struct ab3100_regulator *abreg = reg->reg_data;
246 u8 regval;
247 int err;
248
249 /* Return the voltage for fixed regulators immediately */
250 if (abreg->fixed_voltage)
251 return abreg->fixed_voltage;
252
253 /*
254 * For variable types, read out setting and index into
255 * supplied voltage list.
256 */
Mattias Wallinfa661252010-05-01 18:26:20 +0200257 err = abx500_get_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200258 abreg->regreg, &regval);
259 if (err) {
260 dev_warn(&reg->dev,
261 "failed to get regulator value in register %02x\n",
262 abreg->regreg);
263 return err;
264 }
265
266 /* The 3 highest bits index voltages */
267 regval &= 0xE0;
268 regval >>= 5;
269
Axel Lina3beb742012-05-20 10:31:58 +0800270 if (regval >= reg->desc->n_voltages) {
Linus Walleijd619bc12009-09-09 11:31:00 +0200271 dev_err(&reg->dev,
272 "regulator register %02x contains an illegal voltage setting\n",
273 abreg->regreg);
274 return -EINVAL;
275 }
276
Axel Lina3beb742012-05-20 10:31:58 +0800277 return reg->desc->volt_table[regval];
Linus Walleijd619bc12009-09-09 11:31:00 +0200278}
279
Axel Lin1f793ff2012-03-20 10:14:40 +0800280static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
281 unsigned selector)
Linus Walleijd619bc12009-09-09 11:31:00 +0200282{
283 struct ab3100_regulator *abreg = reg->reg_data;
284 u8 regval;
285 int err;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000286
Mattias Wallinfa661252010-05-01 18:26:20 +0200287 err = abx500_get_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200288 abreg->regreg, &regval);
289 if (err) {
290 dev_warn(&reg->dev,
291 "failed to get regulator register %02x\n",
292 abreg->regreg);
293 return err;
294 }
295
296 /* The highest three bits control the variable regulators */
297 regval &= ~0xE0;
Axel Lin1f793ff2012-03-20 10:14:40 +0800298 regval |= (selector << 5);
Linus Walleijd619bc12009-09-09 11:31:00 +0200299
Mattias Wallinfa661252010-05-01 18:26:20 +0200300 err = abx500_set_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200301 abreg->regreg, regval);
302 if (err)
303 dev_warn(&reg->dev, "failed to set regulator register %02x\n",
304 abreg->regreg);
305
306 return err;
307}
308
309static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
310 int uV)
311{
312 struct ab3100_regulator *abreg = reg->reg_data;
313 u8 regval;
314 int err;
315 int bestindex;
316 u8 targetreg;
317
318 if (abreg->regreg == AB3100_LDO_E)
319 targetreg = AB3100_LDO_E_SLEEP;
320 else if (abreg->regreg == AB3100_BUCK)
321 targetreg = AB3100_BUCK_SLEEP;
322 else
323 return -EINVAL;
324
325 /* LDO E and BUCK have special suspend voltages you can set */
Axel Linb13296d2012-05-17 13:06:18 +0800326 bestindex = regulator_map_voltage_iterate(reg, uV, uV);
Linus Walleijd619bc12009-09-09 11:31:00 +0200327
Mattias Wallinfa661252010-05-01 18:26:20 +0200328 err = abx500_get_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200329 targetreg, &regval);
330 if (err) {
331 dev_warn(&reg->dev,
332 "failed to get regulator register %02x\n",
333 targetreg);
334 return err;
335 }
336
337 /* The highest three bits control the variable regulators */
338 regval &= ~0xE0;
339 regval |= (bestindex << 5);
340
Mattias Wallinfa661252010-05-01 18:26:20 +0200341 err = abx500_set_register_interruptible(abreg->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200342 targetreg, regval);
343 if (err)
344 dev_warn(&reg->dev, "failed to set regulator register %02x\n",
345 abreg->regreg);
346
347 return err;
348}
349
350/*
351 * The external regulator can just define a fixed voltage.
352 */
353static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
354{
355 struct ab3100_regulator *abreg = reg->reg_data;
356
357 return abreg->plfdata->external_voltage;
358}
359
Linus Walleij19c98822011-03-11 16:26:18 +0100360static int ab3100_enable_time_regulator(struct regulator_dev *reg)
361{
362 struct ab3100_regulator *abreg = reg->reg_data;
363
364 /* Per-regulator power on delay from spec */
365 switch (abreg->regreg) {
366 case AB3100_LDO_A: /* Fallthrough */
367 case AB3100_LDO_C: /* Fallthrough */
368 case AB3100_LDO_D: /* Fallthrough */
369 case AB3100_LDO_E: /* Fallthrough */
370 case AB3100_LDO_H: /* Fallthrough */
371 case AB3100_LDO_K:
372 return 200;
373 case AB3100_LDO_F:
374 return 600;
375 case AB3100_LDO_G:
376 return 400;
377 case AB3100_BUCK:
378 return 1000;
379 default:
380 break;
381 }
382 return 0;
383}
384
Linus Walleijd619bc12009-09-09 11:31:00 +0200385static struct regulator_ops regulator_ops_fixed = {
386 .enable = ab3100_enable_regulator,
387 .disable = ab3100_disable_regulator,
388 .is_enabled = ab3100_is_enabled_regulator,
389 .get_voltage = ab3100_get_voltage_regulator,
Linus Walleij19c98822011-03-11 16:26:18 +0100390 .enable_time = ab3100_enable_time_regulator,
Linus Walleijd619bc12009-09-09 11:31:00 +0200391};
392
393static struct regulator_ops regulator_ops_variable = {
394 .enable = ab3100_enable_regulator,
395 .disable = ab3100_disable_regulator,
396 .is_enabled = ab3100_is_enabled_regulator,
397 .get_voltage = ab3100_get_voltage_regulator,
Axel Lin1f793ff2012-03-20 10:14:40 +0800398 .set_voltage_sel = ab3100_set_voltage_regulator_sel,
Axel Lina3beb742012-05-20 10:31:58 +0800399 .list_voltage = regulator_list_voltage_table,
Linus Walleij19c98822011-03-11 16:26:18 +0100400 .enable_time = ab3100_enable_time_regulator,
Linus Walleijd619bc12009-09-09 11:31:00 +0200401};
402
403static struct regulator_ops regulator_ops_variable_sleepable = {
404 .enable = ab3100_enable_regulator,
405 .disable = ab3100_disable_regulator,
406 .is_enabled = ab3100_is_enabled_regulator,
407 .get_voltage = ab3100_get_voltage_regulator,
Axel Lin1f793ff2012-03-20 10:14:40 +0800408 .set_voltage_sel = ab3100_set_voltage_regulator_sel,
Linus Walleijd619bc12009-09-09 11:31:00 +0200409 .set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
Axel Lina3beb742012-05-20 10:31:58 +0800410 .list_voltage = regulator_list_voltage_table,
Linus Walleij19c98822011-03-11 16:26:18 +0100411 .enable_time = ab3100_enable_time_regulator,
Linus Walleijd619bc12009-09-09 11:31:00 +0200412};
413
414/*
415 * LDO EXT is an external regulator so it is really
416 * not possible to set any voltage locally here, AB3100
417 * is an on/off switch plain an simple. The external
418 * voltage is defined in the board set-up if any.
419 */
420static struct regulator_ops regulator_ops_external = {
421 .enable = ab3100_enable_regulator,
422 .disable = ab3100_disable_regulator,
423 .is_enabled = ab3100_is_enabled_regulator,
424 .get_voltage = ab3100_get_voltage_regulator_external,
425};
426
427static struct regulator_desc
428ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
429 {
430 .name = "LDO_A",
431 .id = AB3100_LDO_A,
432 .ops = &regulator_ops_fixed,
433 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800434 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200435 },
436 {
437 .name = "LDO_C",
438 .id = AB3100_LDO_C,
439 .ops = &regulator_ops_fixed,
440 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800441 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200442 },
443 {
444 .name = "LDO_D",
445 .id = AB3100_LDO_D,
446 .ops = &regulator_ops_fixed,
447 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800448 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200449 },
450 {
451 .name = "LDO_E",
452 .id = AB3100_LDO_E,
453 .ops = &regulator_ops_variable_sleepable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200454 .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
Axel Lina3beb742012-05-20 10:31:58 +0800455 .volt_table = ldo_e_buck_typ_voltages,
Linus Walleijd619bc12009-09-09 11:31:00 +0200456 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800457 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200458 },
459 {
460 .name = "LDO_F",
461 .id = AB3100_LDO_F,
462 .ops = &regulator_ops_variable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200463 .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages),
Axel Lina3beb742012-05-20 10:31:58 +0800464 .volt_table = ldo_f_typ_voltages,
Linus Walleijd619bc12009-09-09 11:31:00 +0200465 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800466 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200467 },
468 {
469 .name = "LDO_G",
470 .id = AB3100_LDO_G,
471 .ops = &regulator_ops_variable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200472 .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages),
Axel Lina3beb742012-05-20 10:31:58 +0800473 .volt_table = ldo_g_typ_voltages,
Linus Walleijd619bc12009-09-09 11:31:00 +0200474 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800475 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200476 },
477 {
478 .name = "LDO_H",
479 .id = AB3100_LDO_H,
480 .ops = &regulator_ops_variable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200481 .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages),
Axel Lina3beb742012-05-20 10:31:58 +0800482 .volt_table = ldo_h_typ_voltages,
Linus Walleijd619bc12009-09-09 11:31:00 +0200483 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800484 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200485 },
486 {
487 .name = "LDO_K",
488 .id = AB3100_LDO_K,
489 .ops = &regulator_ops_variable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200490 .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages),
Axel Lina3beb742012-05-20 10:31:58 +0800491 .volt_table = ldo_k_typ_voltages,
Linus Walleijd619bc12009-09-09 11:31:00 +0200492 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800493 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200494 },
495 {
496 .name = "LDO_EXT",
497 .id = AB3100_LDO_EXT,
498 .ops = &regulator_ops_external,
499 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800500 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200501 },
502 {
503 .name = "BUCK",
504 .id = AB3100_BUCK,
505 .ops = &regulator_ops_variable_sleepable,
Linus Walleij75f2ba82009-09-17 09:17:33 +0200506 .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
Linus Walleijd619bc12009-09-09 11:31:00 +0200507 .type = REGULATOR_VOLTAGE,
Axel Lin64714352010-05-13 17:33:01 +0800508 .owner = THIS_MODULE,
Linus Walleijd619bc12009-09-09 11:31:00 +0200509 },
510};
511
512/*
513 * NOTE: the following functions are regulators pluralis - it is the
514 * binding to the AB3100 core driver and the parent platform device
515 * for all the different regulators.
516 */
517
Dmitry Torokhov98bf7c02010-02-23 23:37:50 -0800518static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
Linus Walleijd619bc12009-09-09 11:31:00 +0200519{
Samuel Ortiza771e362011-04-06 00:41:43 +0200520 struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
Mark Brownc1727082012-04-04 00:50:22 +0100521 struct regulator_config config = { };
Linus Walleijd619bc12009-09-09 11:31:00 +0200522 int err = 0;
523 u8 data;
524 int i;
525
526 /* Check chip state */
Mattias Wallinfa661252010-05-01 18:26:20 +0200527 err = abx500_get_register_interruptible(&pdev->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200528 AB3100_LDO_D, &data);
529 if (err) {
530 dev_err(&pdev->dev, "could not read initial status of LDO_D\n");
531 return err;
532 }
533 if (data & 0x10)
534 dev_notice(&pdev->dev,
535 "chip is already in active mode (Warm start)\n");
536 else
537 dev_notice(&pdev->dev,
538 "chip is in inactive mode (Cold start)\n");
539
540 /* Set up regulators */
541 for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
Mattias Wallinfa661252010-05-01 18:26:20 +0200542 err = abx500_set_register_interruptible(&pdev->dev, 0,
Linus Walleijd619bc12009-09-09 11:31:00 +0200543 ab3100_reg_init_order[i],
544 plfdata->reg_initvals[i]);
545 if (err) {
546 dev_err(&pdev->dev, "regulator initialization failed with error %d\n",
547 err);
548 return err;
549 }
550 }
551
Linus Walleijd619bc12009-09-09 11:31:00 +0200552 /* Register the regulators */
553 for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
554 struct ab3100_regulator *reg = &ab3100_regulators[i];
555 struct regulator_dev *rdev;
556
557 /*
558 * Initialize per-regulator struct.
559 * Inherit platform data, this comes down from the
560 * i2c boarddata, from the machine. So if you want to
561 * see what it looks like for a certain machine, go
562 * into the machine I2C setup.
563 */
Mattias Wallinfa661252010-05-01 18:26:20 +0200564 reg->dev = &pdev->dev;
Linus Walleijd619bc12009-09-09 11:31:00 +0200565 reg->plfdata = plfdata;
566
Mark Brownc1727082012-04-04 00:50:22 +0100567 config.dev = &pdev->dev;
568 config.driver_data = reg;
569 config.init_data = &plfdata->reg_constraints[i];
570
Linus Walleijd619bc12009-09-09 11:31:00 +0200571 /*
572 * Register the regulator, pass around
573 * the ab3100_regulator struct
574 */
Mark Brownc1727082012-04-04 00:50:22 +0100575 rdev = regulator_register(&ab3100_regulator_desc[i], &config);
Linus Walleijd619bc12009-09-09 11:31:00 +0200576 if (IS_ERR(rdev)) {
577 err = PTR_ERR(rdev);
578 dev_err(&pdev->dev,
579 "%s: failed to register regulator %s err %d\n",
580 __func__, ab3100_regulator_desc[i].name,
581 err);
Linus Walleijd619bc12009-09-09 11:31:00 +0200582 /* remove the already registered regulators */
Axel Linb3fcf3e2010-08-14 21:31:01 +0800583 while (--i >= 0)
Linus Walleijd619bc12009-09-09 11:31:00 +0200584 regulator_unregister(ab3100_regulators[i].rdev);
Linus Walleijd619bc12009-09-09 11:31:00 +0200585 return err;
586 }
587
588 /* Then set a pointer back to the registered regulator */
589 reg->rdev = rdev;
590 }
591
592 return 0;
593}
594
Dmitry Torokhov98bf7c02010-02-23 23:37:50 -0800595static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
Linus Walleijd619bc12009-09-09 11:31:00 +0200596{
597 int i;
598
599 for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
600 struct ab3100_regulator *reg = &ab3100_regulators[i];
601
602 regulator_unregister(reg->rdev);
603 }
604 return 0;
605}
606
607static struct platform_driver ab3100_regulators_driver = {
608 .driver = {
609 .name = "ab3100-regulators",
610 .owner = THIS_MODULE,
611 },
612 .probe = ab3100_regulators_probe,
Dmitry Torokhov98bf7c02010-02-23 23:37:50 -0800613 .remove = __devexit_p(ab3100_regulators_remove),
Linus Walleijd619bc12009-09-09 11:31:00 +0200614};
615
616static __init int ab3100_regulators_init(void)
617{
618 return platform_driver_register(&ab3100_regulators_driver);
619}
620
621static __exit void ab3100_regulators_exit(void)
622{
Linus Walleij176f45b2009-10-28 17:30:15 +0100623 platform_driver_unregister(&ab3100_regulators_driver);
Linus Walleijd619bc12009-09-09 11:31:00 +0200624}
625
626subsys_initcall(ab3100_regulators_init);
627module_exit(ab3100_regulators_exit);
628
629MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
630MODULE_DESCRIPTION("AB3100 Regulator driver");
631MODULE_LICENSE("GPL");
632MODULE_ALIAS("platform:ab3100-regulators");