1 // SPDX-License-Identifier: GPL-2.0+
2 
3 /*
4  * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
5  */
6 
7 #include <linux/device.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_domain.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <linux/clk.h>
15 
16 #include <dt-bindings/power/imx8mm-power.h>
17 
18 #define BLK_SFT_RSTN	0x0
19 #define BLK_CLK_EN	0x4
20 #define BLK_MIPI_RESET_DIV	0x8 /* Mini/Nano DISPLAY_BLK_CTRL only */
21 
22 struct imx8m_blk_ctrl_domain;
23 
24 struct imx8m_blk_ctrl {
25 	struct device *dev;
26 	struct notifier_block power_nb;
27 	struct device *bus_power_dev;
28 	struct regmap *regmap;
29 	struct imx8m_blk_ctrl_domain *domains;
30 	struct genpd_onecell_data onecell_data;
31 };
32 
33 struct imx8m_blk_ctrl_domain_data {
34 	const char *name;
35 	const char * const *clk_names;
36 	int num_clks;
37 	const char *gpc_name;
38 	u32 rst_mask;
39 	u32 clk_mask;
40 
41 	/*
42 	 * i.MX8M Mini and Nano have a third DISPLAY_BLK_CTRL register
43 	 * which is used to control the reset for the MIPI Phy.
44 	 * Since it's only present in certain circumstances,
45 	 * an if-statement should be used before setting and clearing this
46 	 * register.
47 	 */
48 	u32 mipi_phy_rst_mask;
49 };
50 
51 #define DOMAIN_MAX_CLKS 3
52 
53 struct imx8m_blk_ctrl_domain {
54 	struct generic_pm_domain genpd;
55 	const struct imx8m_blk_ctrl_domain_data *data;
56 	struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
57 	struct device *power_dev;
58 	struct imx8m_blk_ctrl *bc;
59 };
60 
61 struct imx8m_blk_ctrl_data {
62 	int max_reg;
63 	notifier_fn_t power_notifier_fn;
64 	const struct imx8m_blk_ctrl_domain_data *domains;
65 	int num_domains;
66 };
67 
68 static inline struct imx8m_blk_ctrl_domain *
to_imx8m_blk_ctrl_domain(struct generic_pm_domain * genpd)69 to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
70 {
71 	return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
72 }
73 
imx8m_blk_ctrl_power_on(struct generic_pm_domain * genpd)74 static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
75 {
76 	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
77 	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
78 	struct imx8m_blk_ctrl *bc = domain->bc;
79 	int ret;
80 
81 	/* make sure bus domain is awake */
82 	ret = pm_runtime_get_sync(bc->bus_power_dev);
83 	if (ret < 0) {
84 		pm_runtime_put_noidle(bc->bus_power_dev);
85 		dev_err(bc->dev, "failed to power up bus domain\n");
86 		return ret;
87 	}
88 
89 	/* put devices into reset */
90 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
91 	if (data->mipi_phy_rst_mask)
92 		regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
93 
94 	/* enable upstream and blk-ctrl clocks to allow reset to propagate */
95 	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
96 	if (ret) {
97 		dev_err(bc->dev, "failed to enable clocks\n");
98 		goto bus_put;
99 	}
100 	regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
101 
102 	/* power up upstream GPC domain */
103 	ret = pm_runtime_get_sync(domain->power_dev);
104 	if (ret < 0) {
105 		dev_err(bc->dev, "failed to power up peripheral domain\n");
106 		goto clk_disable;
107 	}
108 
109 	/* wait for reset to propagate */
110 	udelay(5);
111 
112 	/* release reset */
113 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
114 	if (data->mipi_phy_rst_mask)
115 		regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
116 
117 	/* disable upstream clocks */
118 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
119 
120 	return 0;
121 
122 clk_disable:
123 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
124 bus_put:
125 	pm_runtime_put(bc->bus_power_dev);
126 
127 	return ret;
128 }
129 
imx8m_blk_ctrl_power_off(struct generic_pm_domain * genpd)130 static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
131 {
132 	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
133 	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
134 	struct imx8m_blk_ctrl *bc = domain->bc;
135 
136 	/* put devices into reset and disable clocks */
137 	if (data->mipi_phy_rst_mask)
138 		regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
139 
140 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
141 	regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
142 
143 	/* power down upstream GPC domain */
144 	pm_runtime_put(domain->power_dev);
145 
146 	/* allow bus domain to suspend */
147 	pm_runtime_put(bc->bus_power_dev);
148 
149 	return 0;
150 }
151 
152 static struct generic_pm_domain *
imx8m_blk_ctrl_xlate(struct of_phandle_args * args,void * data)153 imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
154 {
155 	struct genpd_onecell_data *onecell_data = data;
156 	unsigned int index = args->args[0];
157 
158 	if (args->args_count != 1 ||
159 	    index >= onecell_data->num_domains)
160 		return ERR_PTR(-EINVAL);
161 
162 	return onecell_data->domains[index];
163 }
164 
165 static struct lock_class_key blk_ctrl_genpd_lock_class;
166 
imx8m_blk_ctrl_probe(struct platform_device * pdev)167 static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
168 {
169 	const struct imx8m_blk_ctrl_data *bc_data;
170 	struct device *dev = &pdev->dev;
171 	struct imx8m_blk_ctrl *bc;
172 	void __iomem *base;
173 	int i, ret;
174 
175 	struct regmap_config regmap_config = {
176 		.reg_bits	= 32,
177 		.val_bits	= 32,
178 		.reg_stride	= 4,
179 	};
180 
181 	bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
182 	if (!bc)
183 		return -ENOMEM;
184 
185 	bc->dev = dev;
186 
187 	bc_data = of_device_get_match_data(dev);
188 
189 	base = devm_platform_ioremap_resource(pdev, 0);
190 	if (IS_ERR(base))
191 		return PTR_ERR(base);
192 
193 	regmap_config.max_register = bc_data->max_reg;
194 	bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
195 	if (IS_ERR(bc->regmap))
196 		return dev_err_probe(dev, PTR_ERR(bc->regmap),
197 				     "failed to init regmap\n");
198 
199 	bc->domains = devm_kcalloc(dev, bc_data->num_domains,
200 				   sizeof(struct imx8m_blk_ctrl_domain),
201 				   GFP_KERNEL);
202 	if (!bc->domains)
203 		return -ENOMEM;
204 
205 	bc->onecell_data.num_domains = bc_data->num_domains;
206 	bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
207 	bc->onecell_data.domains =
208 		devm_kcalloc(dev, bc_data->num_domains,
209 			     sizeof(struct generic_pm_domain *), GFP_KERNEL);
210 	if (!bc->onecell_data.domains)
211 		return -ENOMEM;
212 
213 	bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
214 	if (IS_ERR(bc->bus_power_dev))
215 		return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
216 				     "failed to attach power domain\n");
217 
218 	for (i = 0; i < bc_data->num_domains; i++) {
219 		const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
220 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
221 		int j;
222 
223 		domain->data = data;
224 
225 		for (j = 0; j < data->num_clks; j++)
226 			domain->clks[j].id = data->clk_names[j];
227 
228 		ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
229 		if (ret) {
230 			dev_err_probe(dev, ret, "failed to get clock\n");
231 			goto cleanup_pds;
232 		}
233 
234 		domain->power_dev =
235 			dev_pm_domain_attach_by_name(dev, data->gpc_name);
236 		if (IS_ERR(domain->power_dev)) {
237 			dev_err_probe(dev, PTR_ERR(domain->power_dev),
238 				      "failed to attach power domain\n");
239 			ret = PTR_ERR(domain->power_dev);
240 			goto cleanup_pds;
241 		}
242 
243 		domain->genpd.name = data->name;
244 		domain->genpd.power_on = imx8m_blk_ctrl_power_on;
245 		domain->genpd.power_off = imx8m_blk_ctrl_power_off;
246 		domain->bc = bc;
247 
248 		ret = pm_genpd_init(&domain->genpd, NULL, true);
249 		if (ret) {
250 			dev_err_probe(dev, ret, "failed to init power domain\n");
251 			dev_pm_domain_detach(domain->power_dev, true);
252 			goto cleanup_pds;
253 		}
254 
255 		/*
256 		 * We use runtime PM to trigger power on/off of the upstream GPC
257 		 * domain, as a strict hierarchical parent/child power domain
258 		 * setup doesn't allow us to meet the sequencing requirements.
259 		 * This means we have nested locking of genpd locks, without the
260 		 * nesting being visible at the genpd level, so we need a
261 		 * separate lock class to make lockdep aware of the fact that
262 		 * this are separate domain locks that can be nested without a
263 		 * self-deadlock.
264 		 */
265 		lockdep_set_class(&domain->genpd.mlock,
266 				  &blk_ctrl_genpd_lock_class);
267 
268 		bc->onecell_data.domains[i] = &domain->genpd;
269 	}
270 
271 	ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
272 	if (ret) {
273 		dev_err_probe(dev, ret, "failed to add power domain provider\n");
274 		goto cleanup_pds;
275 	}
276 
277 	bc->power_nb.notifier_call = bc_data->power_notifier_fn;
278 	ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
279 	if (ret) {
280 		dev_err_probe(dev, ret, "failed to add power notifier\n");
281 		goto cleanup_provider;
282 	}
283 
284 	dev_set_drvdata(dev, bc);
285 
286 	return 0;
287 
288 cleanup_provider:
289 	of_genpd_del_provider(dev->of_node);
290 cleanup_pds:
291 	for (i--; i >= 0; i--) {
292 		pm_genpd_remove(&bc->domains[i].genpd);
293 		dev_pm_domain_detach(bc->domains[i].power_dev, true);
294 	}
295 
296 	dev_pm_domain_detach(bc->bus_power_dev, true);
297 
298 	return ret;
299 }
300 
imx8m_blk_ctrl_remove(struct platform_device * pdev)301 static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
302 {
303 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
304 	int i;
305 
306 	of_genpd_del_provider(pdev->dev.of_node);
307 
308 	for (i = 0; bc->onecell_data.num_domains; i++) {
309 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
310 
311 		pm_genpd_remove(&domain->genpd);
312 		dev_pm_domain_detach(domain->power_dev, true);
313 	}
314 
315 	dev_pm_genpd_remove_notifier(bc->bus_power_dev);
316 
317 	dev_pm_domain_detach(bc->bus_power_dev, true);
318 
319 	return 0;
320 }
321 
322 #ifdef CONFIG_PM_SLEEP
imx8m_blk_ctrl_suspend(struct device * dev)323 static int imx8m_blk_ctrl_suspend(struct device *dev)
324 {
325 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
326 	int ret, i;
327 
328 	/*
329 	 * This may look strange, but is done so the generic PM_SLEEP code
330 	 * can power down our domains and more importantly power them up again
331 	 * after resume, without tripping over our usage of runtime PM to
332 	 * control the upstream GPC domains. Things happen in the right order
333 	 * in the system suspend/resume paths due to the device parent/child
334 	 * hierarchy.
335 	 */
336 	ret = pm_runtime_get_sync(bc->bus_power_dev);
337 	if (ret < 0) {
338 		pm_runtime_put_noidle(bc->bus_power_dev);
339 		return ret;
340 	}
341 
342 	for (i = 0; i < bc->onecell_data.num_domains; i++) {
343 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
344 
345 		ret = pm_runtime_get_sync(domain->power_dev);
346 		if (ret < 0) {
347 			pm_runtime_put_noidle(domain->power_dev);
348 			goto out_fail;
349 		}
350 	}
351 
352 	return 0;
353 
354 out_fail:
355 	for (i--; i >= 0; i--)
356 		pm_runtime_put(bc->domains[i].power_dev);
357 
358 	pm_runtime_put(bc->bus_power_dev);
359 
360 	return ret;
361 }
362 
imx8m_blk_ctrl_resume(struct device * dev)363 static int imx8m_blk_ctrl_resume(struct device *dev)
364 {
365 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
366 	int i;
367 
368 	for (i = 0; i < bc->onecell_data.num_domains; i++)
369 		pm_runtime_put(bc->domains[i].power_dev);
370 
371 	pm_runtime_put(bc->bus_power_dev);
372 
373 	return 0;
374 }
375 #endif
376 
377 static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
378 	SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
379 };
380 
imx8mm_vpu_power_notifier(struct notifier_block * nb,unsigned long action,void * data)381 static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
382 				     unsigned long action, void *data)
383 {
384 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
385 						 power_nb);
386 
387 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
388 		return NOTIFY_OK;
389 
390 	/*
391 	 * The ADB in the VPUMIX domain has no separate reset and clock
392 	 * enable bits, but is ungated together with the VPU clocks. To
393 	 * allow the handshake with the GPC to progress we put the VPUs
394 	 * in reset and ungate the clocks.
395 	 */
396 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
397 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
398 
399 	if (action == GENPD_NOTIFY_ON) {
400 		/*
401 		 * On power up we have no software backchannel to the GPC to
402 		 * wait for the ADB handshake to happen, so we just delay for a
403 		 * bit. On power down the GPC driver waits for the handshake.
404 		 */
405 		udelay(5);
406 
407 		/* set "fuse" bits to enable the VPUs */
408 		regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
409 		regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
410 		regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
411 		regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
412 	}
413 
414 	return NOTIFY_OK;
415 }
416 
417 static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
418 	[IMX8MM_VPUBLK_PD_G1] = {
419 		.name = "vpublk-g1",
420 		.clk_names = (const char *[]){ "g1", },
421 		.num_clks = 1,
422 		.gpc_name = "g1",
423 		.rst_mask = BIT(1),
424 		.clk_mask = BIT(1),
425 	},
426 	[IMX8MM_VPUBLK_PD_G2] = {
427 		.name = "vpublk-g2",
428 		.clk_names = (const char *[]){ "g2", },
429 		.num_clks = 1,
430 		.gpc_name = "g2",
431 		.rst_mask = BIT(0),
432 		.clk_mask = BIT(0),
433 	},
434 	[IMX8MM_VPUBLK_PD_H1] = {
435 		.name = "vpublk-h1",
436 		.clk_names = (const char *[]){ "h1", },
437 		.num_clks = 1,
438 		.gpc_name = "h1",
439 		.rst_mask = BIT(2),
440 		.clk_mask = BIT(2),
441 	},
442 };
443 
444 static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
445 	.max_reg = 0x18,
446 	.power_notifier_fn = imx8mm_vpu_power_notifier,
447 	.domains = imx8mm_vpu_blk_ctl_domain_data,
448 	.num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
449 };
450 
imx8mm_disp_power_notifier(struct notifier_block * nb,unsigned long action,void * data)451 static int imx8mm_disp_power_notifier(struct notifier_block *nb,
452 				      unsigned long action, void *data)
453 {
454 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
455 						 power_nb);
456 
457 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
458 		return NOTIFY_OK;
459 
460 	/* Enable bus clock and deassert bus reset */
461 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
462 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
463 
464 	/*
465 	 * On power up we have no software backchannel to the GPC to
466 	 * wait for the ADB handshake to happen, so we just delay for a
467 	 * bit. On power down the GPC driver waits for the handshake.
468 	 */
469 	if (action == GENPD_NOTIFY_ON)
470 		udelay(5);
471 
472 
473 	return NOTIFY_OK;
474 }
475 
476 static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
477 	[IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
478 		.name = "dispblk-csi-bridge",
479 		.clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
480 					       "csi-bridge-core", },
481 		.num_clks = 3,
482 		.gpc_name = "csi-bridge",
483 		.rst_mask = BIT(0) | BIT(1) | BIT(2),
484 		.clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
485 	},
486 	[IMX8MM_DISPBLK_PD_LCDIF] = {
487 		.name = "dispblk-lcdif",
488 		.clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
489 		.num_clks = 3,
490 		.gpc_name = "lcdif",
491 		.clk_mask = BIT(6) | BIT(7),
492 	},
493 	[IMX8MM_DISPBLK_PD_MIPI_DSI] = {
494 		.name = "dispblk-mipi-dsi",
495 		.clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
496 		.num_clks = 2,
497 		.gpc_name = "mipi-dsi",
498 		.rst_mask = BIT(5),
499 		.clk_mask = BIT(8) | BIT(9),
500 		.mipi_phy_rst_mask = BIT(17),
501 	},
502 	[IMX8MM_DISPBLK_PD_MIPI_CSI] = {
503 		.name = "dispblk-mipi-csi",
504 		.clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
505 		.num_clks = 2,
506 		.gpc_name = "mipi-csi",
507 		.rst_mask = BIT(3) | BIT(4),
508 		.clk_mask = BIT(10) | BIT(11),
509 		.mipi_phy_rst_mask = BIT(16),
510 	},
511 };
512 
513 static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
514 	.max_reg = 0x2c,
515 	.power_notifier_fn = imx8mm_disp_power_notifier,
516 	.domains = imx8mm_disp_blk_ctl_domain_data,
517 	.num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
518 };
519 
520 static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
521 	{
522 		.compatible = "fsl,imx8mm-vpu-blk-ctrl",
523 		.data = &imx8mm_vpu_blk_ctl_dev_data
524 	}, {
525 		.compatible = "fsl,imx8mm-disp-blk-ctrl",
526 		.data = &imx8mm_disp_blk_ctl_dev_data
527 	} ,{
528 		/* Sentinel */
529 	}
530 };
531 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
532 
533 static struct platform_driver imx8m_blk_ctrl_driver = {
534 	.probe = imx8m_blk_ctrl_probe,
535 	.remove = imx8m_blk_ctrl_remove,
536 	.driver = {
537 		.name = "imx8m-blk-ctrl",
538 		.pm = &imx8m_blk_ctrl_pm_ops,
539 		.of_match_table = imx8m_blk_ctrl_of_match,
540 	},
541 };
542 module_platform_driver(imx8m_blk_ctrl_driver);
543