• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 	struct rockchip_iodomain_soc_data *soc_data;
76 	struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
77 };
78 
rockchip_iodomain_write(struct rockchip_iodomain_supply * supply,int uV)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 
rockchip_iodomain_notify(struct notifier_block * nb,unsigned long event,void * data)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_info(supply->iod->dev, "Setting to %d done\n", uV);
147 	return NOTIFY_OK;
148 }
149 
rk3288_iodomain_init(struct rockchip_iodomain * iod)150 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
151 {
152 	int ret;
153 	u32 val;
154 
155 	/* if no flash supply we should leave things alone */
156 	if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
157 		return;
158 
159 	/*
160 	 * set flash0 iodomain to also use this framework
161 	 * instead of a special gpio.
162 	 */
163 	val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
164 	ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
165 	if (ret < 0)
166 		dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
167 }
168 
rk3368_iodomain_init(struct rockchip_iodomain * iod)169 static void rk3368_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[RK3368_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 = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
183 	ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
184 	if (ret < 0)
185 		dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
186 }
187 
rk3399_pmu_iodomain_init(struct rockchip_iodomain * iod)188 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
189 {
190 	int ret;
191 	u32 val;
192 
193 	/* if no pmu io supply we should leave things alone */
194 	if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
195 		return;
196 
197 	/*
198 	 * set pmu io iodomain to also use this framework
199 	 * instead of a special gpio.
200 	 */
201 	val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
202 	ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
203 	if (ret < 0)
204 		dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
205 }
206 
207 /*
208  * On the rk3188 the io-domains are handled by a shared register with the
209  * lower 8 bits being still being continuing drive-strength settings.
210  */
211 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
212 	.grf_offset = 0x104,
213 	.supply_names = {
214 		NULL,
215 		NULL,
216 		NULL,
217 		NULL,
218 		NULL,
219 		NULL,
220 		NULL,
221 		NULL,
222 		"ap0",
223 		"ap1",
224 		"cif",
225 		"flash",
226 		"vccio0",
227 		"vccio1",
228 		"lcdc0",
229 		"lcdc1",
230 	},
231 };
232 
233 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
234 	.grf_offset = 0x380,
235 	.supply_names = {
236 		"lcdc",		/* LCDC_VDD */
237 		"dvp",		/* DVPIO_VDD */
238 		"flash0",	/* FLASH0_VDD (emmc) */
239 		"flash1",	/* FLASH1_VDD (sdio1) */
240 		"wifi",		/* APIO3_VDD  (sdio0) */
241 		"bb",		/* APIO5_VDD */
242 		"audio",	/* APIO4_VDD */
243 		"sdcard",	/* SDMMC0_VDD (sdmmc) */
244 		"gpio30",	/* APIO1_VDD */
245 		"gpio1830",	/* APIO2_VDD */
246 	},
247 	.init = rk3288_iodomain_init,
248 };
249 
250 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
251 	.grf_offset = 0x900,
252 	.supply_names = {
253 		NULL,		/* reserved */
254 		"dvp",		/* DVPIO_VDD */
255 		"flash0",	/* FLASH0_VDD (emmc) */
256 		"wifi",		/* APIO2_VDD (sdio0) */
257 		NULL,
258 		"audio",	/* APIO3_VDD */
259 		"sdcard",	/* SDMMC0_VDD (sdmmc) */
260 		"gpio30",	/* APIO1_VDD */
261 		"gpio1830",	/* APIO4_VDD (gpujtag) */
262 	},
263 	.init = rk3368_iodomain_init,
264 };
265 
266 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
267 	.grf_offset = 0x100,
268 	.supply_names = {
269 		NULL,
270 		NULL,
271 		NULL,
272 		NULL,
273 		"pmu",	        /*PMU IO domain*/
274 		"vop",	        /*LCDC IO domain*/
275 	},
276 };
277 
278 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
279 	.grf_offset = 0xe640,
280 	.supply_names = {
281 		"bt656",		/* APIO2_VDD */
282 		"audio",		/* APIO5_VDD */
283 		"sdmmc",		/* SDMMC0_VDD */
284 		"gpio1830",		/* APIO4_VDD */
285 	},
286 };
287 
288 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
289 	.grf_offset = 0x180,
290 	.supply_names = {
291 		NULL,
292 		NULL,
293 		NULL,
294 		NULL,
295 		NULL,
296 		NULL,
297 		NULL,
298 		NULL,
299 		NULL,
300 		"pmu1830",		/* PMUIO2_VDD */
301 	},
302 	.init = rk3399_pmu_iodomain_init,
303 };
304 
305 static const struct of_device_id rockchip_iodomain_match[] = {
306 	{
307 		.compatible = "rockchip,rk3188-io-voltage-domain",
308 		.data = (void *)&soc_data_rk3188
309 	},
310 	{
311 		.compatible = "rockchip,rk3288-io-voltage-domain",
312 		.data = (void *)&soc_data_rk3288
313 	},
314 	{
315 		.compatible = "rockchip,rk3368-io-voltage-domain",
316 		.data = (void *)&soc_data_rk3368
317 	},
318 	{
319 		.compatible = "rockchip,rk3368-pmu-io-voltage-domain",
320 		.data = (void *)&soc_data_rk3368_pmu
321 	},
322 	{
323 		.compatible = "rockchip,rk3399-io-voltage-domain",
324 		.data = (void *)&soc_data_rk3399
325 	},
326 	{
327 		.compatible = "rockchip,rk3399-pmu-io-voltage-domain",
328 		.data = (void *)&soc_data_rk3399_pmu
329 	},
330 	{ /* sentinel */ },
331 };
332 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
333 
rockchip_iodomain_probe(struct platform_device * pdev)334 static int rockchip_iodomain_probe(struct platform_device *pdev)
335 {
336 	struct device_node *np = pdev->dev.of_node;
337 	const struct of_device_id *match;
338 	struct rockchip_iodomain *iod;
339 	struct device *parent;
340 	int i, ret = 0;
341 
342 	if (!np)
343 		return -ENODEV;
344 
345 	iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
346 	if (!iod)
347 		return -ENOMEM;
348 
349 	iod->dev = &pdev->dev;
350 	platform_set_drvdata(pdev, iod);
351 
352 	match = of_match_node(rockchip_iodomain_match, np);
353 	iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data;
354 
355 	parent = pdev->dev.parent;
356 	if (parent && parent->of_node) {
357 		iod->grf = syscon_node_to_regmap(parent->of_node);
358 	} else {
359 		dev_dbg(&pdev->dev, "falling back to old binding\n");
360 		iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
361 	}
362 
363 	if (IS_ERR(iod->grf)) {
364 		dev_err(&pdev->dev, "couldn't find grf regmap\n");
365 		return PTR_ERR(iod->grf);
366 	}
367 
368 	for (i = 0; i < MAX_SUPPLIES; i++) {
369 		const char *supply_name = iod->soc_data->supply_names[i];
370 		struct rockchip_iodomain_supply *supply = &iod->supplies[i];
371 		struct regulator *reg;
372 		int uV;
373 
374 		if (!supply_name)
375 			continue;
376 
377 		reg = devm_regulator_get_optional(iod->dev, supply_name);
378 		if (IS_ERR(reg)) {
379 			ret = PTR_ERR(reg);
380 
381 			/* If a supply wasn't specified, that's OK */
382 			if (ret == -ENODEV)
383 				continue;
384 			else if (ret != -EPROBE_DEFER)
385 				dev_err(iod->dev, "couldn't get regulator %s\n",
386 					supply_name);
387 			goto unreg_notify;
388 		}
389 
390 		/* set initial correct value */
391 		uV = regulator_get_voltage(reg);
392 
393 		/* must be a regulator we can get the voltage of */
394 		if (uV < 0) {
395 			dev_err(iod->dev, "Can't determine voltage: %s\n",
396 				supply_name);
397 			goto unreg_notify;
398 		}
399 
400 		if (uV > MAX_VOLTAGE_3_3) {
401 			dev_crit(iod->dev,
402 				 "%d uV is too high. May damage SoC!\n",
403 				 uV);
404 			ret = -EINVAL;
405 			goto unreg_notify;
406 		}
407 
408 		/* setup our supply */
409 		supply->idx = i;
410 		supply->iod = iod;
411 		supply->reg = reg;
412 		supply->nb.notifier_call = rockchip_iodomain_notify;
413 
414 		ret = rockchip_iodomain_write(supply, uV);
415 		if (ret) {
416 			supply->reg = NULL;
417 			goto unreg_notify;
418 		}
419 
420 		/* register regulator notifier */
421 		ret = regulator_register_notifier(reg, &supply->nb);
422 		if (ret) {
423 			dev_err(&pdev->dev,
424 				"regulator notifier request failed\n");
425 			supply->reg = NULL;
426 			goto unreg_notify;
427 		}
428 	}
429 
430 	if (iod->soc_data->init)
431 		iod->soc_data->init(iod);
432 
433 	return 0;
434 
435 unreg_notify:
436 	for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
437 		struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
438 
439 		if (io_supply->reg)
440 			regulator_unregister_notifier(io_supply->reg,
441 						      &io_supply->nb);
442 	}
443 
444 	return ret;
445 }
446 
rockchip_iodomain_remove(struct platform_device * pdev)447 static int rockchip_iodomain_remove(struct platform_device *pdev)
448 {
449 	struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
450 	int i;
451 
452 	for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
453 		struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
454 
455 		if (io_supply->reg)
456 			regulator_unregister_notifier(io_supply->reg,
457 						      &io_supply->nb);
458 	}
459 
460 	return 0;
461 }
462 
463 static struct platform_driver rockchip_iodomain_driver = {
464 	.probe   = rockchip_iodomain_probe,
465 	.remove  = rockchip_iodomain_remove,
466 	.driver  = {
467 		.name  = "rockchip-iodomain",
468 		.of_match_table = rockchip_iodomain_match,
469 	},
470 };
471 
472 module_platform_driver(rockchip_iodomain_driver);
473 
474 MODULE_DESCRIPTION("Rockchip IO-domain driver");
475 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
476 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
477 MODULE_LICENSE("GPL v2");
478