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