mfd: cpcap: Add CPCAP drivers
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / cpcap-regulator.c
1 /*
2  * Copyright (C) 2009 Motorola, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
16  * 02111-1307, USA
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/device.h>
23 #include <linux/err.h>
24 #include <linux/platform_device.h>
25 #include <linux/delay.h>
26
27 #include <linux/regulator/driver.h>
28 #include <linux/regulator/machine.h>
29
30 #include <linux/spi/spi.h>
31 #include <linux/spi/cpcap.h>
32 #include <linux/spi/cpcap-regbits.h>
33
34 #define CPCAP_REGULATOR(_name, _id)             \
35         {                                       \
36                 .name = _name,                  \
37                 .id = _id,                      \
38                 .ops = &cpcap_regulator_ops,    \
39                 .type = REGULATOR_VOLTAGE,      \
40                 .owner = THIS_MODULE,           \
41         }
42
43
44 static const int sw5_val_tbl[] = {0, 5050000};
45 static const int vcam_val_tbl[] = {2600000, 2700000, 2800000, 2900000};
46 static const int vcsi_val_tbl[] = {1200000, 1800000};
47 static const int vdac_val_tbl[] = {1200000, 1500000, 1800000, 2500000};
48 static const int vdig_val_tbl[] = {1200000, 1350000, 1500000, 1875000};
49 static const int vfuse_val_tbl[] = {1500000, 1600000, 1700000, 1800000, 1900000,
50                                     2000000, 2100000, 2200000, 2300000, 2400000,
51                                     2500000, 2600000, 2700000, 3150000};
52 static const int vhvio_val_tbl[] = {2775000};
53 static const int vsdio_val_tbl[] = {1500000, 1600000, 1800000, 2600000,
54                                     2700000, 2800000, 2900000, 3000000};
55 static const int vpll_val_tbl[] = {1200000, 1300000, 1400000, 1800000};
56 static const int vrf1_val_tbl[] = {2775000, 2500000}; /* Yes, this is correct */
57 static const int vrf2_val_tbl[] = {0, 2775000};
58 static const int vrfref_val_tbl[] = {2500000, 2775000};
59 static const int vwlan1_val_tbl[] = {1800000, 1900000};
60 static const int vwlan2_val_tbl[] = {2775000, 3000000, 3300000, 3300000};
61 static const int vsim_val_tbl[] = {1800000, 2900000};
62 static const int vsimcard_val_tbl[] = {1800000, 2900000};
63 static const int vvib_val_tbl[] = {1300000, 1800000, 2000000, 3000000};
64 static const int vusb_val_tbl[] = {0, 3300000};
65 static const int vaudio_val_tbl[] = {0, 2775000};
66
67 static struct {
68         const enum cpcap_reg reg;
69         const unsigned short mode_mask;
70         const unsigned short volt_mask;
71         const unsigned char volt_shft;
72         unsigned short mode_val;
73         unsigned short off_mode_val;
74         const int val_tbl_sz;
75         const int *val_tbl;
76         unsigned int mode_cntr;
77         const unsigned int volt_trans_time; /* in micro seconds */
78         const unsigned int turn_on_time; /* in micro seconds */
79 } cpcap_regltr_data[CPCAP_NUM_REGULATORS] = {
80         [CPCAP_SW5]      = {CPCAP_REG_S5C,
81                             0x002A,
82                             0x0000,
83                             0,
84                             0x0000,
85                             0x0000,
86                             ARRAY_SIZE(sw5_val_tbl),
87                             sw5_val_tbl,
88                             0,
89                             0,
90                             1500},
91
92         [CPCAP_VCAM]     = {CPCAP_REG_VCAMC,
93                             0x0087,
94                             0x0030,
95                             4,
96                             0x0000,
97                             0x0000,
98                             ARRAY_SIZE(vcam_val_tbl),
99                             vcam_val_tbl,
100                             0,
101                             420,
102                             1000},
103
104         [CPCAP_VCSI]     = {CPCAP_REG_VCSIC,
105                             0x0047,
106                             0x0010,
107                             4,
108                             0x0000,
109                             0x0000,
110                             ARRAY_SIZE(vcsi_val_tbl),
111                             vcsi_val_tbl,
112                             0,
113                             350,
114                             1000},
115
116         [CPCAP_VDAC]     = {CPCAP_REG_VDACC,
117                             0x0087,
118                             0x0030,
119                             4,
120                             0x0000,
121                             0x0000,
122                             ARRAY_SIZE(vdac_val_tbl),
123                             vdac_val_tbl,
124                             0,
125                             420,
126                             1000},
127
128         [CPCAP_VDIG]     = {CPCAP_REG_VDIGC,
129                             0x0087,
130                             0x0030,
131                             4,
132                             0x0000,
133                             0x0000,
134                             ARRAY_SIZE(vdig_val_tbl),
135                             vdig_val_tbl,
136                             0,
137                             420,
138                             1000},
139
140         [CPCAP_VFUSE]    = {CPCAP_REG_VFUSEC,
141                             0x0080,
142                             0x000F,
143                             0,
144                             0x0000,
145                             0x0000,
146                             ARRAY_SIZE(vfuse_val_tbl),
147                             vfuse_val_tbl,
148                             0,
149                             420,
150                             1000},
151
152         [CPCAP_VHVIO]    = {CPCAP_REG_VHVIOC,
153                             0x0017,
154                             0x0000,
155                             0,
156                             0x0000,
157                             0x0000,
158                             ARRAY_SIZE(vhvio_val_tbl),
159                             vhvio_val_tbl,
160                             0,
161                             0,
162                             1000},
163
164         [CPCAP_VSDIO]    = {CPCAP_REG_VSDIOC,
165                             0x0087,
166                             0x0038,
167                             3,
168                             0x0000,
169                             0x0000,
170                             ARRAY_SIZE(vsdio_val_tbl),
171                             vsdio_val_tbl,
172                             0,
173                             420,
174                             1000},
175
176         [CPCAP_VPLL]     = {CPCAP_REG_VPLLC,
177                             0x0043,
178                             0x0018,
179                             3,
180                             0x0000,
181                             0x0000,
182                             ARRAY_SIZE(vpll_val_tbl),
183                             vpll_val_tbl,
184                             0,
185                             420,
186                             100},
187
188         [CPCAP_VRF1]     = {CPCAP_REG_VRF1C,
189                             0x00AC,
190                             0x0002,
191                             1,
192                             0x0000,
193                             0x0000,
194                             ARRAY_SIZE(vrf1_val_tbl),
195                             vrf1_val_tbl,
196                             0,
197                             10,
198                             1000},
199
200         [CPCAP_VRF2]     = {CPCAP_REG_VRF2C,
201                             0x0023,
202                             0x0008,
203                             3,
204                             0x0000,
205                             0x0000,
206                             ARRAY_SIZE(vrf2_val_tbl),
207                             vrf2_val_tbl,
208                             0,
209                             10,
210                             1000},
211
212         [CPCAP_VRFREF]   = {CPCAP_REG_VRFREFC,
213                             0x0023,
214                             0x0008,
215                             3,
216                             0x0000,
217                             0x0000,
218                             ARRAY_SIZE(vrfref_val_tbl),
219                             vrfref_val_tbl,
220                             0,
221                             420,
222                             100},
223
224         [CPCAP_VWLAN1]   = {CPCAP_REG_VWLAN1C,
225                             0x0047,
226                             0x0010,
227                             4,
228                             0x0000,
229                             0x0000,
230                             ARRAY_SIZE(vwlan1_val_tbl),
231                             vwlan1_val_tbl,
232                             0,
233                             420,
234                             1000},
235
236         [CPCAP_VWLAN2]   = {CPCAP_REG_VWLAN2C,
237                             0x020C,
238                             0x00C0,
239                             6,
240                             0x0000,
241                             0x0000,
242                             ARRAY_SIZE(vwlan2_val_tbl),
243                             vwlan2_val_tbl,
244                             0,
245                             420,
246                             1000},
247
248         [CPCAP_VSIM]     = {CPCAP_REG_VSIMC,
249                             0x0023,
250                             0x0008,
251                             3,
252                             0x0000,
253                             0x0000,
254                             ARRAY_SIZE(vsim_val_tbl),
255                             vsim_val_tbl,
256                             0,
257                             420,
258                             1000},
259
260         [CPCAP_VSIMCARD] = {CPCAP_REG_VSIMC,
261                             0x1E80,
262                             0x0008,
263                             3,
264                             0x0000,
265                             0x0000,
266                             ARRAY_SIZE(vsimcard_val_tbl),
267                             vsimcard_val_tbl,
268                             0,
269                             420,
270                             1000},
271
272         [CPCAP_VVIB]     = {CPCAP_REG_VVIBC,
273                             0x0001,
274                             0x000C,
275                             2,
276                             0x0000,
277                             0x0000,
278                             ARRAY_SIZE(vvib_val_tbl),
279                             vvib_val_tbl,
280                             0,
281                             500,
282                             500},
283
284         [CPCAP_VUSB]     = {CPCAP_REG_VUSBC,
285                             0x011C,
286                             0x0040,
287                             6,
288                             0x0000,
289                             0x0000,
290                             ARRAY_SIZE(vusb_val_tbl),
291                             vusb_val_tbl,
292                             0,
293                             0,
294                             1000},
295
296         [CPCAP_VAUDIO]   = {CPCAP_REG_VAUDIOC,
297                             0x0016,
298                             0x0001,
299                             0,
300                             0x0000,
301                             0x0000,
302                             ARRAY_SIZE(vaudio_val_tbl),
303                             vaudio_val_tbl,
304                             0,
305                             0,
306                             1000},
307 };
308
309 static int cpcap_regulator_set_voltage(struct regulator_dev *rdev,
310                                        int min_uV, int max_uV)
311 {
312         struct cpcap_device *cpcap;
313         int regltr_id;
314         int retval;
315         enum cpcap_reg regnr;
316         int i;
317
318         cpcap = rdev_get_drvdata(rdev);
319
320         regltr_id = rdev_get_id(rdev);
321         if (regltr_id >= CPCAP_NUM_REGULATORS)
322                 return -EINVAL;
323
324         regnr = cpcap_regltr_data[regltr_id].reg;
325
326         if (regltr_id == CPCAP_VRF1) {
327                 if (min_uV > 2500000)
328                         i = 0;
329                 else
330                         i = cpcap_regltr_data[regltr_id].volt_mask;
331         } else {
332                 for (i = 0; i < cpcap_regltr_data[regltr_id].val_tbl_sz; i++)
333                         if (cpcap_regltr_data[regltr_id].val_tbl[i] >= min_uV)
334                                 break;
335
336                 if (i >= cpcap_regltr_data[regltr_id].val_tbl_sz)
337                         i--;
338
339                 i <<= cpcap_regltr_data[regltr_id].volt_shft;
340         }
341
342         retval = cpcap_regacc_write(cpcap, regnr, i,
343                                     cpcap_regltr_data[regltr_id].volt_mask);
344
345         if ((cpcap_regltr_data[regltr_id].volt_trans_time) && (retval == 0))
346                 udelay(cpcap_regltr_data[regltr_id].volt_trans_time);
347
348         return retval;
349 }
350
351 static int cpcap_regulator_get_voltage(struct regulator_dev *rdev)
352 {
353         struct cpcap_device *cpcap;
354         int regltr_id;
355         unsigned short volt_bits;
356         enum cpcap_reg regnr;
357         unsigned int shift;
358
359         cpcap = rdev_get_drvdata(rdev);
360
361         regltr_id = rdev_get_id(rdev);
362         if (regltr_id >= CPCAP_NUM_REGULATORS)
363                 return -EINVAL;
364
365         regnr = cpcap_regltr_data[regltr_id].reg;
366
367         if (cpcap_regacc_read(cpcap, regnr, &volt_bits) < 0)
368                 return -1;
369
370         if (!(volt_bits & cpcap_regltr_data[regltr_id].mode_mask))
371                 return 0;
372
373         volt_bits &= cpcap_regltr_data[regltr_id].volt_mask;
374         shift = cpcap_regltr_data[regltr_id].volt_shft;
375
376         return cpcap_regltr_data[regltr_id].val_tbl[volt_bits >> shift];
377 }
378
379 static int cpcap_regulator_enable(struct regulator_dev *rdev)
380 {
381         struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
382         int regltr_id;
383         int retval;
384         enum cpcap_reg regnr;
385
386         regltr_id = rdev_get_id(rdev);
387         if (regltr_id >= CPCAP_NUM_REGULATORS)
388                 return -EINVAL;
389
390         regnr = cpcap_regltr_data[regltr_id].reg;
391
392         retval = cpcap_regacc_write(cpcap, regnr,
393                                     cpcap_regltr_data[regltr_id].mode_val,
394                                     cpcap_regltr_data[regltr_id].mode_mask);
395
396         if ((cpcap_regltr_data[regltr_id].turn_on_time) && (retval == 0))
397                 udelay(cpcap_regltr_data[regltr_id].turn_on_time);
398
399         return retval;
400 }
401
402 static int cpcap_regulator_disable(struct regulator_dev *rdev)
403 {
404         struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
405         int regltr_id;
406         enum cpcap_reg regnr;
407
408         regltr_id = rdev_get_id(rdev);
409         if (regltr_id >= CPCAP_NUM_REGULATORS)
410                 return -EINVAL;
411
412         regnr = cpcap_regltr_data[regltr_id].reg;
413
414         return cpcap_regacc_write(cpcap, regnr,
415                                   cpcap_regltr_data[regltr_id].off_mode_val,
416                                   cpcap_regltr_data[regltr_id].mode_mask);
417 }
418
419 static int cpcap_regulator_is_enabled(struct regulator_dev *rdev)
420 {
421         struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
422         int regltr_id;
423         enum cpcap_reg regnr;
424         unsigned short value;
425
426         regltr_id = rdev_get_id(rdev);
427         if (regltr_id >= CPCAP_NUM_REGULATORS)
428                 return -EINVAL;
429
430         regnr = cpcap_regltr_data[regltr_id].reg;
431
432         if (cpcap_regacc_read(cpcap, regnr, &value))
433                 return -1;
434
435         return (value & cpcap_regltr_data[regltr_id].mode_mask) ? 1 : 0;
436 }
437
438 static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
439                                     unsigned int mode)
440 {
441         struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
442         int regltr_id;
443         enum cpcap_reg regnr;
444         int ret = 0;
445
446         regltr_id = rdev_get_id(rdev);
447         if (regltr_id != CPCAP_VAUDIO)
448                 return -EINVAL;
449
450         regnr = cpcap_regltr_data[regltr_id].reg;
451
452         if (mode == REGULATOR_MODE_NORMAL) {
453                 if (cpcap_regltr_data[regltr_id].mode_cntr == 0) {
454                         ret = cpcap_regacc_write(cpcap, regnr,
455                                                  0,
456                                                  CPCAP_BIT_AUDIO_LOW_PWR);
457                 }
458                 if (ret == 0)
459                         cpcap_regltr_data[regltr_id].mode_cntr++;
460         } else if (mode == REGULATOR_MODE_STANDBY) {
461                 if (cpcap_regltr_data[regltr_id].mode_cntr == 1) {
462                         ret = cpcap_regacc_write(cpcap, regnr,
463                                                  CPCAP_BIT_AUDIO_LOW_PWR,
464                                                  CPCAP_BIT_AUDIO_LOW_PWR);
465                 } else if (WARN((cpcap_regltr_data[regltr_id].mode_cntr == 0),
466                                 "Unbalanced modes for supply vaudio\n"))
467                         ret = -EIO;
468
469                 if (ret == 0)
470                         cpcap_regltr_data[regltr_id].mode_cntr--;
471         }
472
473         return ret;
474 }
475
476 static struct regulator_ops cpcap_regulator_ops = {
477         .set_voltage = cpcap_regulator_set_voltage,
478         .get_voltage = cpcap_regulator_get_voltage,
479         .enable = cpcap_regulator_enable,
480         .disable = cpcap_regulator_disable,
481         .is_enabled = cpcap_regulator_is_enabled,
482         .set_mode = cpcap_regulator_set_mode,
483 };
484
485 static struct regulator_desc regulators[] = {
486         [CPCAP_SW5]      = CPCAP_REGULATOR("sw5", CPCAP_SW5),
487         [CPCAP_VCAM]     = CPCAP_REGULATOR("vcam", CPCAP_VCAM),
488         [CPCAP_VCSI]     = CPCAP_REGULATOR("vcsi", CPCAP_VCSI),
489         [CPCAP_VDAC]     = CPCAP_REGULATOR("vdac", CPCAP_VDAC),
490         [CPCAP_VDIG]     = CPCAP_REGULATOR("vdig", CPCAP_VDIG),
491         [CPCAP_VFUSE]    = CPCAP_REGULATOR("vfuse", CPCAP_VFUSE),
492         [CPCAP_VHVIO]    = CPCAP_REGULATOR("vhvio", CPCAP_VHVIO),
493         [CPCAP_VSDIO]    = CPCAP_REGULATOR("vsdio", CPCAP_VSDIO),
494         [CPCAP_VPLL]     = CPCAP_REGULATOR("vpll", CPCAP_VPLL),
495         [CPCAP_VRF1]     = CPCAP_REGULATOR("vrf1", CPCAP_VRF1),
496         [CPCAP_VRF2]     = CPCAP_REGULATOR("vrf2", CPCAP_VRF2),
497         [CPCAP_VRFREF]   = CPCAP_REGULATOR("vrfref", CPCAP_VRFREF),
498         [CPCAP_VWLAN1]   = CPCAP_REGULATOR("vwlan1", CPCAP_VWLAN1),
499         [CPCAP_VWLAN2]   = CPCAP_REGULATOR("vwlan2", CPCAP_VWLAN2),
500         [CPCAP_VSIM]     = CPCAP_REGULATOR("vsim", CPCAP_VSIM),
501         [CPCAP_VSIMCARD] = CPCAP_REGULATOR("vsimcard", CPCAP_VSIMCARD),
502         [CPCAP_VVIB]     = CPCAP_REGULATOR("vvib", CPCAP_VVIB),
503         [CPCAP_VUSB]     = CPCAP_REGULATOR("vusb", CPCAP_VUSB),
504         [CPCAP_VAUDIO]   = CPCAP_REGULATOR("vaudio", CPCAP_VAUDIO),
505 };
506
507 static int __devinit cpcap_regulator_probe(struct platform_device *pdev)
508 {
509         struct regulator_dev *rdev;
510         struct cpcap_device *cpcap;
511         struct cpcap_platform_data *data;
512         struct regulator_init_data *init;
513         int i;
514
515         /* Already set by core driver */
516         cpcap = platform_get_drvdata(pdev);
517         data = cpcap->spi->controller_data;
518         init = pdev->dev.platform_data;
519
520         for (i = 0; i < CPCAP_NUM_REGULATORS; i++) {
521                 cpcap_regltr_data[i].mode_val = data->regulator_mode_values[i];
522                 cpcap_regltr_data[i].off_mode_val =
523                         data->regulator_off_mode_values[i];
524         }
525
526         rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
527                                   init, cpcap);
528         if (IS_ERR(rdev))
529                 return PTR_ERR(rdev);
530         /* this is ok since the cpcap is still reachable from the rdev */
531         platform_set_drvdata(pdev, rdev);
532
533         if (pdev->id == CPCAP_SW5) {
534                 init = cpcap->regulator_pdev[CPCAP_VUSB]->dev.platform_data;
535                 init->supply_regulator_dev = rdev_get_dev(rdev);
536                 platform_device_add(cpcap->regulator_pdev[CPCAP_VUSB]);
537         }
538
539         return 0;
540 }
541
542 static int __devexit cpcap_regulator_remove(struct platform_device *pdev)
543 {
544         struct regulator_dev *rdev = platform_get_drvdata(pdev);
545
546         regulator_unregister(rdev);
547
548         return 0;
549 }
550
551 static struct platform_driver cpcap_regulator_driver = {
552         .driver = {
553                 .name = "cpcap-regltr",
554         },
555         .probe = cpcap_regulator_probe,
556         .remove = __devexit_p(cpcap_regulator_remove),
557 };
558
559 static int __init cpcap_regulator_init(void)
560 {
561         return platform_driver_register(&cpcap_regulator_driver);
562 }
563 subsys_initcall(cpcap_regulator_init);
564
565 static void __exit cpcap_regulator_exit(void)
566 {
567         platform_driver_unregister(&cpcap_regulator_driver);
568 }
569 module_exit(cpcap_regulator_exit);
570
571 MODULE_ALIAS("platform:cpcap-regulator");
572 MODULE_DESCRIPTION("CPCAP regulator driver");
573 MODULE_AUTHOR("Motorola");
574 MODULE_LICENSE("GPL");