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
rockchip_iodomain_write(struct rockchip_iodomain_supply * supply,int uV)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
rockchip_iodomain_notify(struct notifier_block * nb,unsigned long event,void * data)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
px30_iodomain_init(struct rockchip_iodomain * iod)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
rk3288_iodomain_init(struct rockchip_iodomain * iod)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
rk3328_iodomain_init(struct rockchip_iodomain * iod)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
rk3368_iodomain_init(struct rockchip_iodomain * iod)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
rk3399_pmu_iodomain_init(struct rockchip_iodomain * iod)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
rockchip_iodomain_probe(struct platform_device * pdev)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
rockchip_iodomain_remove(struct platform_device * pdev)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");
639