GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / power / avs / rockchip-io-domain.c
1 /*
2  * Rockchip IO Voltage Domain driver
3  *
4  * Copyright 2014 MundoReader S.L.
5  * Copyright 2014 Google, Inc.
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/err.h>
20 #include <linux/mfd/syscon.h>
21 #include <linux/of.h>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
24 #include <linux/regulator/consumer.h>
25
26 #define MAX_SUPPLIES            16
27
28 /*
29  * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
30  * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
31  * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
32  *
33  * They are used like this:
34  * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
35  *   SoC we're at 3.3.
36  * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
37  *   that to be an error.
38  */
39 #define MAX_VOLTAGE_1_8         1980000
40 #define MAX_VOLTAGE_3_3         3600000
41
42 #define PX30_IO_VSEL                    0x180
43 #define PX30_IO_VSEL_VCCIO6_SRC         BIT(0)
44 #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM  1
45
46 #define RK3288_SOC_CON2                 0x24c
47 #define RK3288_SOC_CON2_FLASH0          BIT(7)
48 #define RK3288_SOC_FLASH_SUPPLY_NUM     2
49
50 #define RK3328_SOC_CON4                 0x410
51 #define RK3328_SOC_CON4_VCCIO2          BIT(7)
52 #define RK3328_SOC_VCCIO2_SUPPLY_NUM    1
53
54 #define RK3368_SOC_CON15                0x43c
55 #define RK3368_SOC_CON15_FLASH0         BIT(14)
56 #define RK3368_SOC_FLASH_SUPPLY_NUM     2
57
58 #define RK3399_PMUGRF_CON0              0x180
59 #define RK3399_PMUGRF_CON0_VSEL         BIT(8)
60 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM   9
61
62 struct rockchip_iodomain;
63
64 /**
65  * @supplies: voltage settings matching the register bits.
66  */
67 struct rockchip_iodomain_soc_data {
68         int grf_offset;
69         const char *supply_names[MAX_SUPPLIES];
70         void (*init)(struct rockchip_iodomain *iod);
71 };
72
73 struct rockchip_iodomain_supply {
74         struct rockchip_iodomain *iod;
75         struct regulator *reg;
76         struct notifier_block nb;
77         int idx;
78 };
79
80 struct rockchip_iodomain {
81         struct device *dev;
82         struct regmap *grf;
83         const struct rockchip_iodomain_soc_data *soc_data;
84         struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
85 };
86
87 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
88                                    int uV)
89 {
90         struct rockchip_iodomain *iod = supply->iod;
91         u32 val;
92         int ret;
93
94         /* set value bit */
95         val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
96         val <<= supply->idx;
97
98         /* apply hiword-mask */
99         val |= (BIT(supply->idx) << 16);
100
101         ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
102         if (ret)
103                 dev_err(iod->dev, "Couldn't write to GRF\n");
104
105         return ret;
106 }
107
108 static int rockchip_iodomain_notify(struct notifier_block *nb,
109                                     unsigned long event,
110                                     void *data)
111 {
112         struct rockchip_iodomain_supply *supply =
113                         container_of(nb, struct rockchip_iodomain_supply, nb);
114         int uV;
115         int ret;
116
117         /*
118          * According to Rockchip it's important to keep the SoC IO domain
119          * higher than (or equal to) the external voltage.  That means we need
120          * to change it before external voltage changes happen in the case
121          * of an increase.
122          *
123          * Note that in the "pre" change we pick the max possible voltage that
124          * the regulator might end up at (the client requests a range and we
125          * don't know for certain the exact voltage).  Right now we rely on the
126          * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
127          * request something like a max of 3.6V when they really want 3.3V.
128          * We could attempt to come up with better rules if this fails.
129          */
130         if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
131                 struct pre_voltage_change_data *pvc_data = data;
132
133                 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
134         } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
135                             REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
136                 uV = (unsigned long)data;
137         } else {
138                 return NOTIFY_OK;
139         }
140
141         dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
142
143         if (uV > MAX_VOLTAGE_3_3) {
144                 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
145
146                 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
147                         return NOTIFY_BAD;
148         }
149
150         ret = rockchip_iodomain_write(supply, uV);
151         if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
152                 return NOTIFY_BAD;
153
154         dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
155         return NOTIFY_OK;
156 }
157
158 static void px30_iodomain_init(struct rockchip_iodomain *iod)
159 {
160         int ret;
161         u32 val;
162
163         /* if no VCCIO0 supply we should leave things alone */
164         if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
165                 return;
166
167         /*
168          * set vccio0 iodomain to also use this framework
169          * instead of a special gpio.
170          */
171         val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
172         ret = regmap_write(iod->grf, PX30_IO_VSEL, val);
173         if (ret < 0)
174                 dev_warn(iod->dev, "couldn't update vccio0 ctrl\n");
175 }
176
177 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
178 {
179         int ret;
180         u32 val;
181
182         /* if no flash supply we should leave things alone */
183         if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
184                 return;
185
186         /*
187          * set flash0 iodomain to also use this framework
188          * instead of a special gpio.
189          */
190         val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
191         ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
192         if (ret < 0)
193                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
194 }
195
196 static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
197 {
198         int ret;
199         u32 val;
200
201         /* if no vccio2 supply we should leave things alone */
202         if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
203                 return;
204
205         /*
206          * set vccio2 iodomain to also use this framework
207          * instead of a special gpio.
208          */
209         val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
210         ret = regmap_write(iod->grf, RK3328_SOC_CON4, val);
211         if (ret < 0)
212                 dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
213 }
214
215 static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
216 {
217         int ret;
218         u32 val;
219
220         /* if no flash supply we should leave things alone */
221         if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
222                 return;
223
224         /*
225          * set flash0 iodomain to also use this framework
226          * instead of a special gpio.
227          */
228         val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
229         ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
230         if (ret < 0)
231                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
232 }
233
234 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
235 {
236         int ret;
237         u32 val;
238
239         /* if no pmu io supply we should leave things alone */
240         if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
241                 return;
242
243         /*
244          * set pmu io iodomain to also use this framework
245          * instead of a special gpio.
246          */
247         val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
248         ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
249         if (ret < 0)
250                 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
251 }
252
253 static const struct rockchip_iodomain_soc_data soc_data_px30 = {
254         .grf_offset = 0x180,
255         .supply_names = {
256                 NULL,
257                 "vccio6",
258                 "vccio1",
259                 "vccio2",
260                 "vccio3",
261                 "vccio4",
262                 "vccio5",
263                 "vccio-oscgpi",
264         },
265         .init = px30_iodomain_init,
266 };
267
268 static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
269         .grf_offset = 0x100,
270         .supply_names = {
271                 NULL,
272                 NULL,
273                 NULL,
274                 NULL,
275                 NULL,
276                 NULL,
277                 NULL,
278                 NULL,
279                 NULL,
280                 NULL,
281                 NULL,
282                 NULL,
283                 NULL,
284                 NULL,
285                 "pmuio1",
286                 "pmuio2",
287         },
288 };
289
290 /*
291  * On the rk3188 the io-domains are handled by a shared register with the
292  * lower 8 bits being still being continuing drive-strength settings.
293  */
294 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
295         .grf_offset = 0x104,
296         .supply_names = {
297                 NULL,
298                 NULL,
299                 NULL,
300                 NULL,
301                 NULL,
302                 NULL,
303                 NULL,
304                 NULL,
305                 "ap0",
306                 "ap1",
307                 "cif",
308                 "flash",
309                 "vccio0",
310                 "vccio1",
311                 "lcdc0",
312                 "lcdc1",
313         },
314 };
315
316 static const struct rockchip_iodomain_soc_data soc_data_rk3228 = {
317         .grf_offset = 0x418,
318         .supply_names = {
319                 "vccio1",
320                 "vccio2",
321                 "vccio3",
322                 "vccio4",
323         },
324 };
325
326 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
327         .grf_offset = 0x380,
328         .supply_names = {
329                 "lcdc",         /* LCDC_VDD */
330                 "dvp",          /* DVPIO_VDD */
331                 "flash0",       /* FLASH0_VDD (emmc) */
332                 "flash1",       /* FLASH1_VDD (sdio1) */
333                 "wifi",         /* APIO3_VDD  (sdio0) */
334                 "bb",           /* APIO5_VDD */
335                 "audio",        /* APIO4_VDD */
336                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
337                 "gpio30",       /* APIO1_VDD */
338                 "gpio1830",     /* APIO2_VDD */
339         },
340         .init = rk3288_iodomain_init,
341 };
342
343 static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
344         .grf_offset = 0x410,
345         .supply_names = {
346                 "vccio1",
347                 "vccio2",
348                 "vccio3",
349                 "vccio4",
350                 "vccio5",
351                 "vccio6",
352                 "pmuio",
353         },
354         .init = rk3328_iodomain_init,
355 };
356
357 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
358         .grf_offset = 0x900,
359         .supply_names = {
360                 NULL,           /* reserved */
361                 "dvp",          /* DVPIO_VDD */
362                 "flash0",       /* FLASH0_VDD (emmc) */
363                 "wifi",         /* APIO2_VDD (sdio0) */
364                 NULL,
365                 "audio",        /* APIO3_VDD */
366                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
367                 "gpio30",       /* APIO1_VDD */
368                 "gpio1830",     /* APIO4_VDD (gpujtag) */
369         },
370         .init = rk3368_iodomain_init,
371 };
372
373 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
374         .grf_offset = 0x100,
375         .supply_names = {
376                 NULL,
377                 NULL,
378                 NULL,
379                 NULL,
380                 "pmu",          /*PMU IO domain*/
381                 "vop",          /*LCDC IO domain*/
382         },
383 };
384
385 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
386         .grf_offset = 0xe640,
387         .supply_names = {
388                 "bt656",                /* APIO2_VDD */
389                 "audio",                /* APIO5_VDD */
390                 "sdmmc",                /* SDMMC0_VDD */
391                 "gpio1830",             /* APIO4_VDD */
392         },
393 };
394
395 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
396         .grf_offset = 0x180,
397         .supply_names = {
398                 NULL,
399                 NULL,
400                 NULL,
401                 NULL,
402                 NULL,
403                 NULL,
404                 NULL,
405                 NULL,
406                 NULL,
407                 "pmu1830",              /* PMUIO2_VDD */
408         },
409         .init = rk3399_pmu_iodomain_init,
410 };
411
412 static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
413         .grf_offset = 0x404,
414         .supply_names = {
415                 NULL,
416                 NULL,
417                 NULL,
418                 NULL,
419                 NULL,
420                 NULL,
421                 NULL,
422                 NULL,
423                 NULL,
424                 NULL,
425                 NULL,
426                 "vccio1",
427                 "vccio2",
428                 "vccio3",
429                 "vccio5",
430                 "vccio6",
431         },
432
433 };
434
435 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
436         .grf_offset = 0x104,
437         .supply_names = {
438                 "pmu",
439         },
440 };
441
442 static const struct of_device_id rockchip_iodomain_match[] = {
443         {
444                 .compatible = "rockchip,px30-io-voltage-domain",
445                 .data = (void *)&soc_data_px30
446         },
447         {
448                 .compatible = "rockchip,px30-pmu-io-voltage-domain",
449                 .data = (void *)&soc_data_px30_pmu
450         },
451         {
452                 .compatible = "rockchip,rk3188-io-voltage-domain",
453                 .data = &soc_data_rk3188
454         },
455         {
456                 .compatible = "rockchip,rk3228-io-voltage-domain",
457                 .data = &soc_data_rk3228
458         },
459         {
460                 .compatible = "rockchip,rk3288-io-voltage-domain",
461                 .data = &soc_data_rk3288
462         },
463         {
464                 .compatible = "rockchip,rk3328-io-voltage-domain",
465                 .data = &soc_data_rk3328
466         },
467         {
468                 .compatible = "rockchip,rk3368-io-voltage-domain",
469                 .data = &soc_data_rk3368
470         },
471         {
472                 .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
473                 .data = &soc_data_rk3368_pmu
474         },
475         {
476                 .compatible = "rockchip,rk3399-io-voltage-domain",
477                 .data = &soc_data_rk3399
478         },
479         {
480                 .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
481                 .data = &soc_data_rk3399_pmu
482         },
483         {
484                 .compatible = "rockchip,rv1108-io-voltage-domain",
485                 .data = &soc_data_rv1108
486         },
487         {
488                 .compatible = "rockchip,rv1108-pmu-io-voltage-domain",
489                 .data = &soc_data_rv1108_pmu
490         },
491         { /* sentinel */ },
492 };
493 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
494
495 static int rockchip_iodomain_probe(struct platform_device *pdev)
496 {
497         struct device_node *np = pdev->dev.of_node;
498         const struct of_device_id *match;
499         struct rockchip_iodomain *iod;
500         struct device *parent;
501         int i, ret = 0;
502
503         if (!np)
504                 return -ENODEV;
505
506         iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
507         if (!iod)
508                 return -ENOMEM;
509
510         iod->dev = &pdev->dev;
511         platform_set_drvdata(pdev, iod);
512
513         match = of_match_node(rockchip_iodomain_match, np);
514         iod->soc_data = match->data;
515
516         parent = pdev->dev.parent;
517         if (parent && parent->of_node) {
518                 iod->grf = syscon_node_to_regmap(parent->of_node);
519         } else {
520                 dev_dbg(&pdev->dev, "falling back to old binding\n");
521                 iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
522         }
523
524         if (IS_ERR(iod->grf)) {
525                 dev_err(&pdev->dev, "couldn't find grf regmap\n");
526                 return PTR_ERR(iod->grf);
527         }
528
529         for (i = 0; i < MAX_SUPPLIES; i++) {
530                 const char *supply_name = iod->soc_data->supply_names[i];
531                 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
532                 struct regulator *reg;
533                 int uV;
534
535                 if (!supply_name)
536                         continue;
537
538                 reg = devm_regulator_get_optional(iod->dev, supply_name);
539                 if (IS_ERR(reg)) {
540                         ret = PTR_ERR(reg);
541
542                         /* If a supply wasn't specified, that's OK */
543                         if (ret == -ENODEV)
544                                 continue;
545                         else if (ret != -EPROBE_DEFER)
546                                 dev_err(iod->dev, "couldn't get regulator %s\n",
547                                         supply_name);
548                         goto unreg_notify;
549                 }
550
551                 /* set initial correct value */
552                 uV = regulator_get_voltage(reg);
553
554                 /* must be a regulator we can get the voltage of */
555                 if (uV < 0) {
556                         dev_err(iod->dev, "Can't determine voltage: %s\n",
557                                 supply_name);
558                         goto unreg_notify;
559                 }
560
561                 if (uV > MAX_VOLTAGE_3_3) {
562                         dev_crit(iod->dev,
563                                  "%d uV is too high. May damage SoC!\n",
564                                  uV);
565                         ret = -EINVAL;
566                         goto unreg_notify;
567                 }
568
569                 /* setup our supply */
570                 supply->idx = i;
571                 supply->iod = iod;
572                 supply->reg = reg;
573                 supply->nb.notifier_call = rockchip_iodomain_notify;
574
575                 ret = rockchip_iodomain_write(supply, uV);
576                 if (ret) {
577                         supply->reg = NULL;
578                         goto unreg_notify;
579                 }
580
581                 /* register regulator notifier */
582                 ret = regulator_register_notifier(reg, &supply->nb);
583                 if (ret) {
584                         dev_err(&pdev->dev,
585                                 "regulator notifier request failed\n");
586                         supply->reg = NULL;
587                         goto unreg_notify;
588                 }
589         }
590
591         if (iod->soc_data->init)
592                 iod->soc_data->init(iod);
593
594         return 0;
595
596 unreg_notify:
597         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
598                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
599
600                 if (io_supply->reg)
601                         regulator_unregister_notifier(io_supply->reg,
602                                                       &io_supply->nb);
603         }
604
605         return ret;
606 }
607
608 static int rockchip_iodomain_remove(struct platform_device *pdev)
609 {
610         struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
611         int i;
612
613         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
614                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
615
616                 if (io_supply->reg)
617                         regulator_unregister_notifier(io_supply->reg,
618                                                       &io_supply->nb);
619         }
620
621         return 0;
622 }
623
624 static struct platform_driver rockchip_iodomain_driver = {
625         .probe   = rockchip_iodomain_probe,
626         .remove  = rockchip_iodomain_remove,
627         .driver  = {
628                 .name  = "rockchip-iodomain",
629                 .of_match_table = rockchip_iodomain_match,
630         },
631 };
632
633 module_platform_driver(rockchip_iodomain_driver);
634
635 MODULE_DESCRIPTION("Rockchip IO-domain driver");
636 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
637 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
638 MODULE_LICENSE("GPL v2");