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