blob: 283d9a51114becb0bcc25b6db24ad3a486926c1f [file] [log] [blame]
Sundar R IYERc789ca22010-07-13 21:48:56 +05301/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 *
Bengt Jonssone1159e62010-12-10 11:08:44 +01006 * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
7 * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
Sundar R IYERc789ca22010-07-13 21:48:56 +05308 *
9 * AB8500 peripheral regulators
10 *
Bengt Jonssone1159e62010-12-10 11:08:44 +010011 * AB8500 supports the following regulators:
Bengt Jonssonea05ef32011-03-10 14:43:31 +010012 * VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
Sundar R IYERc789ca22010-07-13 21:48:56 +053013 */
14#include <linux/init.h>
15#include <linux/kernel.h>
Paul Gortmaker65602c32011-07-17 16:28:23 -040016#include <linux/module.h>
Sundar R IYERc789ca22010-07-13 21:48:56 +053017#include <linux/err.h>
18#include <linux/platform_device.h>
Mattias Wallin47c16972010-09-10 17:47:56 +020019#include <linux/mfd/abx500.h>
Linus Walleijee66e652011-12-02 14:16:33 +010020#include <linux/mfd/abx500/ab8500.h>
Lee Jones3a8334b2012-05-17 14:45:16 +010021#include <linux/of.h>
22#include <linux/regulator/of_regulator.h>
Sundar R IYERc789ca22010-07-13 21:48:56 +053023#include <linux/regulator/driver.h>
24#include <linux/regulator/machine.h>
25#include <linux/regulator/ab8500.h>
Lee Jones3a8334b2012-05-17 14:45:16 +010026#include <linux/slab.h>
Sundar R IYERc789ca22010-07-13 21:48:56 +053027
28/**
29 * struct ab8500_regulator_info - ab8500 regulator information
Bengt Jonssone1159e62010-12-10 11:08:44 +010030 * @dev: device pointer
Sundar R IYERc789ca22010-07-13 21:48:56 +053031 * @desc: regulator description
Sundar R IYERc789ca22010-07-13 21:48:56 +053032 * @regulator_dev: regulator device
Emeric Vigierbd28a152013-03-21 15:58:59 +000033 * @is_enabled: status of regulator (on/off)
Mattias Wallin47c16972010-09-10 17:47:56 +020034 * @update_bank: bank to control on/off
Sundar R IYERc789ca22010-07-13 21:48:56 +053035 * @update_reg: register to control on/off
Emeric Vigierbd28a152013-03-21 15:58:59 +000036 * @update_mask: mask to enable/disable and set mode of regulator
37 * @update_val: bits holding the regulator current mode
38 * @update_val_idle: bits to enable the regulator in idle (low power) mode
39 * @update_val_normal: bits to enable the regulator in normal (high power) mode
Mattias Wallin47c16972010-09-10 17:47:56 +020040 * @voltage_bank: bank to control regulator voltage
Sundar R IYERc789ca22010-07-13 21:48:56 +053041 * @voltage_reg: register to control regulator voltage
42 * @voltage_mask: mask to control regulator voltage
Linus Walleija0a70142012-08-20 18:41:35 +020043 * @voltage_shift: shift to control regulator voltage
Linus Walleij42ab6162011-03-17 13:25:02 +010044 * @delay: startup/set voltage delay in us
Sundar R IYERc789ca22010-07-13 21:48:56 +053045 */
46struct ab8500_regulator_info {
47 struct device *dev;
48 struct regulator_desc desc;
Sundar R IYERc789ca22010-07-13 21:48:56 +053049 struct regulator_dev *regulator;
Emeric Vigierbd28a152013-03-21 15:58:59 +000050 bool is_enabled;
Mattias Wallin47c16972010-09-10 17:47:56 +020051 u8 update_bank;
52 u8 update_reg;
Bengt Jonssone1159e62010-12-10 11:08:44 +010053 u8 update_mask;
Emeric Vigierbd28a152013-03-21 15:58:59 +000054 u8 update_val;
55 u8 update_val_idle;
56 u8 update_val_normal;
Mattias Wallin47c16972010-09-10 17:47:56 +020057 u8 voltage_bank;
58 u8 voltage_reg;
59 u8 voltage_mask;
Linus Walleija0a70142012-08-20 18:41:35 +020060 u8 voltage_shift;
Linus Walleij42ab6162011-03-17 13:25:02 +010061 unsigned int delay;
Sundar R IYERc789ca22010-07-13 21:48:56 +053062};
63
64/* voltage tables for the vauxn/vintcore supplies */
Axel Linec1cc4d2012-05-20 10:33:35 +080065static const unsigned int ldo_vauxn_voltages[] = {
Sundar R IYERc789ca22010-07-13 21:48:56 +053066 1100000,
67 1200000,
68 1300000,
69 1400000,
70 1500000,
71 1800000,
72 1850000,
73 1900000,
74 2500000,
75 2650000,
76 2700000,
77 2750000,
78 2800000,
79 2900000,
80 3000000,
81 3300000,
82};
83
Axel Linec1cc4d2012-05-20 10:33:35 +080084static const unsigned int ldo_vaux3_voltages[] = {
Bengt Jonsson2b751512010-12-10 11:08:43 +010085 1200000,
86 1500000,
87 1800000,
88 2100000,
89 2500000,
90 2750000,
91 2790000,
92 2910000,
93};
94
Axel Linec1cc4d2012-05-20 10:33:35 +080095static const unsigned int ldo_vintcore_voltages[] = {
Sundar R IYERc789ca22010-07-13 21:48:56 +053096 1200000,
97 1225000,
98 1250000,
99 1275000,
100 1300000,
101 1325000,
102 1350000,
103};
104
105static int ab8500_regulator_enable(struct regulator_dev *rdev)
106{
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100107 int ret;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530108 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
109
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100110 if (info == NULL) {
111 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
Sundar R IYERc789ca22010-07-13 21:48:56 +0530112 return -EINVAL;
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100113 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530114
Mattias Wallin47c16972010-09-10 17:47:56 +0200115 ret = abx500_mask_and_set_register_interruptible(info->dev,
Bengt Jonssone1159e62010-12-10 11:08:44 +0100116 info->update_bank, info->update_reg,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000117 info->update_mask, info->update_val);
Sundar R IYERc789ca22010-07-13 21:48:56 +0530118 if (ret < 0)
119 dev_err(rdev_get_dev(rdev),
120 "couldn't set enable bits for regulator\n");
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100121
Emeric Vigierbd28a152013-03-21 15:58:59 +0000122 info->is_enabled = true;
123
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100124 dev_vdbg(rdev_get_dev(rdev),
125 "%s-enable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
126 info->desc.name, info->update_bank, info->update_reg,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000127 info->update_mask, info->update_val);
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100128
Sundar R IYERc789ca22010-07-13 21:48:56 +0530129 return ret;
130}
131
132static int ab8500_regulator_disable(struct regulator_dev *rdev)
133{
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100134 int ret;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530135 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
136
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100137 if (info == NULL) {
138 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
Sundar R IYERc789ca22010-07-13 21:48:56 +0530139 return -EINVAL;
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100140 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530141
Mattias Wallin47c16972010-09-10 17:47:56 +0200142 ret = abx500_mask_and_set_register_interruptible(info->dev,
Bengt Jonssone1159e62010-12-10 11:08:44 +0100143 info->update_bank, info->update_reg,
144 info->update_mask, 0x0);
Sundar R IYERc789ca22010-07-13 21:48:56 +0530145 if (ret < 0)
146 dev_err(rdev_get_dev(rdev),
147 "couldn't set disable bits for regulator\n");
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100148
Emeric Vigierbd28a152013-03-21 15:58:59 +0000149 info->is_enabled = false;
150
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100151 dev_vdbg(rdev_get_dev(rdev),
152 "%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
153 info->desc.name, info->update_bank, info->update_reg,
154 info->update_mask, 0x0);
155
Sundar R IYERc789ca22010-07-13 21:48:56 +0530156 return ret;
157}
158
Emeric Vigierbd28a152013-03-21 15:58:59 +0000159static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
160 unsigned int mode)
161{
162 int ret = 0;
163
164 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
165
166 if (info == NULL) {
167 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
168 return -EINVAL;
169 }
170
171 switch (mode) {
172 case REGULATOR_MODE_NORMAL:
173 info->update_val = info->update_val_normal;
174 break;
175 case REGULATOR_MODE_IDLE:
176 info->update_val = info->update_val_idle;
177 break;
178 default:
179 return -EINVAL;
180 }
181
182 if (info->is_enabled) {
183 ret = abx500_mask_and_set_register_interruptible(info->dev,
184 info->update_bank, info->update_reg,
185 info->update_mask, info->update_val);
186 if (ret < 0)
187 dev_err(rdev_get_dev(rdev),
188 "couldn't set regulator mode\n");
189 }
190
191 return ret;
192}
193
194static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev)
195{
196 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
197 int ret;
198
199 if (info == NULL) {
200 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
201 return -EINVAL;
202 }
203
204 if (info->update_val == info->update_val_normal)
205 ret = REGULATOR_MODE_NORMAL;
206 else if (info->update_val == info->update_val_idle)
207 ret = REGULATOR_MODE_IDLE;
208 else
209 ret = -EINVAL;
210
211 return ret;
212}
213
Sundar R IYERc789ca22010-07-13 21:48:56 +0530214static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
215{
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100216 int ret;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530217 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100218 u8 regval;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530219
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100220 if (info == NULL) {
221 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
Sundar R IYERc789ca22010-07-13 21:48:56 +0530222 return -EINVAL;
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100223 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530224
Mattias Wallin47c16972010-09-10 17:47:56 +0200225 ret = abx500_get_register_interruptible(info->dev,
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100226 info->update_bank, info->update_reg, &regval);
Sundar R IYERc789ca22010-07-13 21:48:56 +0530227 if (ret < 0) {
228 dev_err(rdev_get_dev(rdev),
229 "couldn't read 0x%x register\n", info->update_reg);
230 return ret;
231 }
232
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100233 dev_vdbg(rdev_get_dev(rdev),
234 "%s-is_enabled (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
235 " 0x%x\n",
236 info->desc.name, info->update_bank, info->update_reg,
237 info->update_mask, regval);
238
239 if (regval & info->update_mask)
Emeric Vigierbd28a152013-03-21 15:58:59 +0000240 info->is_enabled = true;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530241 else
Emeric Vigierbd28a152013-03-21 15:58:59 +0000242 info->is_enabled = false;
243
244 return info->is_enabled;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530245}
246
Axel Lin3bf6e902012-02-24 17:15:45 +0800247static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
Sundar R IYERc789ca22010-07-13 21:48:56 +0530248{
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100249 int ret, val;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530250 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100251 u8 regval;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530252
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100253 if (info == NULL) {
254 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
Sundar R IYERc789ca22010-07-13 21:48:56 +0530255 return -EINVAL;
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100256 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530257
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100258 ret = abx500_get_register_interruptible(info->dev,
259 info->voltage_bank, info->voltage_reg, &regval);
Sundar R IYERc789ca22010-07-13 21:48:56 +0530260 if (ret < 0) {
261 dev_err(rdev_get_dev(rdev),
262 "couldn't read voltage reg for regulator\n");
263 return ret;
264 }
265
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100266 dev_vdbg(rdev_get_dev(rdev),
Linus Walleija0a70142012-08-20 18:41:35 +0200267 "%s-get_voltage (bank, reg, mask, shift, value): "
268 "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
269 info->desc.name, info->voltage_bank,
270 info->voltage_reg, info->voltage_mask,
271 info->voltage_shift, regval);
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100272
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100273 val = regval & info->voltage_mask;
Linus Walleija0a70142012-08-20 18:41:35 +0200274 return val >> info->voltage_shift;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530275}
276
Axel Linae713d32012-03-20 09:51:08 +0800277static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
278 unsigned selector)
Sundar R IYERc789ca22010-07-13 21:48:56 +0530279{
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100280 int ret;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530281 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100282 u8 regval;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530283
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100284 if (info == NULL) {
285 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
Sundar R IYERc789ca22010-07-13 21:48:56 +0530286 return -EINVAL;
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100287 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530288
Sundar R IYERc789ca22010-07-13 21:48:56 +0530289 /* set the registers for the request */
Linus Walleija0a70142012-08-20 18:41:35 +0200290 regval = (u8)selector << info->voltage_shift;
Mattias Wallin47c16972010-09-10 17:47:56 +0200291 ret = abx500_mask_and_set_register_interruptible(info->dev,
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100292 info->voltage_bank, info->voltage_reg,
293 info->voltage_mask, regval);
Sundar R IYERc789ca22010-07-13 21:48:56 +0530294 if (ret < 0)
295 dev_err(rdev_get_dev(rdev),
296 "couldn't set voltage reg for regulator\n");
297
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100298 dev_vdbg(rdev_get_dev(rdev),
299 "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
300 " 0x%x\n",
301 info->desc.name, info->voltage_bank, info->voltage_reg,
302 info->voltage_mask, regval);
303
Sundar R IYERc789ca22010-07-13 21:48:56 +0530304 return ret;
305}
306
Linus Walleij42ab6162011-03-17 13:25:02 +0100307static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
308 unsigned int old_sel,
309 unsigned int new_sel)
310{
311 struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
Linus Walleij42ab6162011-03-17 13:25:02 +0100312
Linus Walleij42ab6162011-03-17 13:25:02 +0100313 return info->delay;
314}
315
Sundar R IYERc789ca22010-07-13 21:48:56 +0530316static struct regulator_ops ab8500_regulator_ops = {
317 .enable = ab8500_regulator_enable,
318 .disable = ab8500_regulator_disable,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000319 .set_mode = ab8500_regulator_set_mode,
320 .get_mode = ab8500_regulator_get_mode,
Sundar R IYERc789ca22010-07-13 21:48:56 +0530321 .is_enabled = ab8500_regulator_is_enabled,
Axel Lin3bf6e902012-02-24 17:15:45 +0800322 .get_voltage_sel = ab8500_regulator_get_voltage_sel,
Axel Linae713d32012-03-20 09:51:08 +0800323 .set_voltage_sel = ab8500_regulator_set_voltage_sel,
Axel Linec1cc4d2012-05-20 10:33:35 +0800324 .list_voltage = regulator_list_voltage_table,
Linus Walleij42ab6162011-03-17 13:25:02 +0100325 .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
Sundar R IYERc789ca22010-07-13 21:48:56 +0530326};
327
Bengt Jonsson6909b452010-12-10 11:08:47 +0100328static struct regulator_ops ab8500_regulator_fixed_ops = {
Sundar R IYERc789ca22010-07-13 21:48:56 +0530329 .enable = ab8500_regulator_enable,
330 .disable = ab8500_regulator_disable,
331 .is_enabled = ab8500_regulator_is_enabled,
Axel Lin7142e212012-06-08 10:27:49 +0800332 .list_voltage = regulator_list_voltage_linear,
Sundar R IYERc789ca22010-07-13 21:48:56 +0530333};
334
Bengt Jonsson6909b452010-12-10 11:08:47 +0100335static struct ab8500_regulator_info
336 ab8500_regulator_info[AB8500_NUM_REGULATORS] = {
Sundar R IYERc789ca22010-07-13 21:48:56 +0530337 /*
Bengt Jonssone1159e62010-12-10 11:08:44 +0100338 * Variable Voltage Regulators
339 * name, min mV, max mV,
340 * update bank, reg, mask, enable val
Axel Linec1cc4d2012-05-20 10:33:35 +0800341 * volt bank, reg, mask
Sundar R IYERc789ca22010-07-13 21:48:56 +0530342 */
Bengt Jonsson6909b452010-12-10 11:08:47 +0100343 [AB8500_LDO_AUX1] = {
344 .desc = {
345 .name = "LDO-AUX1",
346 .ops = &ab8500_regulator_ops,
347 .type = REGULATOR_VOLTAGE,
348 .id = AB8500_LDO_AUX1,
349 .owner = THIS_MODULE,
350 .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
Axel Linec1cc4d2012-05-20 10:33:35 +0800351 .volt_table = ldo_vauxn_voltages,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100352 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100353 .update_bank = 0x04,
354 .update_reg = 0x09,
355 .update_mask = 0x03,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000356 .update_val = 0x01,
357 .update_val_idle = 0x03,
358 .update_val_normal = 0x01,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100359 .voltage_bank = 0x04,
360 .voltage_reg = 0x1f,
361 .voltage_mask = 0x0f,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100362 },
363 [AB8500_LDO_AUX2] = {
364 .desc = {
365 .name = "LDO-AUX2",
366 .ops = &ab8500_regulator_ops,
367 .type = REGULATOR_VOLTAGE,
368 .id = AB8500_LDO_AUX2,
369 .owner = THIS_MODULE,
370 .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
Axel Linec1cc4d2012-05-20 10:33:35 +0800371 .volt_table = ldo_vauxn_voltages,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100372 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100373 .update_bank = 0x04,
374 .update_reg = 0x09,
375 .update_mask = 0x0c,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000376 .update_val = 0x04,
377 .update_val_idle = 0x0c,
378 .update_val_normal = 0x04,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100379 .voltage_bank = 0x04,
380 .voltage_reg = 0x20,
381 .voltage_mask = 0x0f,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100382 },
383 [AB8500_LDO_AUX3] = {
384 .desc = {
385 .name = "LDO-AUX3",
386 .ops = &ab8500_regulator_ops,
387 .type = REGULATOR_VOLTAGE,
388 .id = AB8500_LDO_AUX3,
389 .owner = THIS_MODULE,
390 .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
Axel Linec1cc4d2012-05-20 10:33:35 +0800391 .volt_table = ldo_vaux3_voltages,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100392 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100393 .update_bank = 0x04,
394 .update_reg = 0x0a,
395 .update_mask = 0x03,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000396 .update_val = 0x01,
397 .update_val_idle = 0x03,
398 .update_val_normal = 0x01,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100399 .voltage_bank = 0x04,
400 .voltage_reg = 0x21,
401 .voltage_mask = 0x07,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100402 },
403 [AB8500_LDO_INTCORE] = {
404 .desc = {
405 .name = "LDO-INTCORE",
406 .ops = &ab8500_regulator_ops,
407 .type = REGULATOR_VOLTAGE,
408 .id = AB8500_LDO_INTCORE,
409 .owner = THIS_MODULE,
410 .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages),
Axel Linec1cc4d2012-05-20 10:33:35 +0800411 .volt_table = ldo_vintcore_voltages,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100412 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100413 .update_bank = 0x03,
414 .update_reg = 0x80,
415 .update_mask = 0x44,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000416 .update_val = 0x04,
417 .update_val_idle = 0x44,
418 .update_val_normal = 0x04,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100419 .voltage_bank = 0x03,
420 .voltage_reg = 0x80,
421 .voltage_mask = 0x38,
Linus Walleija0a70142012-08-20 18:41:35 +0200422 .voltage_shift = 3,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100423 },
Sundar R IYERc789ca22010-07-13 21:48:56 +0530424
425 /*
Bengt Jonssone1159e62010-12-10 11:08:44 +0100426 * Fixed Voltage Regulators
427 * name, fixed mV,
428 * update bank, reg, mask, enable val
Sundar R IYERc789ca22010-07-13 21:48:56 +0530429 */
Bengt Jonsson6909b452010-12-10 11:08:47 +0100430 [AB8500_LDO_TVOUT] = {
431 .desc = {
432 .name = "LDO-TVOUT",
433 .ops = &ab8500_regulator_fixed_ops,
434 .type = REGULATOR_VOLTAGE,
435 .id = AB8500_LDO_TVOUT,
436 .owner = THIS_MODULE,
437 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800438 .min_uV = 2000000,
Axel Lin7fee2af2012-08-07 22:21:23 +0800439 .enable_time = 10000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100440 },
Linus Walleij42ab6162011-03-17 13:25:02 +0100441 .delay = 10000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100442 .update_bank = 0x03,
443 .update_reg = 0x80,
444 .update_mask = 0x82,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000445 .update_val = 0x02,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100446 },
Bengt Jonssonea05ef32011-03-10 14:43:31 +0100447 [AB8500_LDO_USB] = {
448 .desc = {
449 .name = "LDO-USB",
450 .ops = &ab8500_regulator_fixed_ops,
451 .type = REGULATOR_VOLTAGE,
452 .id = AB8500_LDO_USB,
453 .owner = THIS_MODULE,
454 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800455 .min_uV = 3300000,
Bengt Jonssonea05ef32011-03-10 14:43:31 +0100456 },
Bengt Jonssonea05ef32011-03-10 14:43:31 +0100457 .update_bank = 0x03,
458 .update_reg = 0x82,
459 .update_mask = 0x03,
Bengt Jonssonea05ef32011-03-10 14:43:31 +0100460 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100461 [AB8500_LDO_AUDIO] = {
462 .desc = {
463 .name = "LDO-AUDIO",
464 .ops = &ab8500_regulator_fixed_ops,
465 .type = REGULATOR_VOLTAGE,
466 .id = AB8500_LDO_AUDIO,
467 .owner = THIS_MODULE,
468 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800469 .min_uV = 2000000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100470 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100471 .update_bank = 0x03,
472 .update_reg = 0x83,
473 .update_mask = 0x02,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000474 .update_val = 0x02,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100475 },
476 [AB8500_LDO_ANAMIC1] = {
477 .desc = {
478 .name = "LDO-ANAMIC1",
479 .ops = &ab8500_regulator_fixed_ops,
480 .type = REGULATOR_VOLTAGE,
481 .id = AB8500_LDO_ANAMIC1,
482 .owner = THIS_MODULE,
483 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800484 .min_uV = 2050000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100485 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100486 .update_bank = 0x03,
487 .update_reg = 0x83,
488 .update_mask = 0x08,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000489 .update_val = 0x08,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100490 },
491 [AB8500_LDO_ANAMIC2] = {
492 .desc = {
493 .name = "LDO-ANAMIC2",
494 .ops = &ab8500_regulator_fixed_ops,
495 .type = REGULATOR_VOLTAGE,
496 .id = AB8500_LDO_ANAMIC2,
497 .owner = THIS_MODULE,
498 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800499 .min_uV = 2050000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100500 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100501 .update_bank = 0x03,
502 .update_reg = 0x83,
503 .update_mask = 0x10,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000504 .update_val = 0x10,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100505 },
506 [AB8500_LDO_DMIC] = {
507 .desc = {
508 .name = "LDO-DMIC",
509 .ops = &ab8500_regulator_fixed_ops,
510 .type = REGULATOR_VOLTAGE,
511 .id = AB8500_LDO_DMIC,
512 .owner = THIS_MODULE,
513 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800514 .min_uV = 1800000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100515 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100516 .update_bank = 0x03,
517 .update_reg = 0x83,
518 .update_mask = 0x04,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000519 .update_val = 0x04,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100520 },
521 [AB8500_LDO_ANA] = {
522 .desc = {
523 .name = "LDO-ANA",
524 .ops = &ab8500_regulator_fixed_ops,
525 .type = REGULATOR_VOLTAGE,
526 .id = AB8500_LDO_ANA,
527 .owner = THIS_MODULE,
528 .n_voltages = 1,
Axel Lin7142e212012-06-08 10:27:49 +0800529 .min_uV = 1200000,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100530 },
Bengt Jonsson6909b452010-12-10 11:08:47 +0100531 .update_bank = 0x04,
532 .update_reg = 0x06,
533 .update_mask = 0x0c,
Emeric Vigierbd28a152013-03-21 15:58:59 +0000534 .update_val = 0x04,
Bengt Jonsson6909b452010-12-10 11:08:47 +0100535 },
536
537
Sundar R IYERc789ca22010-07-13 21:48:56 +0530538};
539
Bengt Jonsson79568b942011-03-11 11:54:46 +0100540struct ab8500_reg_init {
541 u8 bank;
542 u8 addr;
543 u8 mask;
544};
545
546#define REG_INIT(_id, _bank, _addr, _mask) \
547 [_id] = { \
548 .bank = _bank, \
549 .addr = _addr, \
550 .mask = _mask, \
551 }
552
553static struct ab8500_reg_init ab8500_reg_init[] = {
554 /*
555 * 0x30, VanaRequestCtrl
Lee Jonesd79df322013-03-21 15:58:58 +0000556 * 0x0c, VpllRequestCtrl
Bengt Jonsson79568b942011-03-11 11:54:46 +0100557 * 0xc0, VextSupply1RequestCtrl
558 */
559 REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xfc),
560 /*
561 * 0x03, VextSupply2RequestCtrl
562 * 0x0c, VextSupply3RequestCtrl
563 * 0x30, Vaux1RequestCtrl
564 * 0xc0, Vaux2RequestCtrl
565 */
566 REG_INIT(AB8500_REGUREQUESTCTRL3, 0x03, 0x05, 0xff),
567 /*
568 * 0x03, Vaux3RequestCtrl
569 * 0x04, SwHPReq
570 */
571 REG_INIT(AB8500_REGUREQUESTCTRL4, 0x03, 0x06, 0x07),
572 /*
Lee Jonesd79df322013-03-21 15:58:58 +0000573 * 0x01, Vsmps1SysClkReq1HPValid
574 * 0x02, Vsmps2SysClkReq1HPValid
575 * 0x04, Vsmps3SysClkReq1HPValid
Bengt Jonsson79568b942011-03-11 11:54:46 +0100576 * 0x08, VanaSysClkReq1HPValid
Lee Jonesd79df322013-03-21 15:58:58 +0000577 * 0x10, VpllSysClkReq1HPValid
Bengt Jonsson79568b942011-03-11 11:54:46 +0100578 * 0x20, Vaux1SysClkReq1HPValid
579 * 0x40, Vaux2SysClkReq1HPValid
580 * 0x80, Vaux3SysClkReq1HPValid
581 */
Lee Jonesd79df322013-03-21 15:58:58 +0000582 REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff),
Bengt Jonsson79568b942011-03-11 11:54:46 +0100583 /*
584 * 0x10, VextSupply1SysClkReq1HPValid
585 * 0x20, VextSupply2SysClkReq1HPValid
586 * 0x40, VextSupply3SysClkReq1HPValid
587 */
588 REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x70),
589 /*
590 * 0x08, VanaHwHPReq1Valid
591 * 0x20, Vaux1HwHPReq1Valid
592 * 0x40, Vaux2HwHPReq1Valid
593 * 0x80, Vaux3HwHPReq1Valid
594 */
595 REG_INIT(AB8500_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xe8),
596 /*
597 * 0x01, VextSupply1HwHPReq1Valid
598 * 0x02, VextSupply2HwHPReq1Valid
599 * 0x04, VextSupply3HwHPReq1Valid
600 */
601 REG_INIT(AB8500_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x07),
602 /*
603 * 0x08, VanaHwHPReq2Valid
604 * 0x20, Vaux1HwHPReq2Valid
605 * 0x40, Vaux2HwHPReq2Valid
606 * 0x80, Vaux3HwHPReq2Valid
607 */
608 REG_INIT(AB8500_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xe8),
609 /*
610 * 0x01, VextSupply1HwHPReq2Valid
611 * 0x02, VextSupply2HwHPReq2Valid
612 * 0x04, VextSupply3HwHPReq2Valid
613 */
614 REG_INIT(AB8500_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x07),
615 /*
616 * 0x20, VanaSwHPReqValid
617 * 0x80, Vaux1SwHPReqValid
618 */
619 REG_INIT(AB8500_REGUSWHPREQVALID1, 0x03, 0x0d, 0xa0),
620 /*
621 * 0x01, Vaux2SwHPReqValid
622 * 0x02, Vaux3SwHPReqValid
623 * 0x04, VextSupply1SwHPReqValid
624 * 0x08, VextSupply2SwHPReqValid
625 * 0x10, VextSupply3SwHPReqValid
626 */
627 REG_INIT(AB8500_REGUSWHPREQVALID2, 0x03, 0x0e, 0x1f),
628 /*
629 * 0x02, SysClkReq2Valid1
630 * ...
631 * 0x80, SysClkReq8Valid1
632 */
633 REG_INIT(AB8500_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xfe),
634 /*
635 * 0x02, SysClkReq2Valid2
636 * ...
637 * 0x80, SysClkReq8Valid2
638 */
639 REG_INIT(AB8500_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xfe),
640 /*
641 * 0x02, VTVoutEna
642 * 0x04, Vintcore12Ena
643 * 0x38, Vintcore12Sel
644 * 0x40, Vintcore12LP
645 * 0x80, VTVoutLP
646 */
647 REG_INIT(AB8500_REGUMISC1, 0x03, 0x80, 0xfe),
648 /*
649 * 0x02, VaudioEna
650 * 0x04, VdmicEna
651 * 0x08, Vamic1Ena
652 * 0x10, Vamic2Ena
653 */
654 REG_INIT(AB8500_VAUDIOSUPPLY, 0x03, 0x83, 0x1e),
655 /*
656 * 0x01, Vamic1_dzout
657 * 0x02, Vamic2_dzout
658 */
659 REG_INIT(AB8500_REGUCTRL1VAMIC, 0x03, 0x84, 0x03),
660 /*
Lee Jonesd79df322013-03-21 15:58:58 +0000661 * 0x0c, VBBNRegu
662 * 0x03, VBBPRegu
663 * NOTE! PRCMU register
664 */
665 REG_INIT(AB8500_ARMREGU2, 0x04, 0x01, 0x0f),
666 /*
667 * 0x0c, VBBPSel1
668 * 0x03, VBBNSel1
669 * NOTE! PRCMU register
670 */
671 REG_INIT(AB8500_VBBSEL1, 0x04, 0x11, 0x0f),
672 /*
673 * 0x0c, VBBNSel2
674 * 0x03, VBBPSel2
675 * NOTE! PRCMU register
676 */
677 REG_INIT(AB8500_VBBSEL2, 0x04, 0x12, 0x0f),
678 /*
679 * 0x03, Vsmps1Regu
680 * 0x0c, Vsmps1SelCtrl
681 */
682 REG_INIT(AB8500_VSMPS1REGU, 0x04, 0x03, 0x0f),
683 /*
684 * 0x03, Vsmps2Regu
685 * 0x0c, Vsmps2SelCtrl
686 */
687 REG_INIT(AB8500_VSMPS2REGU, 0x04, 0x04, 0x0f),
688 /*
Bengt Jonsson79568b942011-03-11 11:54:46 +0100689 * 0x0c, VanaRegu
690 * 0x03, VpllRegu
691 */
692 REG_INIT(AB8500_VPLLVANAREGU, 0x04, 0x06, 0x0f),
693 /*
694 * 0x01, VrefDDREna
695 * 0x02, VrefDDRSleepMode
696 */
697 REG_INIT(AB8500_VREFDDR, 0x04, 0x07, 0x03),
698 /*
699 * 0x03, VextSupply1Regu
700 * 0x0c, VextSupply2Regu
701 * 0x30, VextSupply3Regu
702 * 0x40, ExtSupply2Bypass
703 * 0x80, ExtSupply3Bypass
704 */
705 REG_INIT(AB8500_EXTSUPPLYREGU, 0x04, 0x08, 0xff),
706 /*
707 * 0x03, Vaux1Regu
708 * 0x0c, Vaux2Regu
709 */
710 REG_INIT(AB8500_VAUX12REGU, 0x04, 0x09, 0x0f),
711 /*
Lee Jonesd79df322013-03-21 15:58:58 +0000712 * 0x0c, Vrf1Regu
Bengt Jonsson79568b942011-03-11 11:54:46 +0100713 * 0x03, Vaux3Regu
714 */
Lee Jonesd79df322013-03-21 15:58:58 +0000715 REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f),
Bengt Jonsson79568b942011-03-11 11:54:46 +0100716 /*
717 * 0x3f, Vsmps1Sel1
718 */
719 REG_INIT(AB8500_VSMPS1SEL1, 0x04, 0x13, 0x3f),
720 /*
721 * 0x0f, Vaux1Sel
722 */
723 REG_INIT(AB8500_VAUX1SEL, 0x04, 0x1f, 0x0f),
724 /*
725 * 0x0f, Vaux2Sel
726 */
727 REG_INIT(AB8500_VAUX2SEL, 0x04, 0x20, 0x0f),
728 /*
729 * 0x07, Vaux3Sel
730 */
731 REG_INIT(AB8500_VRF1VAUX3SEL, 0x04, 0x21, 0x07),
732 /*
733 * 0x01, VextSupply12LP
734 */
735 REG_INIT(AB8500_REGUCTRL2SPARE, 0x04, 0x22, 0x01),
736 /*
737 * 0x04, Vaux1Disch
738 * 0x08, Vaux2Disch
739 * 0x10, Vaux3Disch
740 * 0x20, Vintcore12Disch
741 * 0x40, VTVoutDisch
742 * 0x80, VaudioDisch
743 */
744 REG_INIT(AB8500_REGUCTRLDISCH, 0x04, 0x43, 0xfc),
745 /*
746 * 0x02, VanaDisch
747 * 0x04, VdmicPullDownEna
748 * 0x10, VdmicDisch
749 */
750 REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16),
751};
752
Bill Pembertona5023572012-11-19 13:22:22 -0500753static int
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100754ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
755{
756 int err;
757
758 if (value & ~ab8500_reg_init[id].mask) {
759 dev_err(&pdev->dev,
760 "Configuration error: value outside mask.\n");
761 return -EINVAL;
762 }
763
764 err = abx500_mask_and_set_register_interruptible(
765 &pdev->dev,
766 ab8500_reg_init[id].bank,
767 ab8500_reg_init[id].addr,
768 ab8500_reg_init[id].mask,
769 value);
770 if (err < 0) {
771 dev_err(&pdev->dev,
772 "Failed to initialize 0x%02x, 0x%02x.\n",
773 ab8500_reg_init[id].bank,
774 ab8500_reg_init[id].addr);
775 return err;
776 }
777
778 dev_vdbg(&pdev->dev,
779 "init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
780 ab8500_reg_init[id].bank,
781 ab8500_reg_init[id].addr,
782 ab8500_reg_init[id].mask,
783 value);
784
785 return 0;
786}
787
Bill Pembertona5023572012-11-19 13:22:22 -0500788static int ab8500_regulator_register(struct platform_device *pdev,
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100789 struct regulator_init_data *init_data,
790 int id,
791 struct device_node *np)
792{
793 struct ab8500_regulator_info *info = NULL;
794 struct regulator_config config = { };
795 int err;
796
797 /* assign per-regulator data */
798 info = &ab8500_regulator_info[id];
799 info->dev = &pdev->dev;
800
801 config.dev = &pdev->dev;
802 config.init_data = init_data;
803 config.driver_data = info;
804 config.of_node = np;
805
806 /* fix for hardware before ab8500v2.0 */
807 if (abx500_get_chip_id(info->dev) < 0x20) {
808 if (info->desc.id == AB8500_LDO_AUX3) {
809 info->desc.n_voltages =
810 ARRAY_SIZE(ldo_vauxn_voltages);
Axel Linec1cc4d2012-05-20 10:33:35 +0800811 info->desc.volt_table = ldo_vauxn_voltages;
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100812 info->voltage_mask = 0xf;
813 }
814 }
815
816 /* register regulator with framework */
817 info->regulator = regulator_register(&info->desc, &config);
818 if (IS_ERR(info->regulator)) {
819 err = PTR_ERR(info->regulator);
820 dev_err(&pdev->dev, "failed to register regulator %s\n",
821 info->desc.name);
822 /* when we fail, un-register all earlier regulators */
823 while (--id >= 0) {
824 info = &ab8500_regulator_info[id];
825 regulator_unregister(info->regulator);
826 }
827 return err;
828 }
829
830 return 0;
831}
832
Lee Jones3a8334b2012-05-17 14:45:16 +0100833static struct of_regulator_match ab8500_regulator_matches[] = {
Lee Jones7e715b92012-05-30 12:47:26 +0800834 { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8500_LDO_AUX1, },
835 { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8500_LDO_AUX2, },
836 { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8500_LDO_AUX3, },
837 { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, },
838 { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8500_LDO_TVOUT, },
839 { .name = "ab8500_ldo_usb", .driver_data = (void *) AB8500_LDO_USB, },
840 { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8500_LDO_AUDIO, },
841 { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8500_LDO_ANAMIC1, },
842 { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, },
843 { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, },
844 { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, },
Lee Jones3a8334b2012-05-17 14:45:16 +0100845};
846
Bill Pembertona5023572012-11-19 13:22:22 -0500847static int
Lee Jones3a8334b2012-05-17 14:45:16 +0100848ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
849{
850 int err, i;
851
852 for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
853 err = ab8500_regulator_register(
854 pdev, ab8500_regulator_matches[i].init_data,
855 i, ab8500_regulator_matches[i].of_node);
856 if (err)
857 return err;
858 }
859
860 return 0;
861}
862
Bill Pembertona5023572012-11-19 13:22:22 -0500863static int ab8500_regulator_probe(struct platform_device *pdev)
Sundar R IYERc789ca22010-07-13 21:48:56 +0530864{
865 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
Dan Carpenteraf54dec2010-08-14 11:03:16 +0200866 struct ab8500_platform_data *pdata;
Lee Jones3a8334b2012-05-17 14:45:16 +0100867 struct device_node *np = pdev->dev.of_node;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530868 int i, err;
869
Lee Jones3a8334b2012-05-17 14:45:16 +0100870 if (np) {
871 err = of_regulator_match(&pdev->dev, np,
872 ab8500_regulator_matches,
873 ARRAY_SIZE(ab8500_regulator_matches));
874 if (err < 0) {
875 dev_err(&pdev->dev,
876 "Error parsing regulator init data: %d\n", err);
877 return err;
878 }
879
880 err = ab8500_regulator_of_probe(pdev, np);
881 return err;
882 }
883
Sundar R IYERc789ca22010-07-13 21:48:56 +0530884 if (!ab8500) {
885 dev_err(&pdev->dev, "null mfd parent\n");
886 return -EINVAL;
887 }
Dan Carpenteraf54dec2010-08-14 11:03:16 +0200888 pdata = dev_get_platdata(ab8500->dev);
Bengt Jonssonfc24b422010-12-10 11:08:45 +0100889 if (!pdata) {
890 dev_err(&pdev->dev, "null pdata\n");
891 return -EINVAL;
892 }
Sundar R IYERc789ca22010-07-13 21:48:56 +0530893
Bengt Jonssoncb189b02010-12-10 11:08:40 +0100894 /* make sure the platform data has the correct size */
895 if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
Bengt Jonsson79568b942011-03-11 11:54:46 +0100896 dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
Bengt Jonssoncb189b02010-12-10 11:08:40 +0100897 return -EINVAL;
898 }
899
Bengt Jonsson79568b942011-03-11 11:54:46 +0100900 /* initialize registers */
901 for (i = 0; i < pdata->num_regulator_reg_init; i++) {
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100902 int id, value;
Bengt Jonsson79568b942011-03-11 11:54:46 +0100903
904 id = pdata->regulator_reg_init[i].id;
905 value = pdata->regulator_reg_init[i].value;
906
907 /* check for configuration errors */
908 if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
909 dev_err(&pdev->dev,
910 "Configuration error: id outside range.\n");
911 return -EINVAL;
912 }
Bengt Jonsson79568b942011-03-11 11:54:46 +0100913
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100914 err = ab8500_regulator_init_registers(pdev, id, value);
915 if (err < 0)
Bengt Jonsson79568b942011-03-11 11:54:46 +0100916 return err;
Bengt Jonsson79568b942011-03-11 11:54:46 +0100917 }
918
Sundar R IYERc789ca22010-07-13 21:48:56 +0530919 /* register all regulators */
920 for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
Lee Jonesa7ac1d92012-05-17 14:45:14 +0100921 err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL);
922 if (err < 0)
Sundar R IYERc789ca22010-07-13 21:48:56 +0530923 return err;
Sundar R IYERc789ca22010-07-13 21:48:56 +0530924 }
925
926 return 0;
927}
928
Bill Pemberton8dc995f2012-11-19 13:26:10 -0500929static int ab8500_regulator_remove(struct platform_device *pdev)
Sundar R IYERc789ca22010-07-13 21:48:56 +0530930{
931 int i;
932
933 for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
934 struct ab8500_regulator_info *info = NULL;
935 info = &ab8500_regulator_info[i];
Bengt Jonsson09aefa12010-12-10 11:08:46 +0100936
937 dev_vdbg(rdev_get_dev(info->regulator),
938 "%s-remove\n", info->desc.name);
939
Sundar R IYERc789ca22010-07-13 21:48:56 +0530940 regulator_unregister(info->regulator);
941 }
942
943 return 0;
944}
945
946static struct platform_driver ab8500_regulator_driver = {
947 .probe = ab8500_regulator_probe,
Bill Pemberton5eb9f2b2012-11-19 13:20:42 -0500948 .remove = ab8500_regulator_remove,
Sundar R IYERc789ca22010-07-13 21:48:56 +0530949 .driver = {
950 .name = "ab8500-regulator",
951 .owner = THIS_MODULE,
Sundar R IYERc789ca22010-07-13 21:48:56 +0530952 },
953};
954
955static int __init ab8500_regulator_init(void)
956{
957 int ret;
958
959 ret = platform_driver_register(&ab8500_regulator_driver);
960 if (ret != 0)
961 pr_err("Failed to register ab8500 regulator: %d\n", ret);
962
963 return ret;
964}
965subsys_initcall(ab8500_regulator_init);
966
967static void __exit ab8500_regulator_exit(void)
968{
969 platform_driver_unregister(&ab8500_regulator_driver);
970}
971module_exit(ab8500_regulator_exit);
972
973MODULE_LICENSE("GPL v2");
974MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
975MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC");
976MODULE_ALIAS("platform:ab8500-regulator");