5e813b9059e7753aba801b1a813b99c51e7cff64
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / as3711-regulator.c
1 /*
2  * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
3  *
4  * Copyright (C) 2012 Renesas Electronics Corporation
5  * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the version 2 of the GNU General Public License as
9  * published by the Free Software Foundation
10  */
11
12 #include <linux/err.h>
13 #include <linux/init.h>
14 #include <linux/mfd/as3711.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/regulator/driver.h>
19 #include <linux/slab.h>
20
21 struct as3711_regulator_info {
22         struct regulator_desc   desc;
23         unsigned int            max_uV;
24 };
25
26 struct as3711_regulator {
27         struct as3711_regulator_info *reg_info;
28         struct regulator_dev *rdev;
29 };
30
31 static int as3711_list_voltage_sd(struct regulator_dev *rdev,
32                                   unsigned int selector)
33 {
34         if (selector >= rdev->desc->n_voltages)
35                 return -EINVAL;
36
37         if (!selector)
38                 return 0;
39         if (selector < 0x41)
40                 return 600000 + selector * 12500;
41         if (selector < 0x71)
42                 return 1400000 + (selector - 0x40) * 25000;
43         return 2600000 + (selector - 0x70) * 50000;
44 }
45
46 static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
47                                     unsigned int selector)
48 {
49         if (selector >= rdev->desc->n_voltages)
50                 return -EINVAL;
51
52         if (selector < 0x10)
53                 return 1200000 + selector * 50000;
54         return 1800000 + (selector - 0x10) * 100000;
55 }
56
57 static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
58                                     unsigned int selector)
59 {
60         if (selector >= rdev->desc->n_voltages ||
61             (selector > 0x10 && selector < 0x20))
62                 return -EINVAL;
63
64         if (selector < 0x11)
65                 return 900000 + selector * 50000;
66         return 1750000 + (selector - 0x20) * 50000;
67 }
68
69 static int as3711_bound_check(struct regulator_dev *rdev,
70                               int *min_uV, int *max_uV)
71 {
72         struct as3711_regulator *reg = rdev_get_drvdata(rdev);
73         struct as3711_regulator_info *info = reg->reg_info;
74
75         dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
76                 *min_uV, rdev->desc->min_uV, info->max_uV);
77
78         if (*max_uV < *min_uV ||
79             *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
80                 return -EINVAL;
81
82         if (rdev->desc->n_voltages == 1)
83                 return 0;
84
85         if (*max_uV > info->max_uV)
86                 *max_uV = info->max_uV;
87
88         if (*min_uV < rdev->desc->min_uV)
89                 *min_uV = rdev->desc->min_uV;
90
91         return *min_uV;
92 }
93
94 static int as3711_sel_check(int min, int max, int bottom, int step)
95 {
96         int ret, voltage;
97
98         /* Round up min, when dividing: keeps us within the range */
99         ret = (min - bottom + step - 1) / step;
100         voltage = ret * step + bottom;
101         pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
102                min, max, bottom, step, ret);
103         if (voltage > max) {
104                 /*
105                  * Try 1 down. It will take us below min, but as long we stay
106                  * above bottom, we're fine.
107                  */
108                 ret--;
109                 voltage = ret * step + bottom;
110                 if (voltage < bottom)
111                         return -EINVAL;
112         }
113         return ret;
114 }
115
116 static int as3711_map_voltage_sd(struct regulator_dev *rdev,
117                                  int min_uV, int max_uV)
118 {
119         int ret;
120
121         ret = as3711_bound_check(rdev, &min_uV, &max_uV);
122         if (ret <= 0)
123                 return ret;
124
125         if (min_uV <= 1400000)
126                 return as3711_sel_check(min_uV, max_uV, 600000, 12500);
127
128         if (min_uV <= 2600000)
129                 return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
130
131         return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
132 }
133
134 /*
135  * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
136  * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
137  * FAST:        sdX_fast=1
138  * NORMAL:      low_noise=1
139  * IDLE:        low_noise=0
140  */
141
142 static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
143 {
144         unsigned int fast_bit = rdev->desc->enable_mask,
145                 low_noise_bit = fast_bit << 4;
146         u8 val;
147
148         switch (mode) {
149         case REGULATOR_MODE_FAST:
150                 val = fast_bit | low_noise_bit;
151                 break;
152         case REGULATOR_MODE_NORMAL:
153                 val = low_noise_bit;
154                 break;
155         case REGULATOR_MODE_IDLE:
156                 val = 0;
157                 break;
158         default:
159                 return -EINVAL;
160         }
161
162         return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
163                                   low_noise_bit | fast_bit, val);
164 }
165
166 static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
167 {
168         unsigned int fast_bit = rdev->desc->enable_mask,
169                 low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
170         unsigned int val;
171         int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
172
173         if (ret < 0)
174                 return ret;
175
176         if ((val & mask) == mask)
177                 return REGULATOR_MODE_FAST;
178
179         if ((val & mask) == low_noise_bit)
180                 return REGULATOR_MODE_NORMAL;
181
182         if (!(val & mask))
183                 return REGULATOR_MODE_IDLE;
184
185         return -EINVAL;
186 }
187
188 static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
189                                   int min_uV, int max_uV)
190 {
191         int ret;
192
193         ret = as3711_bound_check(rdev, &min_uV, &max_uV);
194         if (ret <= 0)
195                 return ret;
196
197         if (min_uV <= 1800000)
198                 return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
199
200         return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
201 }
202
203 static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
204                                   int min_uV, int max_uV)
205 {
206         int ret;
207
208         ret = as3711_bound_check(rdev, &min_uV, &max_uV);
209         if (ret <= 0)
210                 return ret;
211
212         if (min_uV <= 1700000)
213                 return as3711_sel_check(min_uV, max_uV, 900000, 50000);
214
215         return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
216 }
217
218 static struct regulator_ops as3711_sd_ops = {
219         .is_enabled             = regulator_is_enabled_regmap,
220         .enable                 = regulator_enable_regmap,
221         .disable                = regulator_disable_regmap,
222         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
223         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
224         .list_voltage           = as3711_list_voltage_sd,
225         .map_voltage            = as3711_map_voltage_sd,
226         .get_mode               = as3711_get_mode_sd,
227         .set_mode               = as3711_set_mode_sd,
228 };
229
230 static struct regulator_ops as3711_aldo_ops = {
231         .is_enabled             = regulator_is_enabled_regmap,
232         .enable                 = regulator_enable_regmap,
233         .disable                = regulator_disable_regmap,
234         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
235         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
236         .list_voltage           = as3711_list_voltage_aldo,
237         .map_voltage            = as3711_map_voltage_aldo,
238 };
239
240 static struct regulator_ops as3711_dldo_ops = {
241         .is_enabled             = regulator_is_enabled_regmap,
242         .enable                 = regulator_enable_regmap,
243         .disable                = regulator_disable_regmap,
244         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
245         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
246         .list_voltage           = as3711_list_voltage_dldo,
247         .map_voltage            = as3711_map_voltage_dldo,
248 };
249
250 #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)      \
251         [AS3711_REGULATOR_ ## _id] = {                                                  \
252         .desc = {                                                                       \
253                 .name = "as3711-regulator-" # _id,                                      \
254                 .id = AS3711_REGULATOR_ ## _id,                                         \
255                 .n_voltages = (_vmask + 1),                                             \
256                 .ops = &as3711_ ## _sfx ## _ops,                                        \
257                 .type = REGULATOR_VOLTAGE,                                              \
258                 .owner = THIS_MODULE,                                                   \
259                 .vsel_reg = AS3711_ ## _id ## _VOLTAGE,                                 \
260                 .vsel_mask = _vmask << _vshift,                                         \
261                 .enable_reg = AS3711_ ## _en_reg,                                       \
262                 .enable_mask = BIT(_en_bit),                                            \
263                 .min_uV = _min_uV,                                                      \
264         },                                                                              \
265         .max_uV = _max_uV,                                                              \
266 }
267
268 static struct as3711_regulator_info as3711_reg_info[] = {
269         AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
270         AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
271         AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
272         AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
273         AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
274         AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
275         AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
276         AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
277         AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
278         AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
279         AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
280         AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
281         /* StepUp output voltage depends on supplying regulator */
282 };
283
284 #define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
285
286 static int as3711_regulator_probe(struct platform_device *pdev)
287 {
288         struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
289         struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
290         struct regulator_init_data *reg_data;
291         struct regulator_config config = {.dev = &pdev->dev,};
292         struct as3711_regulator *reg = NULL;
293         struct as3711_regulator *regs;
294         struct regulator_dev *rdev;
295         struct as3711_regulator_info *ri;
296         int ret;
297         int id;
298
299         if (!pdata)
300                 dev_dbg(&pdev->dev, "No platform data...\n");
301
302         regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
303                         sizeof(struct as3711_regulator), GFP_KERNEL);
304         if (!regs) {
305                 dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
306                 return -ENOMEM;
307         }
308
309         for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
310                 reg_data = pdata ? pdata->init_data[id] : NULL;
311
312                 /* No need to register if there is no regulator data */
313                 if (!ri->desc.name)
314                         continue;
315
316                 reg = &regs[id];
317                 reg->reg_info = ri;
318
319                 config.init_data = reg_data;
320                 config.driver_data = reg;
321                 config.regmap = as3711->regmap;
322
323                 rdev = regulator_register(&ri->desc, &config);
324                 if (IS_ERR(rdev)) {
325                         dev_err(&pdev->dev, "Failed to register regulator %s\n",
326                                 ri->desc.name);
327                         ret = PTR_ERR(rdev);
328                         goto eregreg;
329                 }
330                 reg->rdev = rdev;
331         }
332         platform_set_drvdata(pdev, regs);
333         return 0;
334
335 eregreg:
336         while (--id >= 0)
337                 regulator_unregister(regs[id].rdev);
338
339         return ret;
340 }
341
342 static int as3711_regulator_remove(struct platform_device *pdev)
343 {
344         struct as3711_regulator *regs = platform_get_drvdata(pdev);
345         int id;
346
347         for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
348                 regulator_unregister(regs[id].rdev);
349         return 0;
350 }
351
352 static struct platform_driver as3711_regulator_driver = {
353         .driver = {
354                 .name   = "as3711-regulator",
355                 .owner  = THIS_MODULE,
356         },
357         .probe          = as3711_regulator_probe,
358         .remove         = as3711_regulator_remove,
359 };
360
361 static int __init as3711_regulator_init(void)
362 {
363         return platform_driver_register(&as3711_regulator_driver);
364 }
365 subsys_initcall(as3711_regulator_init);
366
367 static void __exit as3711_regulator_exit(void)
368 {
369         platform_driver_unregister(&as3711_regulator_driver);
370 }
371 module_exit(as3711_regulator_exit);
372
373 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
374 MODULE_DESCRIPTION("AS3711 regulator driver");
375 MODULE_ALIAS("platform:as3711-regulator");
376 MODULE_LICENSE("GPL v2");