aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-10-11 07:48:57 -0400
committerMark Brown <broonie@linaro.org>2013-10-11 07:48:57 -0400
commit813de3c649d6c6ff14c930de9fcd161c0062fabd (patch)
tree299ba8cc940d6254a56920c12411b9d92f94fd33 /drivers/regulator
parentd0e639c9e06d44e713170031fe05fb60ebe680af (diff)
parent5e965704803dcbcbfbf97e8a976b3778b245834b (diff)
Merge remote-tracking branch 'regulator/topic/as3722' into regulator-linear
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/as3722-regulator.c917
3 files changed, 926 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index dfe58096b374..9869064f9f03 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -133,6 +133,14 @@ config REGULATOR_AS3711
133 This driver provides support for the voltage regulators on the 133 This driver provides support for the voltage regulators on the
134 AS3711 PMIC 134 AS3711 PMIC
135 135
136config REGULATOR_AS3722
137 tristate "AMS AS3722 PMIC Regulators"
138 depends on MFD_AS3722
139 help
140 This driver provides support for the voltage regulators on the
141 AS3722 PMIC. This will enable support for all the software
142 controllable DCDC/LDO regulators.
143
136config REGULATOR_DA903X 144config REGULATOR_DA903X
137 tristate "Dialog Semiconductor DA9030/DA9034 regulators" 145 tristate "Dialog Semiconductor DA9030/DA9034 regulators"
138 depends on PMIC_DA903X 146 depends on PMIC_DA903X
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 185cce246022..0b233bbe6734 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
18obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o 18obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
19obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o 19obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
20obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o 20obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
21obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
21obj-$(CONFIG_REGULATOR_DA903X) += da903x.o 22obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
22obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o 23obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
23obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o 24obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
new file mode 100644
index 000000000000..d7b71a9c41f1
--- /dev/null
+++ b/drivers/regulator/as3722-regulator.c
@@ -0,0 +1,917 @@
1/*
2 * Voltage regulator support for AMS AS3722 PMIC
3 *
4 * Copyright (C) 2013 ams
5 *
6 * Author: Florian Lobmaier <florian.lobmaier@ams.com>
7 * Author: Laxman Dewangan <ldewangan@nvidia.com>
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 as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include <linux/err.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/mfd/as3722.h>
29#include <linux/of.h>
30#include <linux/of_platform.h>
31#include <linux/platform_device.h>
32#include <linux/regulator/driver.h>
33#include <linux/regulator/machine.h>
34#include <linux/regulator/of_regulator.h>
35#include <linux/slab.h>
36
37/* Regulator IDs */
38enum as3722_regulators_id {
39 AS3722_REGULATOR_ID_SD0,
40 AS3722_REGULATOR_ID_SD1,
41 AS3722_REGULATOR_ID_SD2,
42 AS3722_REGULATOR_ID_SD3,
43 AS3722_REGULATOR_ID_SD4,
44 AS3722_REGULATOR_ID_SD5,
45 AS3722_REGULATOR_ID_SD6,
46 AS3722_REGULATOR_ID_LDO0,
47 AS3722_REGULATOR_ID_LDO1,
48 AS3722_REGULATOR_ID_LDO2,
49 AS3722_REGULATOR_ID_LDO3,
50 AS3722_REGULATOR_ID_LDO4,
51 AS3722_REGULATOR_ID_LDO5,
52 AS3722_REGULATOR_ID_LDO6,
53 AS3722_REGULATOR_ID_LDO7,
54 AS3722_REGULATOR_ID_LDO9,
55 AS3722_REGULATOR_ID_LDO10,
56 AS3722_REGULATOR_ID_LDO11,
57 AS3722_REGULATOR_ID_MAX,
58};
59
60struct as3722_register_mapping {
61 u8 regulator_id;
62 const char *name;
63 const char *sname;
64 u8 vsel_reg;
65 u8 vsel_mask;
66 int n_voltages;
67 u32 enable_reg;
68 u8 enable_mask;
69 u32 control_reg;
70 u8 mode_mask;
71 u32 sleep_ctrl_reg;
72 u8 sleep_ctrl_mask;
73};
74
75struct as3722_regulator_config_data {
76 struct regulator_init_data *reg_init;
77 bool enable_tracking;
78 int ext_control;
79};
80
81struct as3722_regulators {
82 struct device *dev;
83 struct as3722 *as3722;
84 struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX];
85 struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
86 struct as3722_regulator_config_data
87 reg_config_data[AS3722_REGULATOR_ID_MAX];
88};
89
90static const struct as3722_register_mapping as3722_reg_lookup[] = {
91 {
92 .regulator_id = AS3722_REGULATOR_ID_SD0,
93 .name = "as3722-sd0",
94 .vsel_reg = AS3722_SD0_VOLTAGE_REG,
95 .vsel_mask = AS3722_SD_VSEL_MASK,
96 .enable_reg = AS3722_SD_CONTROL_REG,
97 .enable_mask = AS3722_SDn_CTRL(0),
98 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
99 .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
100 .control_reg = AS3722_SD0_CONTROL_REG,
101 .mode_mask = AS3722_SD0_MODE_FAST,
102 .n_voltages = AS3722_SD0_VSEL_MAX + 1,
103 },
104 {
105 .regulator_id = AS3722_REGULATOR_ID_SD1,
106 .name = "as3722-sd1",
107 .vsel_reg = AS3722_SD1_VOLTAGE_REG,
108 .vsel_mask = AS3722_SD_VSEL_MASK,
109 .enable_reg = AS3722_SD_CONTROL_REG,
110 .enable_mask = AS3722_SDn_CTRL(1),
111 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
112 .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
113 .control_reg = AS3722_SD1_CONTROL_REG,
114 .mode_mask = AS3722_SD1_MODE_FAST,
115 .n_voltages = AS3722_SD0_VSEL_MAX + 1,
116 },
117 {
118 .regulator_id = AS3722_REGULATOR_ID_SD2,
119 .name = "as3722-sd2",
120 .sname = "vsup-sd2",
121 .vsel_reg = AS3722_SD2_VOLTAGE_REG,
122 .vsel_mask = AS3722_SD_VSEL_MASK,
123 .enable_reg = AS3722_SD_CONTROL_REG,
124 .enable_mask = AS3722_SDn_CTRL(2),
125 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
126 .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
127 .control_reg = AS3722_SD23_CONTROL_REG,
128 .mode_mask = AS3722_SD2_MODE_FAST,
129 .n_voltages = AS3722_SD2_VSEL_MAX + 1,
130 },
131 {
132 .regulator_id = AS3722_REGULATOR_ID_SD3,
133 .name = "as3722-sd3",
134 .sname = "vsup-sd3",
135 .vsel_reg = AS3722_SD3_VOLTAGE_REG,
136 .vsel_mask = AS3722_SD_VSEL_MASK,
137 .enable_reg = AS3722_SD_CONTROL_REG,
138 .enable_mask = AS3722_SDn_CTRL(3),
139 .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
140 .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
141 .control_reg = AS3722_SD23_CONTROL_REG,
142 .mode_mask = AS3722_SD3_MODE_FAST,
143 .n_voltages = AS3722_SD2_VSEL_MAX + 1,
144 },
145 {
146 .regulator_id = AS3722_REGULATOR_ID_SD4,
147 .name = "as3722-sd4",
148 .sname = "vsup-sd4",
149 .vsel_reg = AS3722_SD4_VOLTAGE_REG,
150 .vsel_mask = AS3722_SD_VSEL_MASK,
151 .enable_reg = AS3722_SD_CONTROL_REG,
152 .enable_mask = AS3722_SDn_CTRL(4),
153 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
154 .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
155 .control_reg = AS3722_SD4_CONTROL_REG,
156 .mode_mask = AS3722_SD4_MODE_FAST,
157 .n_voltages = AS3722_SD2_VSEL_MAX + 1,
158 },
159 {
160 .regulator_id = AS3722_REGULATOR_ID_SD5,
161 .name = "as3722-sd5",
162 .sname = "vsup-sd5",
163 .vsel_reg = AS3722_SD5_VOLTAGE_REG,
164 .vsel_mask = AS3722_SD_VSEL_MASK,
165 .enable_reg = AS3722_SD_CONTROL_REG,
166 .enable_mask = AS3722_SDn_CTRL(5),
167 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
168 .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
169 .control_reg = AS3722_SD5_CONTROL_REG,
170 .mode_mask = AS3722_SD5_MODE_FAST,
171 .n_voltages = AS3722_SD2_VSEL_MAX + 1,
172 },
173 {
174 .regulator_id = AS3722_REGULATOR_ID_SD6,
175 .name = "as3722-sd6",
176 .vsel_reg = AS3722_SD6_VOLTAGE_REG,
177 .vsel_mask = AS3722_SD_VSEL_MASK,
178 .enable_reg = AS3722_SD_CONTROL_REG,
179 .enable_mask = AS3722_SDn_CTRL(6),
180 .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
181 .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
182 .control_reg = AS3722_SD6_CONTROL_REG,
183 .mode_mask = AS3722_SD6_MODE_FAST,
184 .n_voltages = AS3722_SD0_VSEL_MAX + 1,
185 },
186 {
187 .regulator_id = AS3722_REGULATOR_ID_LDO0,
188 .name = "as3722-ldo0",
189 .sname = "vin-ldo0",
190 .vsel_reg = AS3722_LDO0_VOLTAGE_REG,
191 .vsel_mask = AS3722_LDO0_VSEL_MASK,
192 .enable_reg = AS3722_LDOCONTROL0_REG,
193 .enable_mask = AS3722_LDO0_CTRL,
194 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
195 .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
196 .n_voltages = AS3722_LDO0_NUM_VOLT,
197 },
198 {
199 .regulator_id = AS3722_REGULATOR_ID_LDO1,
200 .name = "as3722-ldo1",
201 .sname = "vin-ldo1-6",
202 .vsel_reg = AS3722_LDO1_VOLTAGE_REG,
203 .vsel_mask = AS3722_LDO_VSEL_MASK,
204 .enable_reg = AS3722_LDOCONTROL0_REG,
205 .enable_mask = AS3722_LDO1_CTRL,
206 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
207 .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
208 .n_voltages = AS3722_LDO_NUM_VOLT,
209 },
210 {
211 .regulator_id = AS3722_REGULATOR_ID_LDO2,
212 .name = "as3722-ldo2",
213 .sname = "vin-ldo2-5-7",
214 .vsel_reg = AS3722_LDO2_VOLTAGE_REG,
215 .vsel_mask = AS3722_LDO_VSEL_MASK,
216 .enable_reg = AS3722_LDOCONTROL0_REG,
217 .enable_mask = AS3722_LDO2_CTRL,
218 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
219 .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
220 .n_voltages = AS3722_LDO_NUM_VOLT,
221 },
222 {
223 .regulator_id = AS3722_REGULATOR_ID_LDO3,
224 .name = "as3722-ldo3",
225 .name = "vin-ldo3-4",
226 .vsel_reg = AS3722_LDO3_VOLTAGE_REG,
227 .vsel_mask = AS3722_LDO3_VSEL_MASK,
228 .enable_reg = AS3722_LDOCONTROL0_REG,
229 .enable_mask = AS3722_LDO3_CTRL,
230 .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
231 .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
232 .n_voltages = AS3722_LDO3_NUM_VOLT,
233 },
234 {
235 .regulator_id = AS3722_REGULATOR_ID_LDO4,
236 .name = "as3722-ldo4",
237 .name = "vin-ldo3-4",
238 .vsel_reg = AS3722_LDO4_VOLTAGE_REG,
239 .vsel_mask = AS3722_LDO_VSEL_MASK,
240 .enable_reg = AS3722_LDOCONTROL0_REG,
241 .enable_mask = AS3722_LDO4_CTRL,
242 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
243 .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
244 .n_voltages = AS3722_LDO_NUM_VOLT,
245 },
246 {
247 .regulator_id = AS3722_REGULATOR_ID_LDO5,
248 .name = "as3722-ldo5",
249 .sname = "vin-ldo2-5-7",
250 .vsel_reg = AS3722_LDO5_VOLTAGE_REG,
251 .vsel_mask = AS3722_LDO_VSEL_MASK,
252 .enable_reg = AS3722_LDOCONTROL0_REG,
253 .enable_mask = AS3722_LDO5_CTRL,
254 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
255 .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
256 .n_voltages = AS3722_LDO_NUM_VOLT,
257 },
258 {
259 .regulator_id = AS3722_REGULATOR_ID_LDO6,
260 .name = "as3722-ldo6",
261 .sname = "vin-ldo1-6",
262 .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
263 .vsel_mask = AS3722_LDO_VSEL_MASK,
264 .enable_reg = AS3722_LDOCONTROL0_REG,
265 .enable_mask = AS3722_LDO6_CTRL,
266 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
267 .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
268 .n_voltages = AS3722_LDO_NUM_VOLT,
269 },
270 {
271 .regulator_id = AS3722_REGULATOR_ID_LDO7,
272 .name = "as3722-ldo7",
273 .sname = "vin-ldo2-5-7",
274 .vsel_reg = AS3722_LDO7_VOLTAGE_REG,
275 .vsel_mask = AS3722_LDO_VSEL_MASK,
276 .enable_reg = AS3722_LDOCONTROL0_REG,
277 .enable_mask = AS3722_LDO7_CTRL,
278 .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
279 .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
280 .n_voltages = AS3722_LDO_NUM_VOLT,
281 },
282 {
283 .regulator_id = AS3722_REGULATOR_ID_LDO9,
284 .name = "as3722-ldo9",
285 .sname = "vin-ldo9-10",
286 .vsel_reg = AS3722_LDO9_VOLTAGE_REG,
287 .vsel_mask = AS3722_LDO_VSEL_MASK,
288 .enable_reg = AS3722_LDOCONTROL1_REG,
289 .enable_mask = AS3722_LDO9_CTRL,
290 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
291 .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
292 .n_voltages = AS3722_LDO_NUM_VOLT,
293 },
294 {
295 .regulator_id = AS3722_REGULATOR_ID_LDO10,
296 .name = "as3722-ldo10",
297 .sname = "vin-ldo9-10",
298 .vsel_reg = AS3722_LDO10_VOLTAGE_REG,
299 .vsel_mask = AS3722_LDO_VSEL_MASK,
300 .enable_reg = AS3722_LDOCONTROL1_REG,
301 .enable_mask = AS3722_LDO10_CTRL,
302 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
303 .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
304 .n_voltages = AS3722_LDO_NUM_VOLT,
305 },
306 {
307 .regulator_id = AS3722_REGULATOR_ID_LDO11,
308 .name = "as3722-ldo11",
309 .sname = "vin-ldo11",
310 .vsel_reg = AS3722_LDO11_VOLTAGE_REG,
311 .vsel_mask = AS3722_LDO_VSEL_MASK,
312 .enable_reg = AS3722_LDOCONTROL1_REG,
313 .enable_mask = AS3722_LDO11_CTRL,
314 .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
315 .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
316 .n_voltages = AS3722_LDO_NUM_VOLT,
317 },
318};
319
320
321static const int as3722_ldo_current[] = { 150000, 300000 };
322static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 };
323
324static int as3722_current_to_index(int min_uA, int max_uA,
325 const int *curr_table, int n_currents)
326{
327 int i;
328
329 for (i = n_currents - 1; i >= 0; i--) {
330 if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA))
331 return i;
332 }
333 return -EINVAL;
334}
335
336static int as3722_ldo_get_current_limit(struct regulator_dev *rdev)
337{
338 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
339 struct as3722 *as3722 = as3722_regs->as3722;
340 int id = rdev_get_id(rdev);
341 u32 val;
342 int ret;
343
344 ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val);
345 if (ret < 0) {
346 dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
347 as3722_reg_lookup[id].vsel_reg, ret);
348 return ret;
349 }
350 if (val & AS3722_LDO_ILIMIT_MASK)
351 return 300000;
352 return 150000;
353}
354
355static int as3722_ldo_set_current_limit(struct regulator_dev *rdev,
356 int min_uA, int max_uA)
357{
358 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
359 struct as3722 *as3722 = as3722_regs->as3722;
360 int id = rdev_get_id(rdev);
361 int ret;
362 u32 reg = 0;
363
364 ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current,
365 ARRAY_SIZE(as3722_ldo_current));
366 if (ret < 0) {
367 dev_err(as3722_regs->dev,
368 "Current range min:max = %d:%d does not support\n",
369 min_uA, max_uA);
370 return ret;
371 }
372 if (ret)
373 reg = AS3722_LDO_ILIMIT_BIT;
374 return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg,
375 AS3722_LDO_ILIMIT_MASK, reg);
376}
377
378static struct regulator_ops as3722_ldo0_ops = {
379 .is_enabled = regulator_is_enabled_regmap,
380 .enable = regulator_enable_regmap,
381 .disable = regulator_disable_regmap,
382 .list_voltage = regulator_list_voltage_linear,
383 .get_voltage_sel = regulator_get_voltage_sel_regmap,
384 .set_voltage_sel = regulator_set_voltage_sel_regmap,
385 .get_current_limit = as3722_ldo_get_current_limit,
386 .set_current_limit = as3722_ldo_set_current_limit,
387};
388
389static struct regulator_ops as3722_ldo0_extcntrl_ops = {
390 .list_voltage = regulator_list_voltage_linear,
391 .get_voltage_sel = regulator_get_voltage_sel_regmap,
392 .set_voltage_sel = regulator_set_voltage_sel_regmap,
393 .get_current_limit = as3722_ldo_get_current_limit,
394 .set_current_limit = as3722_ldo_set_current_limit,
395};
396
397static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
398 int id, u8 mode)
399{
400 struct as3722 *as3722 = as3722_reg->as3722;
401
402 switch (mode) {
403 case AS3722_LDO3_MODE_PMOS:
404 case AS3722_LDO3_MODE_PMOS_TRACKING:
405 case AS3722_LDO3_MODE_NMOS:
406 case AS3722_LDO3_MODE_SWITCH:
407 return as3722_update_bits(as3722,
408 as3722_reg_lookup[id].vsel_reg,
409 AS3722_LDO3_MODE_MASK, mode);
410
411 default:
412 return -EINVAL;
413 }
414}
415
416static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
417{
418 return 150000;
419}
420
421static struct regulator_ops as3722_ldo3_ops = {
422 .is_enabled = regulator_is_enabled_regmap,
423 .enable = regulator_enable_regmap,
424 .disable = regulator_disable_regmap,
425 .list_voltage = regulator_list_voltage_linear,
426 .get_voltage_sel = regulator_get_voltage_sel_regmap,
427 .set_voltage_sel = regulator_set_voltage_sel_regmap,
428 .get_current_limit = as3722_ldo3_get_current_limit,
429};
430
431static struct regulator_ops as3722_ldo3_extcntrl_ops = {
432 .list_voltage = regulator_list_voltage_linear,
433 .get_voltage_sel = regulator_get_voltage_sel_regmap,
434 .set_voltage_sel = regulator_set_voltage_sel_regmap,
435 .get_current_limit = as3722_ldo3_get_current_limit,
436};
437
438#define regulator_lin_range(_min_sel, _max_sel, _min_uV, _step_uV) \
439 { \
440 .min_sel = _min_sel, \
441 .max_sel = _max_sel, \
442 .uV_step = _step_uV, \
443 .min_uV = _min_uV, \
444 .max_uV = _min_uV + (_max_sel - _min_sel) * _step_uV, \
445 }
446
447static const struct regulator_linear_range as3722_ldo_ranges[] = {
448 regulator_lin_range(0x01, 0x24, 825000, 25000),
449 regulator_lin_range(0x40, 0x7F, 1725000, 25000),
450};
451
452static struct regulator_ops as3722_ldo_ops = {
453 .is_enabled = regulator_is_enabled_regmap,
454 .enable = regulator_enable_regmap,
455 .disable = regulator_disable_regmap,
456 .map_voltage = regulator_map_voltage_linear_range,
457 .set_voltage_sel = regulator_set_voltage_sel_regmap,
458 .get_voltage_sel = regulator_get_voltage_sel_regmap,
459 .list_voltage = regulator_list_voltage_linear_range,
460 .get_current_limit = as3722_ldo_get_current_limit,
461 .set_current_limit = as3722_ldo_set_current_limit,
462};
463
464static struct regulator_ops as3722_ldo_extcntrl_ops = {
465 .map_voltage = regulator_map_voltage_linear_range,
466 .set_voltage_sel = regulator_set_voltage_sel_regmap,
467 .get_voltage_sel = regulator_get_voltage_sel_regmap,
468 .list_voltage = regulator_list_voltage_linear_range,
469 .get_current_limit = as3722_ldo_get_current_limit,
470 .set_current_limit = as3722_ldo_set_current_limit,
471};
472
473static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
474{
475 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
476 struct as3722 *as3722 = as3722_regs->as3722;
477 int id = rdev_get_id(rdev);
478 u32 val;
479 int ret;
480
481 if (!as3722_reg_lookup[id].control_reg)
482 return -ENOTSUPP;
483
484 ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
485 if (ret < 0) {
486 dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
487 as3722_reg_lookup[id].control_reg, ret);
488 return ret;
489 }
490
491 if (val & as3722_reg_lookup[id].mode_mask)
492 return REGULATOR_MODE_FAST;
493 else
494 return REGULATOR_MODE_NORMAL;
495}
496
497static int as3722_sd_set_mode(struct regulator_dev *rdev,
498 unsigned int mode)
499{
500 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
501 struct as3722 *as3722 = as3722_regs->as3722;
502 u8 id = rdev_get_id(rdev);
503 u8 val = 0;
504 int ret;
505
506 if (!as3722_reg_lookup[id].control_reg)
507 return -ERANGE;
508
509 switch (mode) {
510 case REGULATOR_MODE_FAST:
511 val = as3722_reg_lookup[id].mode_mask;
512 case REGULATOR_MODE_NORMAL: /* fall down */
513 break;
514 default:
515 return -EINVAL;
516 }
517
518 ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
519 as3722_reg_lookup[id].mode_mask, val);
520 if (ret < 0) {
521 dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
522 as3722_reg_lookup[id].control_reg, ret);
523 return ret;
524 }
525 return ret;
526}
527
528static int as3722_sd016_get_current_limit(struct regulator_dev *rdev)
529{
530 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
531 struct as3722 *as3722 = as3722_regs->as3722;
532 int id = rdev_get_id(rdev);
533 u32 val, reg;
534 int mask;
535 int ret;
536
537 switch (id) {
538 case AS3722_REGULATOR_ID_SD0:
539 reg = AS3722_OVCURRENT_REG;
540 mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
541 break;
542 case AS3722_REGULATOR_ID_SD1:
543 reg = AS3722_OVCURRENT_REG;
544 mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
545 break;
546 case AS3722_REGULATOR_ID_SD6:
547 reg = AS3722_OVCURRENT_DEB_REG;
548 mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
549 break;
550 default:
551 return -EINVAL;
552 }
553 ret = as3722_read(as3722, reg, &val);
554 if (ret < 0) {
555 dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
556 reg, ret);
557 return ret;
558 }
559 val &= mask;
560 val >>= ffs(mask) - 1;
561 if (val == 3)
562 return -EINVAL;
563 return as3722_sd016_current[val];
564}
565
566static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
567 int min_uA, int max_uA)
568{
569 struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
570 struct as3722 *as3722 = as3722_regs->as3722;
571 int id = rdev_get_id(rdev);
572 int ret;
573 int val;
574 int mask;
575 u32 reg;
576
577 ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current,
578 ARRAY_SIZE(as3722_sd016_current));
579 if (ret < 0) {
580 dev_err(as3722_regs->dev,
581 "Current range min:max = %d:%d does not support\n",
582 min_uA, max_uA);
583 return ret;
584 }
585
586 switch (id) {
587 case AS3722_REGULATOR_ID_SD0:
588 reg = AS3722_OVCURRENT_REG;
589 mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
590 break;
591 case AS3722_REGULATOR_ID_SD1:
592 reg = AS3722_OVCURRENT_REG;
593 mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
594 break;
595 case AS3722_REGULATOR_ID_SD6:
596 reg = AS3722_OVCURRENT_DEB_REG;
597 mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
598 break;
599 default:
600 return -EINVAL;
601 }
602 val = ret & mask;
603 val <<= ffs(mask) - 1;
604 return as3722_update_bits(as3722, reg, mask, val);
605}
606
607static const struct regulator_linear_range as3722_sd2345_ranges[] = {
608 regulator_lin_range(0x01, 0x40, 612500, 12500),
609 regulator_lin_range(0x41, 0x70, 1425000, 25000),
610 regulator_lin_range(0x71, 0x7F, 2650000, 50000),
611};
612
613static struct regulator_ops as3722_sd016_ops = {
614 .is_enabled = regulator_is_enabled_regmap,
615 .enable = regulator_enable_regmap,
616 .disable = regulator_disable_regmap,
617 .list_voltage = regulator_list_voltage_linear,
618 .map_voltage = regulator_map_voltage_linear,
619 .get_voltage_sel = regulator_get_voltage_sel_regmap,
620 .set_voltage_sel = regulator_set_voltage_sel_regmap,
621 .get_current_limit = as3722_sd016_get_current_limit,
622 .set_current_limit = as3722_sd016_set_current_limit,
623 .get_mode = as3722_sd_get_mode,
624 .set_mode = as3722_sd_set_mode,
625};
626
627static struct regulator_ops as3722_sd016_extcntrl_ops = {
628 .list_voltage = regulator_list_voltage_linear,
629 .map_voltage = regulator_map_voltage_linear,
630 .get_voltage_sel = regulator_get_voltage_sel_regmap,
631 .set_voltage_sel = regulator_set_voltage_sel_regmap,
632 .get_current_limit = as3722_sd016_get_current_limit,
633 .set_current_limit = as3722_sd016_set_current_limit,
634 .get_mode = as3722_sd_get_mode,
635 .set_mode = as3722_sd_set_mode,
636};
637
638static struct regulator_ops as3722_sd2345_ops = {
639 .is_enabled = regulator_is_enabled_regmap,
640 .enable = regulator_enable_regmap,
641 .disable = regulator_disable_regmap,
642 .list_voltage = regulator_list_voltage_linear_range,
643 .map_voltage = regulator_map_voltage_linear_range,
644 .set_voltage_sel = regulator_set_voltage_sel_regmap,
645 .get_voltage_sel = regulator_get_voltage_sel_regmap,
646 .get_mode = as3722_sd_get_mode,
647 .set_mode = as3722_sd_set_mode,
648};
649
650static struct regulator_ops as3722_sd2345_extcntrl_ops = {
651 .list_voltage = regulator_list_voltage_linear_range,
652 .map_voltage = regulator_map_voltage_linear_range,
653 .set_voltage_sel = regulator_set_voltage_sel_regmap,
654 .get_voltage_sel = regulator_get_voltage_sel_regmap,
655 .get_mode = as3722_sd_get_mode,
656 .set_mode = as3722_sd_set_mode,
657};
658
659static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
660 int ext_pwr_ctrl)
661{
662 int ret;
663 unsigned int val;
664
665 if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
666 (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
667 return -EINVAL;
668
669 val = ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
670 ret = as3722_update_bits(as3722_regs->as3722,
671 as3722_reg_lookup[id].sleep_ctrl_reg,
672 as3722_reg_lookup[id].sleep_ctrl_mask, val);
673 if (ret < 0)
674 dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
675 as3722_reg_lookup[id].sleep_ctrl_reg, ret);
676 return ret;
677}
678
679static struct of_regulator_match as3722_regulator_matches[] = {
680 { .name = "sd0", },
681 { .name = "sd1", },
682 { .name = "sd2", },
683 { .name = "sd3", },
684 { .name = "sd4", },
685 { .name = "sd5", },
686 { .name = "sd6", },
687 { .name = "ldo0", },
688 { .name = "ldo1", },
689 { .name = "ldo2", },
690 { .name = "ldo3", },
691 { .name = "ldo4", },
692 { .name = "ldo5", },
693 { .name = "ldo6", },
694 { .name = "ldo7", },
695 { .name = "ldo9", },
696 { .name = "ldo10", },
697 { .name = "ldo11", },
698};
699
700static int as3722_get_regulator_dt_data(struct platform_device *pdev,
701 struct as3722_regulators *as3722_regs)
702{
703 struct device_node *np;
704 struct as3722_regulator_config_data *reg_config;
705 u32 prop;
706 int id;
707 int ret;
708
709 np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
710 if (!np) {
711 dev_err(&pdev->dev, "Device is not having regulators node\n");
712 return -ENODEV;
713 }
714 pdev->dev.of_node = np;
715
716 ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
717 ARRAY_SIZE(as3722_regulator_matches));
718 if (ret < 0) {
719 dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
720 ret);
721 return ret;
722 }
723
724 for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
725 struct device_node *reg_node;
726
727 reg_config = &as3722_regs->reg_config_data[id];
728 reg_config->reg_init = as3722_regulator_matches[id].init_data;
729 reg_node = as3722_regulator_matches[id].of_node;
730
731 if (!reg_config->reg_init || !reg_node)
732 continue;
733
734 ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
735 if (!ret) {
736 if (prop < 3)
737 reg_config->ext_control = prop;
738 else
739 dev_warn(&pdev->dev,
740 "ext-control have invalid option: %u\n",
741 prop);
742 }
743 reg_config->enable_tracking =
744 of_property_read_bool(reg_node, "ams,enable-tracking");
745 }
746 return 0;
747}
748
749static int as3722_regulator_probe(struct platform_device *pdev)
750{
751 struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
752 struct as3722_regulators *as3722_regs;
753 struct as3722_regulator_config_data *reg_config;
754 struct regulator_dev *rdev;
755 struct regulator_config config = { };
756 struct regulator_ops *ops;
757 int id;
758 int ret;
759
760 as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
761 GFP_KERNEL);
762 if (!as3722_regs)
763 return -ENOMEM;
764
765 as3722_regs->dev = &pdev->dev;
766 as3722_regs->as3722 = as3722;
767 platform_set_drvdata(pdev, as3722_regs);
768
769 ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
770 if (ret < 0)
771 return ret;
772
773 config.dev = &pdev->dev;
774 config.driver_data = as3722_regs;
775 config.regmap = as3722->regmap;
776
777 for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
778 reg_config = &as3722_regs->reg_config_data[id];
779
780 as3722_regs->desc[id].name = as3722_reg_lookup[id].name;
781 as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname;
782 as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id;
783 as3722_regs->desc[id].n_voltages =
784 as3722_reg_lookup[id].n_voltages;
785 as3722_regs->desc[id].type = REGULATOR_VOLTAGE;
786 as3722_regs->desc[id].owner = THIS_MODULE;
787 as3722_regs->desc[id].enable_reg =
788 as3722_reg_lookup[id].enable_reg;
789 as3722_regs->desc[id].enable_mask =
790 as3722_reg_lookup[id].enable_mask;
791 as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg;
792 as3722_regs->desc[id].vsel_mask =
793 as3722_reg_lookup[id].vsel_mask;
794 switch (id) {
795 case AS3722_REGULATOR_ID_LDO0:
796 if (reg_config->ext_control)
797 ops = &as3722_ldo0_extcntrl_ops;
798 else
799 ops = &as3722_ldo0_ops;
800 as3722_regs->desc[id].min_uV = 825000;
801 as3722_regs->desc[id].uV_step = 25000;
802 as3722_regs->desc[id].linear_min_sel = 1;
803 as3722_regs->desc[id].enable_time = 500;
804 break;
805 case AS3722_REGULATOR_ID_LDO3:
806 if (reg_config->ext_control)
807 ops = &as3722_ldo3_extcntrl_ops;
808 else
809 ops = &as3722_ldo3_ops;
810 as3722_regs->desc[id].min_uV = 620000;
811 as3722_regs->desc[id].uV_step = 20000;
812 as3722_regs->desc[id].linear_min_sel = 1;
813 as3722_regs->desc[id].enable_time = 500;
814 if (reg_config->enable_tracking) {
815 ret = as3722_ldo3_set_tracking_mode(as3722_regs,
816 id, AS3722_LDO3_MODE_PMOS_TRACKING);
817 if (ret < 0) {
818 dev_err(&pdev->dev,
819 "LDO3 tracking failed: %d\n",
820 ret);
821 return ret;
822 }
823 }
824 break;
825 case AS3722_REGULATOR_ID_SD0:
826 case AS3722_REGULATOR_ID_SD1:
827 case AS3722_REGULATOR_ID_SD6:
828 if (reg_config->ext_control)
829 ops = &as3722_sd016_extcntrl_ops;
830 else
831 ops = &as3722_sd016_ops;
832 as3722_regs->desc[id].min_uV = 610000;
833 as3722_regs->desc[id].uV_step = 10000;
834 as3722_regs->desc[id].linear_min_sel = 1;
835 break;
836 case AS3722_REGULATOR_ID_SD2:
837 case AS3722_REGULATOR_ID_SD3:
838 case AS3722_REGULATOR_ID_SD4:
839 case AS3722_REGULATOR_ID_SD5:
840 if (reg_config->ext_control)
841 ops = &as3722_sd2345_extcntrl_ops;
842 else
843 ops = &as3722_sd2345_ops;
844 as3722_regs->desc[id].linear_ranges =
845 as3722_sd2345_ranges;
846 as3722_regs->desc[id].n_linear_ranges =
847 ARRAY_SIZE(as3722_sd2345_ranges);
848 break;
849 default:
850 if (reg_config->ext_control)
851 ops = &as3722_ldo_extcntrl_ops;
852 else
853 ops = &as3722_ldo_ops;
854 as3722_regs->desc[id].min_uV = 825000;
855 as3722_regs->desc[id].uV_step = 25000;
856 as3722_regs->desc[id].linear_min_sel = 1;
857 as3722_regs->desc[id].enable_time = 500;
858 as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
859 as3722_regs->desc[id].n_linear_ranges =
860 ARRAY_SIZE(as3722_ldo_ranges);
861 break;
862 }
863 as3722_regs->desc[id].ops = ops;
864 config.init_data = reg_config->reg_init;
865 config.of_node = as3722_regulator_matches[id].of_node;
866 rdev = devm_regulator_register(&pdev->dev,
867 &as3722_regs->desc[id], &config);
868 if (IS_ERR(rdev)) {
869 ret = PTR_ERR(rdev);
870 dev_err(&pdev->dev, "regulator %d register failed %d\n",
871 id, ret);
872 return ret;
873 }
874
875 as3722_regs->rdevs[id] = rdev;
876 if (reg_config->ext_control) {
877 ret = regulator_enable_regmap(rdev);
878 if (ret < 0) {
879 dev_err(&pdev->dev,
880 "Regulator %d enable failed: %d\n",
881 id, ret);
882 return ret;
883 }
884 ret = as3722_extreg_init(as3722_regs, id,
885 reg_config->ext_control);
886 if (ret < 0) {
887 dev_err(&pdev->dev,
888 "AS3722 ext control failed: %d", ret);
889 return ret;
890 }
891 }
892 }
893 return 0;
894}
895
896static const struct of_device_id of_as3722_regulator_match[] = {
897 { .compatible = "ams,as3722-regulator", },
898 {},
899};
900MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
901
902static struct platform_driver as3722_regulator_driver = {
903 .driver = {
904 .name = "as3722-regulator",
905 .owner = THIS_MODULE,
906 .of_match_table = of_as3722_regulator_match,
907 },
908 .probe = as3722_regulator_probe,
909};
910
911module_platform_driver(as3722_regulator_driver);
912
913MODULE_ALIAS("platform:as3722-regulator");
914MODULE_DESCRIPTION("AS3722 regulator driver");
915MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
916MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
917MODULE_LICENSE("GPL");