Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/regulator/max77686.c

  1 /*
  2  * max77686.c - Regulator driver for the Maxim 77686
  3  *
  4  * Copyright (C) 2012 Samsung Electronics
  5  * Chiwoong Byun <woong.byun@smasung.com>
  6  * Jonghwa Lee <jonghwa3.lee@samsung.com>
  7  *
  8  * This program is free software; you can redistribute it and/or modify
  9  * it under the terms of the GNU General Public License as published by
 10  * the Free Software Foundation; either version 2 of the License, or
 11  * (at your option) any later version.
 12  *
 13  * This program is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  * GNU General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU General Public License
 19  * along with this program; if not, write to the Free Software
 20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 21  *
 22  * This driver is based on max8997.c
 23  */
 24 
 25 #include <linux/kernel.h>
 26 #include <linux/bug.h>
 27 #include <linux/err.h>
 28 #include <linux/gpio.h>
 29 #include <linux/slab.h>
 30 #include <linux/platform_device.h>
 31 #include <linux/regulator/driver.h>
 32 #include <linux/regulator/machine.h>
 33 #include <linux/regulator/of_regulator.h>
 34 #include <linux/mfd/max77686.h>
 35 #include <linux/mfd/max77686-private.h>
 36 
 37 #define MAX77686_LDO_MINUV      800000
 38 #define MAX77686_LDO_UVSTEP     50000
 39 #define MAX77686_LDO_LOW_MINUV  800000
 40 #define MAX77686_LDO_LOW_UVSTEP 25000
 41 #define MAX77686_BUCK_MINUV     750000
 42 #define MAX77686_BUCK_UVSTEP    50000
 43 #define MAX77686_RAMP_DELAY     100000                  /* uV/us */
 44 #define MAX77686_DVS_RAMP_DELAY 27500                   /* uV/us */
 45 #define MAX77686_DVS_MINUV      600000
 46 #define MAX77686_DVS_UVSTEP     12500
 47 
 48 #define MAX77686_OPMODE_SHIFT   6
 49 #define MAX77686_OPMODE_BUCK234_SHIFT   4
 50 #define MAX77686_OPMODE_MASK    0x3
 51 
 52 #define MAX77686_VSEL_MASK      0x3F
 53 #define MAX77686_DVS_VSEL_MASK  0xFF
 54 
 55 #define MAX77686_RAMP_RATE_MASK 0xC0
 56 
 57 #define MAX77686_REGULATORS     MAX77686_REG_MAX
 58 #define MAX77686_LDOS           26
 59 
 60 enum max77686_ramp_rate {
 61         RAMP_RATE_13P75MV,
 62         RAMP_RATE_27P5MV,
 63         RAMP_RATE_55MV,
 64         RAMP_RATE_NO_CTRL,      /* 100mV/us */
 65 };
 66 
 67 struct max77686_data {
 68         unsigned int opmode[MAX77686_REGULATORS];
 69 };
 70 
 71 /* Some BUCKS supports Normal[ON/OFF] mode during suspend */
 72 static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
 73 {
 74         unsigned int val;
 75         struct max77686_data *max77686 = rdev_get_drvdata(rdev);
 76         int ret, id = rdev_get_id(rdev);
 77 
 78         if (id == MAX77686_BUCK1)
 79                 val = 0x1;
 80         else
 81                 val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
 82 
 83         ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 84                                  rdev->desc->enable_mask, val);
 85         if (ret)
 86                 return ret;
 87 
 88         max77686->opmode[id] = val;
 89         return 0;
 90 }
 91 
 92 /* Some LDOs supports [LPM/Normal]ON mode during suspend state */
 93 static int max77686_set_suspend_mode(struct regulator_dev *rdev,
 94                                      unsigned int mode)
 95 {
 96         struct max77686_data *max77686 = rdev_get_drvdata(rdev);
 97         unsigned int val;
 98         int ret, id = rdev_get_id(rdev);
 99 
100         /* BUCK[5-9] doesn't support this feature */
101         if (id >= MAX77686_BUCK5)
102                 return 0;
103 
104         switch (mode) {
105         case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
106                 val = 0x2 << MAX77686_OPMODE_SHIFT;
107                 break;
108         case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
109                 val = 0x3 << MAX77686_OPMODE_SHIFT;
110                 break;
111         default:
112                 pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
113                         rdev->desc->name, mode);
114                 return -EINVAL;
115         }
116 
117         ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
118                                   rdev->desc->enable_mask, val);
119         if (ret)
120                 return ret;
121 
122         max77686->opmode[id] = val;
123         return 0;
124 }
125 
126 /* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
127 static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
128                                      unsigned int mode)
129 {
130         unsigned int val;
131         struct max77686_data *max77686 = rdev_get_drvdata(rdev);
132         int ret;
133 
134         switch (mode) {
135         case REGULATOR_MODE_STANDBY:                    /* switch off */
136                 val = 0x1 << MAX77686_OPMODE_SHIFT;
137                 break;
138         case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
139                 val = 0x2 << MAX77686_OPMODE_SHIFT;
140                 break;
141         case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
142                 val = 0x3 << MAX77686_OPMODE_SHIFT;
143                 break;
144         default:
145                 pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
146                         rdev->desc->name, mode);
147                 return -EINVAL;
148         }
149 
150         ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
151                                  rdev->desc->enable_mask, val);
152         if (ret)
153                 return ret;
154 
155         max77686->opmode[rdev_get_id(rdev)] = val;
156         return 0;
157 }
158 
159 static int max77686_enable(struct regulator_dev *rdev)
160 {
161         struct max77686_data *max77686 = rdev_get_drvdata(rdev);
162 
163         return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
164                                   rdev->desc->enable_mask,
165                                   max77686->opmode[rdev_get_id(rdev)]);
166 }
167 
168 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
169 {
170         unsigned int ramp_value = RAMP_RATE_NO_CTRL;
171 
172         switch (ramp_delay) {
173         case 1 ... 13750:
174                 ramp_value = RAMP_RATE_13P75MV;
175                 break;
176         case 13751 ... 27500:
177                 ramp_value = RAMP_RATE_27P5MV;
178                 break;
179         case 27501 ... 55000:
180                 ramp_value = RAMP_RATE_55MV;
181                 break;
182         case 55001 ... 100000:
183                 break;
184         default:
185                 pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
186                         rdev->desc->name, ramp_delay);
187         }
188 
189         return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
190                                   MAX77686_RAMP_RATE_MASK, ramp_value << 6);
191 }
192 
193 static struct regulator_ops max77686_ops = {
194         .list_voltage           = regulator_list_voltage_linear,
195         .map_voltage            = regulator_map_voltage_linear,
196         .is_enabled             = regulator_is_enabled_regmap,
197         .enable                 = max77686_enable,
198         .disable                = regulator_disable_regmap,
199         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
200         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
201         .set_voltage_time_sel   = regulator_set_voltage_time_sel,
202         .set_suspend_mode       = max77686_set_suspend_mode,
203 };
204 
205 static struct regulator_ops max77686_ldo_ops = {
206         .list_voltage           = regulator_list_voltage_linear,
207         .map_voltage            = regulator_map_voltage_linear,
208         .is_enabled             = regulator_is_enabled_regmap,
209         .enable                 = max77686_enable,
210         .disable                = regulator_disable_regmap,
211         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
212         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
213         .set_voltage_time_sel   = regulator_set_voltage_time_sel,
214         .set_suspend_mode       = max77686_ldo_set_suspend_mode,
215 };
216 
217 static struct regulator_ops max77686_buck1_ops = {
218         .list_voltage           = regulator_list_voltage_linear,
219         .map_voltage            = regulator_map_voltage_linear,
220         .is_enabled             = regulator_is_enabled_regmap,
221         .enable                 = max77686_enable,
222         .disable                = regulator_disable_regmap,
223         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
224         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
225         .set_voltage_time_sel   = regulator_set_voltage_time_sel,
226         .set_suspend_disable    = max77686_buck_set_suspend_disable,
227 };
228 
229 static struct regulator_ops max77686_buck_dvs_ops = {
230         .list_voltage           = regulator_list_voltage_linear,
231         .map_voltage            = regulator_map_voltage_linear,
232         .is_enabled             = regulator_is_enabled_regmap,
233         .enable                 = max77686_enable,
234         .disable                = regulator_disable_regmap,
235         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
236         .set_voltage_sel        = regulator_set_voltage_sel_regmap,
237         .set_voltage_time_sel   = regulator_set_voltage_time_sel,
238         .set_ramp_delay         = max77686_set_ramp_delay,
239         .set_suspend_disable    = max77686_buck_set_suspend_disable,
240 };
241 
242 #define regulator_desc_ldo(num)         {                               \
243         .name           = "LDO"#num,                                    \
244         .id             = MAX77686_LDO##num,                            \
245         .ops            = &max77686_ops,                                \
246         .type           = REGULATOR_VOLTAGE,                            \
247         .owner          = THIS_MODULE,                                  \
248         .min_uV         = MAX77686_LDO_MINUV,                           \
249         .uV_step        = MAX77686_LDO_UVSTEP,                          \
250         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
251         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
252         .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
253         .vsel_mask      = MAX77686_VSEL_MASK,                           \
254         .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
255         .enable_mask    = MAX77686_OPMODE_MASK                          \
256                         << MAX77686_OPMODE_SHIFT,                       \
257 }
258 #define regulator_desc_lpm_ldo(num)     {                               \
259         .name           = "LDO"#num,                                    \
260         .id             = MAX77686_LDO##num,                            \
261         .ops            = &max77686_ldo_ops,                            \
262         .type           = REGULATOR_VOLTAGE,                            \
263         .owner          = THIS_MODULE,                                  \
264         .min_uV         = MAX77686_LDO_MINUV,                           \
265         .uV_step        = MAX77686_LDO_UVSTEP,                          \
266         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
267         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
268         .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
269         .vsel_mask      = MAX77686_VSEL_MASK,                           \
270         .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
271         .enable_mask    = MAX77686_OPMODE_MASK                          \
272                         << MAX77686_OPMODE_SHIFT,                       \
273 }
274 #define regulator_desc_ldo_low(num)             {                       \
275         .name           = "LDO"#num,                                    \
276         .id             = MAX77686_LDO##num,                            \
277         .ops            = &max77686_ldo_ops,                            \
278         .type           = REGULATOR_VOLTAGE,                            \
279         .owner          = THIS_MODULE,                                  \
280         .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
281         .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
282         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
283         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
284         .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
285         .vsel_mask      = MAX77686_VSEL_MASK,                           \
286         .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
287         .enable_mask    = MAX77686_OPMODE_MASK                          \
288                         << MAX77686_OPMODE_SHIFT,                       \
289 }
290 #define regulator_desc_ldo1_low(num)            {                       \
291         .name           = "LDO"#num,                                    \
292         .id             = MAX77686_LDO##num,                            \
293         .ops            = &max77686_ops,                                \
294         .type           = REGULATOR_VOLTAGE,                            \
295         .owner          = THIS_MODULE,                                  \
296         .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
297         .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
298         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
299         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
300         .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
301         .vsel_mask      = MAX77686_VSEL_MASK,                           \
302         .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
303         .enable_mask    = MAX77686_OPMODE_MASK                          \
304                         << MAX77686_OPMODE_SHIFT,                       \
305 }
306 #define regulator_desc_buck(num)                {                       \
307         .name           = "BUCK"#num,                                   \
308         .id             = MAX77686_BUCK##num,                           \
309         .ops            = &max77686_ops,                                \
310         .type           = REGULATOR_VOLTAGE,                            \
311         .owner          = THIS_MODULE,                                  \
312         .min_uV         = MAX77686_BUCK_MINUV,                          \
313         .uV_step        = MAX77686_BUCK_UVSTEP,                         \
314         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
315         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
316         .vsel_reg       = MAX77686_REG_BUCK5OUT + (num - 5) * 2,        \
317         .vsel_mask      = MAX77686_VSEL_MASK,                           \
318         .enable_reg     = MAX77686_REG_BUCK5CTRL + (num - 5) * 2,       \
319         .enable_mask    = MAX77686_OPMODE_MASK,                         \
320 }
321 #define regulator_desc_buck1(num)               {                       \
322         .name           = "BUCK"#num,                                   \
323         .id             = MAX77686_BUCK##num,                           \
324         .ops            = &max77686_buck1_ops,                          \
325         .type           = REGULATOR_VOLTAGE,                            \
326         .owner          = THIS_MODULE,                                  \
327         .min_uV         = MAX77686_BUCK_MINUV,                          \
328         .uV_step        = MAX77686_BUCK_UVSTEP,                         \
329         .ramp_delay     = MAX77686_RAMP_DELAY,                          \
330         .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
331         .vsel_reg       = MAX77686_REG_BUCK1OUT,                        \
332         .vsel_mask      = MAX77686_VSEL_MASK,                           \
333         .enable_reg     = MAX77686_REG_BUCK1CTRL,                       \
334         .enable_mask    = MAX77686_OPMODE_MASK,                         \
335 }
336 #define regulator_desc_buck_dvs(num)            {                       \
337         .name           = "BUCK"#num,                                   \
338         .id             = MAX77686_BUCK##num,                           \
339         .ops            = &max77686_buck_dvs_ops,                       \
340         .type           = REGULATOR_VOLTAGE,                            \
341         .owner          = THIS_MODULE,                                  \
342         .min_uV         = MAX77686_DVS_MINUV,                           \
343         .uV_step        = MAX77686_DVS_UVSTEP,                          \
344         .ramp_delay     = MAX77686_DVS_RAMP_DELAY,                      \
345         .n_voltages     = MAX77686_DVS_VSEL_MASK + 1,                   \
346         .vsel_reg       = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,      \
347         .vsel_mask      = MAX77686_DVS_VSEL_MASK,                       \
348         .enable_reg     = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,     \
349         .enable_mask    = MAX77686_OPMODE_MASK                          \
350                         << MAX77686_OPMODE_BUCK234_SHIFT,               \
351 }
352 
353 static struct regulator_desc regulators[] = {
354         regulator_desc_ldo1_low(1),
355         regulator_desc_ldo_low(2),
356         regulator_desc_ldo(3),
357         regulator_desc_ldo(4),
358         regulator_desc_ldo(5),
359         regulator_desc_ldo_low(6),
360         regulator_desc_ldo_low(7),
361         regulator_desc_ldo_low(8),
362         regulator_desc_ldo(9),
363         regulator_desc_lpm_ldo(10),
364         regulator_desc_lpm_ldo(11),
365         regulator_desc_lpm_ldo(12),
366         regulator_desc_ldo(13),
367         regulator_desc_lpm_ldo(14),
368         regulator_desc_ldo_low(15),
369         regulator_desc_lpm_ldo(16),
370         regulator_desc_ldo(17),
371         regulator_desc_ldo(18),
372         regulator_desc_ldo(19),
373         regulator_desc_ldo(20),
374         regulator_desc_ldo(21),
375         regulator_desc_ldo(22),
376         regulator_desc_ldo(23),
377         regulator_desc_ldo(24),
378         regulator_desc_ldo(25),
379         regulator_desc_ldo(26),
380         regulator_desc_buck1(1),
381         regulator_desc_buck_dvs(2),
382         regulator_desc_buck_dvs(3),
383         regulator_desc_buck_dvs(4),
384         regulator_desc_buck(5),
385         regulator_desc_buck(6),
386         regulator_desc_buck(7),
387         regulator_desc_buck(8),
388         regulator_desc_buck(9),
389 };
390 
391 #ifdef CONFIG_OF
392 static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
393                                         struct max77686_platform_data *pdata)
394 {
395         struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
396         struct device_node *pmic_np, *regulators_np;
397         struct max77686_regulator_data *rdata;
398         struct of_regulator_match rmatch;
399         unsigned int i;
400 
401         pmic_np = iodev->dev->of_node;
402         regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
403         if (!regulators_np) {
404                 dev_err(&pdev->dev, "could not find regulators sub-node\n");
405                 return -EINVAL;
406         }
407 
408         pdata->num_regulators = ARRAY_SIZE(regulators);
409         rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
410                              pdata->num_regulators, GFP_KERNEL);
411         if (!rdata) {
412                 of_node_put(regulators_np);
413                 return -ENOMEM;
414         }
415 
416         for (i = 0; i < pdata->num_regulators; i++) {
417                 rmatch.name = regulators[i].name;
418                 rmatch.init_data = NULL;
419                 rmatch.of_node = NULL;
420                 of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
421                 rdata[i].initdata = rmatch.init_data;
422                 rdata[i].of_node = rmatch.of_node;
423         }
424 
425         pdata->regulators = rdata;
426         of_node_put(regulators_np);
427 
428         return 0;
429 }
430 #else
431 static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
432                                         struct max77686_platform_data *pdata)
433 {
434         return 0;
435 }
436 #endif /* CONFIG_OF */
437 
438 static int max77686_pmic_probe(struct platform_device *pdev)
439 {
440         struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
441         struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
442         struct max77686_data *max77686;
443         int i, ret = 0;
444         struct regulator_config config = { };
445 
446         dev_dbg(&pdev->dev, "%s\n", __func__);
447 
448         if (!pdata) {
449                 dev_err(&pdev->dev, "no platform data found for regulator\n");
450                 return -ENODEV;
451         }
452 
453         if (iodev->dev->of_node) {
454                 ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
455                 if (ret)
456                         return ret;
457         }
458 
459         if (pdata->num_regulators != MAX77686_REGULATORS) {
460                 dev_err(&pdev->dev,
461                         "Invalid initial data for regulator's initialiation\n");
462                 return -EINVAL;
463         }
464 
465         max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
466                                 GFP_KERNEL);
467         if (!max77686)
468                 return -ENOMEM;
469 
470         config.dev = &pdev->dev;
471         config.regmap = iodev->regmap;
472         config.driver_data = max77686;
473         platform_set_drvdata(pdev, max77686);
474 
475         for (i = 0; i < MAX77686_REGULATORS; i++) {
476                 struct regulator_dev *rdev;
477 
478                 config.init_data = pdata->regulators[i].initdata;
479                 config.of_node = pdata->regulators[i].of_node;
480 
481                 max77686->opmode[i] = regulators[i].enable_mask;
482                 rdev = devm_regulator_register(&pdev->dev,
483                                                 &regulators[i], &config);
484                 if (IS_ERR(rdev)) {
485                         dev_err(&pdev->dev,
486                                 "regulator init failed for %d\n", i);
487                         return PTR_ERR(rdev);
488                 }
489         }
490 
491         return 0;
492 }
493 
494 static const struct platform_device_id max77686_pmic_id[] = {
495         {"max77686-pmic", 0},
496         { },
497 };
498 MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
499 
500 static struct platform_driver max77686_pmic_driver = {
501         .driver = {
502                 .name = "max77686-pmic",
503                 .owner = THIS_MODULE,
504         },
505         .probe = max77686_pmic_probe,
506         .id_table = max77686_pmic_id,
507 };
508 
509 static int __init max77686_pmic_init(void)
510 {
511         return platform_driver_register(&max77686_pmic_driver);
512 }
513 subsys_initcall(max77686_pmic_init);
514 
515 static void __exit max77686_pmic_cleanup(void)
516 {
517         platform_driver_unregister(&max77686_pmic_driver);
518 }
519 module_exit(max77686_pmic_cleanup);
520 
521 MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
522 MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
523 MODULE_LICENSE("GPL");
524 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us