1 // SPDX-License-Identifier: GPL-2.0+
2 
3 /*
4  * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/device.h>
9 #include <linux/interconnect.h>
10 #include <linux/module.h>
11 #include <linux/of_device.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_domain.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <linux/clk.h>
17 
18 #include <dt-bindings/power/imx8mm-power.h>
19 #include <dt-bindings/power/imx8mn-power.h>
20 #include <dt-bindings/power/imx8mp-power.h>
21 #include <dt-bindings/power/imx8mq-power.h>
22 
23 #define BLK_SFT_RSTN	0x0
24 #define BLK_CLK_EN	0x4
25 #define BLK_MIPI_RESET_DIV	0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
26 
27 struct imx8m_blk_ctrl_domain;
28 
29 struct imx8m_blk_ctrl {
30 	struct device *dev;
31 	struct notifier_block power_nb;
32 	struct device *bus_power_dev;
33 	struct regmap *regmap;
34 	struct imx8m_blk_ctrl_domain *domains;
35 	struct genpd_onecell_data onecell_data;
36 };
37 
38 struct imx8m_blk_ctrl_domain_data {
39 	const char *name;
40 	const char * const *clk_names;
41 	int num_clks;
42 	const char * const *path_names;
43 	int num_paths;
44 	const char *gpc_name;
45 	u32 rst_mask;
46 	u32 clk_mask;
47 
48 	/*
49 	 * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
50 	 * which is used to control the reset for the MIPI Phy.
51 	 * Since it's only present in certain circumstances,
52 	 * an if-statement should be used before setting and clearing this
53 	 * register.
54 	 */
55 	u32 mipi_phy_rst_mask;
56 };
57 
58 #define DOMAIN_MAX_CLKS 4
59 #define DOMAIN_MAX_PATHS 4
60 
61 struct imx8m_blk_ctrl_domain {
62 	struct generic_pm_domain genpd;
63 	const struct imx8m_blk_ctrl_domain_data *data;
64 	struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
65 	struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
66 	struct device *power_dev;
67 	struct imx8m_blk_ctrl *bc;
68 	int num_paths;
69 };
70 
71 struct imx8m_blk_ctrl_data {
72 	int max_reg;
73 	notifier_fn_t power_notifier_fn;
74 	const struct imx8m_blk_ctrl_domain_data *domains;
75 	int num_domains;
76 };
77 
78 static inline struct imx8m_blk_ctrl_domain *
to_imx8m_blk_ctrl_domain(struct generic_pm_domain * genpd)79 to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
80 {
81 	return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
82 }
83 
imx8m_blk_ctrl_power_on(struct generic_pm_domain * genpd)84 static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
85 {
86 	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
87 	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
88 	struct imx8m_blk_ctrl *bc = domain->bc;
89 	int ret;
90 
91 	/* make sure bus domain is awake */
92 	ret = pm_runtime_get_sync(bc->bus_power_dev);
93 	if (ret < 0) {
94 		pm_runtime_put_noidle(bc->bus_power_dev);
95 		dev_err(bc->dev, "failed to power up bus domain\n");
96 		return ret;
97 	}
98 
99 	/* put devices into reset */
100 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
101 	if (data->mipi_phy_rst_mask)
102 		regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
103 
104 	/* enable upstream and blk-ctrl clocks to allow reset to propagate */
105 	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
106 	if (ret) {
107 		dev_err(bc->dev, "failed to enable clocks\n");
108 		goto bus_put;
109 	}
110 	regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
111 
112 	/* power up upstream GPC domain */
113 	ret = pm_runtime_get_sync(domain->power_dev);
114 	if (ret < 0) {
115 		dev_err(bc->dev, "failed to power up peripheral domain\n");
116 		goto clk_disable;
117 	}
118 
119 	/* wait for reset to propagate */
120 	udelay(5);
121 
122 	/* release reset */
123 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
124 	if (data->mipi_phy_rst_mask)
125 		regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
126 
127 	ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
128 	if (ret)
129 		dev_err(bc->dev, "failed to set icc bw\n");
130 
131 	/* disable upstream clocks */
132 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
133 
134 	return 0;
135 
136 clk_disable:
137 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
138 bus_put:
139 	pm_runtime_put(bc->bus_power_dev);
140 
141 	return ret;
142 }
143 
imx8m_blk_ctrl_power_off(struct generic_pm_domain * genpd)144 static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
145 {
146 	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
147 	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
148 	struct imx8m_blk_ctrl *bc = domain->bc;
149 
150 	/* put devices into reset and disable clocks */
151 	if (data->mipi_phy_rst_mask)
152 		regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
153 
154 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
155 	regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
156 
157 	/* power down upstream GPC domain */
158 	pm_runtime_put(domain->power_dev);
159 
160 	/* allow bus domain to suspend */
161 	pm_runtime_put(bc->bus_power_dev);
162 
163 	return 0;
164 }
165 
166 static struct lock_class_key blk_ctrl_genpd_lock_class;
167 
imx8m_blk_ctrl_probe(struct platform_device * pdev)168 static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
169 {
170 	const struct imx8m_blk_ctrl_data *bc_data;
171 	struct device *dev = &pdev->dev;
172 	struct imx8m_blk_ctrl *bc;
173 	void __iomem *base;
174 	int i, ret;
175 
176 	struct regmap_config regmap_config = {
177 		.reg_bits	= 32,
178 		.val_bits	= 32,
179 		.reg_stride	= 4,
180 	};
181 
182 	bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
183 	if (!bc)
184 		return -ENOMEM;
185 
186 	bc->dev = dev;
187 
188 	bc_data = of_device_get_match_data(dev);
189 
190 	base = devm_platform_ioremap_resource(pdev, 0);
191 	if (IS_ERR(base))
192 		return PTR_ERR(base);
193 
194 	regmap_config.max_register = bc_data->max_reg;
195 	bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
196 	if (IS_ERR(bc->regmap))
197 		return dev_err_probe(dev, PTR_ERR(bc->regmap),
198 				     "failed to init regmap\n");
199 
200 	bc->domains = devm_kcalloc(dev, bc_data->num_domains,
201 				   sizeof(struct imx8m_blk_ctrl_domain),
202 				   GFP_KERNEL);
203 	if (!bc->domains)
204 		return -ENOMEM;
205 
206 	bc->onecell_data.num_domains = bc_data->num_domains;
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 		if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
216 			return dev_err_probe(dev, -EPROBE_DEFER,
217 					     "failed to attach power domain \"bus\"\n");
218 		else
219 			return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
220 					     "failed to attach power domain \"bus\"\n");
221 	}
222 
223 	for (i = 0; i < bc_data->num_domains; i++) {
224 		const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
225 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
226 		int j;
227 
228 		domain->data = data;
229 		domain->num_paths = data->num_paths;
230 
231 		for (j = 0; j < data->num_clks; j++)
232 			domain->clks[j].id = data->clk_names[j];
233 
234 		for (j = 0; j < data->num_paths; j++) {
235 			domain->paths[j].name = data->path_names[j];
236 			/* Fake value for now, just let ICC could configure NoC mode/priority */
237 			domain->paths[j].avg_bw = 1;
238 			domain->paths[j].peak_bw = 1;
239 		}
240 
241 		ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
242 		if (ret) {
243 			if (ret != -EPROBE_DEFER) {
244 				dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
245 				domain->num_paths = 0;
246 			} else {
247 				dev_err_probe(dev, ret, "failed to get noc entries\n");
248 				goto cleanup_pds;
249 			}
250 		}
251 
252 		ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
253 		if (ret) {
254 			dev_err_probe(dev, ret, "failed to get clock\n");
255 			goto cleanup_pds;
256 		}
257 
258 		domain->power_dev =
259 			dev_pm_domain_attach_by_name(dev, data->gpc_name);
260 		if (IS_ERR(domain->power_dev)) {
261 			dev_err_probe(dev, PTR_ERR(domain->power_dev),
262 				      "failed to attach power domain \"%s\"\n",
263 				      data->gpc_name);
264 			ret = PTR_ERR(domain->power_dev);
265 			goto cleanup_pds;
266 		}
267 
268 		domain->genpd.name = data->name;
269 		domain->genpd.power_on = imx8m_blk_ctrl_power_on;
270 		domain->genpd.power_off = imx8m_blk_ctrl_power_off;
271 		domain->bc = bc;
272 
273 		ret = pm_genpd_init(&domain->genpd, NULL, true);
274 		if (ret) {
275 			dev_err_probe(dev, ret,
276 				      "failed to init power domain \"%s\"\n",
277 				      data->gpc_name);
278 			dev_pm_domain_detach(domain->power_dev, true);
279 			goto cleanup_pds;
280 		}
281 
282 		/*
283 		 * We use runtime PM to trigger power on/off of the upstream GPC
284 		 * domain, as a strict hierarchical parent/child power domain
285 		 * setup doesn't allow us to meet the sequencing requirements.
286 		 * This means we have nested locking of genpd locks, without the
287 		 * nesting being visible at the genpd level, so we need a
288 		 * separate lock class to make lockdep aware of the fact that
289 		 * this are separate domain locks that can be nested without a
290 		 * self-deadlock.
291 		 */
292 		lockdep_set_class(&domain->genpd.mlock,
293 				  &blk_ctrl_genpd_lock_class);
294 
295 		bc->onecell_data.domains[i] = &domain->genpd;
296 	}
297 
298 	ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
299 	if (ret) {
300 		dev_err_probe(dev, ret, "failed to add power domain provider\n");
301 		goto cleanup_pds;
302 	}
303 
304 	bc->power_nb.notifier_call = bc_data->power_notifier_fn;
305 	ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
306 	if (ret) {
307 		dev_err_probe(dev, ret, "failed to add power notifier\n");
308 		goto cleanup_provider;
309 	}
310 
311 	dev_set_drvdata(dev, bc);
312 
313 	return 0;
314 
315 cleanup_provider:
316 	of_genpd_del_provider(dev->of_node);
317 cleanup_pds:
318 	for (i--; i >= 0; i--) {
319 		pm_genpd_remove(&bc->domains[i].genpd);
320 		dev_pm_domain_detach(bc->domains[i].power_dev, true);
321 	}
322 
323 	dev_pm_domain_detach(bc->bus_power_dev, true);
324 
325 	return ret;
326 }
327 
imx8m_blk_ctrl_remove(struct platform_device * pdev)328 static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
329 {
330 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
331 	int i;
332 
333 	of_genpd_del_provider(pdev->dev.of_node);
334 
335 	for (i = 0; bc->onecell_data.num_domains; i++) {
336 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
337 
338 		pm_genpd_remove(&domain->genpd);
339 		dev_pm_domain_detach(domain->power_dev, true);
340 	}
341 
342 	dev_pm_genpd_remove_notifier(bc->bus_power_dev);
343 
344 	dev_pm_domain_detach(bc->bus_power_dev, true);
345 
346 	return 0;
347 }
348 
349 #ifdef CONFIG_PM_SLEEP
imx8m_blk_ctrl_suspend(struct device * dev)350 static int imx8m_blk_ctrl_suspend(struct device *dev)
351 {
352 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
353 	int ret, i;
354 
355 	/*
356 	 * This may look strange, but is done so the generic PM_SLEEP code
357 	 * can power down our domains and more importantly power them up again
358 	 * after resume, without tripping over our usage of runtime PM to
359 	 * control the upstream GPC domains. Things happen in the right order
360 	 * in the system suspend/resume paths due to the device parent/child
361 	 * hierarchy.
362 	 */
363 	ret = pm_runtime_get_sync(bc->bus_power_dev);
364 	if (ret < 0) {
365 		pm_runtime_put_noidle(bc->bus_power_dev);
366 		return ret;
367 	}
368 
369 	for (i = 0; i < bc->onecell_data.num_domains; i++) {
370 		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
371 
372 		ret = pm_runtime_get_sync(domain->power_dev);
373 		if (ret < 0) {
374 			pm_runtime_put_noidle(domain->power_dev);
375 			goto out_fail;
376 		}
377 	}
378 
379 	return 0;
380 
381 out_fail:
382 	for (i--; i >= 0; i--)
383 		pm_runtime_put(bc->domains[i].power_dev);
384 
385 	pm_runtime_put(bc->bus_power_dev);
386 
387 	return ret;
388 }
389 
imx8m_blk_ctrl_resume(struct device * dev)390 static int imx8m_blk_ctrl_resume(struct device *dev)
391 {
392 	struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
393 	int i;
394 
395 	for (i = 0; i < bc->onecell_data.num_domains; i++)
396 		pm_runtime_put(bc->domains[i].power_dev);
397 
398 	pm_runtime_put(bc->bus_power_dev);
399 
400 	return 0;
401 }
402 #endif
403 
404 static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
405 	SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
406 };
407 
imx8mm_vpu_power_notifier(struct notifier_block * nb,unsigned long action,void * data)408 static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
409 				     unsigned long action, void *data)
410 {
411 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
412 						 power_nb);
413 
414 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
415 		return NOTIFY_OK;
416 
417 	/*
418 	 * The ADB in the VPUMIX domain has no separate reset and clock
419 	 * enable bits, but is ungated together with the VPU clocks. To
420 	 * allow the handshake with the GPC to progress we put the VPUs
421 	 * in reset and ungate the clocks.
422 	 */
423 	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
424 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
425 
426 	if (action == GENPD_NOTIFY_ON) {
427 		/*
428 		 * On power up we have no software backchannel to the GPC to
429 		 * wait for the ADB handshake to happen, so we just delay for a
430 		 * bit. On power down the GPC driver waits for the handshake.
431 		 */
432 		udelay(5);
433 
434 		/* set "fuse" bits to enable the VPUs */
435 		regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
436 		regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
437 		regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
438 		regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
439 	}
440 
441 	return NOTIFY_OK;
442 }
443 
444 static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
445 	[IMX8MM_VPUBLK_PD_G1] = {
446 		.name = "vpublk-g1",
447 		.clk_names = (const char *[]){ "g1", },
448 		.num_clks = 1,
449 		.gpc_name = "g1",
450 		.rst_mask = BIT(1),
451 		.clk_mask = BIT(1),
452 	},
453 	[IMX8MM_VPUBLK_PD_G2] = {
454 		.name = "vpublk-g2",
455 		.clk_names = (const char *[]){ "g2", },
456 		.num_clks = 1,
457 		.gpc_name = "g2",
458 		.rst_mask = BIT(0),
459 		.clk_mask = BIT(0),
460 	},
461 	[IMX8MM_VPUBLK_PD_H1] = {
462 		.name = "vpublk-h1",
463 		.clk_names = (const char *[]){ "h1", },
464 		.num_clks = 1,
465 		.gpc_name = "h1",
466 		.rst_mask = BIT(2),
467 		.clk_mask = BIT(2),
468 	},
469 };
470 
471 static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
472 	.max_reg = 0x18,
473 	.power_notifier_fn = imx8mm_vpu_power_notifier,
474 	.domains = imx8mm_vpu_blk_ctl_domain_data,
475 	.num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
476 };
477 
478 static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
479 	[IMX8MP_VPUBLK_PD_G1] = {
480 		.name = "vpublk-g1",
481 		.clk_names = (const char *[]){ "g1", },
482 		.num_clks = 1,
483 		.gpc_name = "g1",
484 		.rst_mask = BIT(1),
485 		.clk_mask = BIT(1),
486 		.path_names = (const char *[]){"g1"},
487 		.num_paths = 1,
488 	},
489 	[IMX8MP_VPUBLK_PD_G2] = {
490 		.name = "vpublk-g2",
491 		.clk_names = (const char *[]){ "g2", },
492 		.num_clks = 1,
493 		.gpc_name = "g2",
494 		.rst_mask = BIT(0),
495 		.clk_mask = BIT(0),
496 		.path_names = (const char *[]){"g2"},
497 		.num_paths = 1,
498 	},
499 	[IMX8MP_VPUBLK_PD_VC8000E] = {
500 		.name = "vpublk-vc8000e",
501 		.clk_names = (const char *[]){ "vc8000e", },
502 		.num_clks = 1,
503 		.gpc_name = "vc8000e",
504 		.rst_mask = BIT(2),
505 		.clk_mask = BIT(2),
506 		.path_names = (const char *[]){"vc8000e"},
507 		.num_paths = 1,
508 	},
509 };
510 
511 static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
512 	.max_reg = 0x18,
513 	.power_notifier_fn = imx8mm_vpu_power_notifier,
514 	.domains = imx8mp_vpu_blk_ctl_domain_data,
515 	.num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
516 };
517 
imx8mm_disp_power_notifier(struct notifier_block * nb,unsigned long action,void * data)518 static int imx8mm_disp_power_notifier(struct notifier_block *nb,
519 				      unsigned long action, void *data)
520 {
521 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
522 						 power_nb);
523 
524 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
525 		return NOTIFY_OK;
526 
527 	/* Enable bus clock and deassert bus reset */
528 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
529 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
530 
531 	/*
532 	 * On power up we have no software backchannel to the GPC to
533 	 * wait for the ADB handshake to happen, so we just delay for a
534 	 * bit. On power down the GPC driver waits for the handshake.
535 	 */
536 	if (action == GENPD_NOTIFY_ON)
537 		udelay(5);
538 
539 
540 	return NOTIFY_OK;
541 }
542 
543 static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
544 	[IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
545 		.name = "dispblk-csi-bridge",
546 		.clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
547 					       "csi-bridge-core", },
548 		.num_clks = 3,
549 		.gpc_name = "csi-bridge",
550 		.rst_mask = BIT(0) | BIT(1) | BIT(2),
551 		.clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
552 	},
553 	[IMX8MM_DISPBLK_PD_LCDIF] = {
554 		.name = "dispblk-lcdif",
555 		.clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
556 		.num_clks = 3,
557 		.gpc_name = "lcdif",
558 		.clk_mask = BIT(6) | BIT(7),
559 	},
560 	[IMX8MM_DISPBLK_PD_MIPI_DSI] = {
561 		.name = "dispblk-mipi-dsi",
562 		.clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
563 		.num_clks = 2,
564 		.gpc_name = "mipi-dsi",
565 		.rst_mask = BIT(5),
566 		.clk_mask = BIT(8) | BIT(9),
567 		.mipi_phy_rst_mask = BIT(17),
568 	},
569 	[IMX8MM_DISPBLK_PD_MIPI_CSI] = {
570 		.name = "dispblk-mipi-csi",
571 		.clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
572 		.num_clks = 2,
573 		.gpc_name = "mipi-csi",
574 		.rst_mask = BIT(3) | BIT(4),
575 		.clk_mask = BIT(10) | BIT(11),
576 		.mipi_phy_rst_mask = BIT(16),
577 	},
578 };
579 
580 static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
581 	.max_reg = 0x2c,
582 	.power_notifier_fn = imx8mm_disp_power_notifier,
583 	.domains = imx8mm_disp_blk_ctl_domain_data,
584 	.num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
585 };
586 
587 
imx8mn_disp_power_notifier(struct notifier_block * nb,unsigned long action,void * data)588 static int imx8mn_disp_power_notifier(struct notifier_block *nb,
589 				      unsigned long action, void *data)
590 {
591 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
592 						 power_nb);
593 
594 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
595 		return NOTIFY_OK;
596 
597 	/* Enable bus clock and deassert bus reset */
598 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
599 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
600 
601 	/*
602 	 * On power up we have no software backchannel to the GPC to
603 	 * wait for the ADB handshake to happen, so we just delay for a
604 	 * bit. On power down the GPC driver waits for the handshake.
605 	 */
606 	if (action == GENPD_NOTIFY_ON)
607 		udelay(5);
608 
609 
610 	return NOTIFY_OK;
611 }
612 
613 static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
614 	[IMX8MN_DISPBLK_PD_MIPI_DSI] = {
615 		.name = "dispblk-mipi-dsi",
616 		.clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
617 		.num_clks = 2,
618 		.gpc_name = "mipi-dsi",
619 		.rst_mask = BIT(0) | BIT(1),
620 		.clk_mask = BIT(0) | BIT(1),
621 		.mipi_phy_rst_mask = BIT(17),
622 	},
623 	[IMX8MN_DISPBLK_PD_MIPI_CSI] = {
624 		.name = "dispblk-mipi-csi",
625 		.clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
626 		.num_clks = 2,
627 		.gpc_name = "mipi-csi",
628 		.rst_mask = BIT(2) | BIT(3),
629 		.clk_mask = BIT(2) | BIT(3),
630 		.mipi_phy_rst_mask = BIT(16),
631 	},
632 	[IMX8MN_DISPBLK_PD_LCDIF] = {
633 		.name = "dispblk-lcdif",
634 		.clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
635 		.num_clks = 3,
636 		.gpc_name = "lcdif",
637 		.rst_mask = BIT(4) | BIT(5),
638 		.clk_mask = BIT(4) | BIT(5),
639 	},
640 	[IMX8MN_DISPBLK_PD_ISI] = {
641 		.name = "dispblk-isi",
642 		.clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
643 						"disp_apb_root"},
644 		.num_clks = 4,
645 		.gpc_name = "isi",
646 		.rst_mask = BIT(6) | BIT(7),
647 		.clk_mask = BIT(6) | BIT(7),
648 	},
649 };
650 
651 static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
652 	.max_reg = 0x84,
653 	.power_notifier_fn = imx8mn_disp_power_notifier,
654 	.domains = imx8mn_disp_blk_ctl_domain_data,
655 	.num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
656 };
657 
658 #define LCDIF_ARCACHE_CTRL	0x4c
659 #define  LCDIF_1_RD_HURRY	GENMASK(15, 13)
660 #define  LCDIF_0_RD_HURRY	GENMASK(12, 10)
661 
imx8mp_media_power_notifier(struct notifier_block * nb,unsigned long action,void * data)662 static int imx8mp_media_power_notifier(struct notifier_block *nb,
663 				unsigned long action, void *data)
664 {
665 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
666 						 power_nb);
667 
668 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
669 		return NOTIFY_OK;
670 
671 	/* Enable bus clock and deassert bus reset */
672 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
673 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
674 
675 	if (action == GENPD_NOTIFY_ON) {
676 		/*
677 		 * On power up we have no software backchannel to the GPC to
678 		 * wait for the ADB handshake to happen, so we just delay for a
679 		 * bit. On power down the GPC driver waits for the handshake.
680 		 */
681 		udelay(5);
682 
683 		/*
684 		 * Set panic read hurry level for both LCDIF interfaces to
685 		 * maximum priority to minimize chances of display FIFO
686 		 * underflow.
687 		 */
688 		regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL,
689 				FIELD_PREP(LCDIF_1_RD_HURRY, 7) |
690 				FIELD_PREP(LCDIF_0_RD_HURRY, 7));
691 	}
692 
693 	return NOTIFY_OK;
694 }
695 
696 /*
697  * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
698  * section 13.2.2, 13.2.3
699  * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
700  */
701 static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
702 	[IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
703 		.name = "mediablk-mipi-dsi-1",
704 		.clk_names = (const char *[]){ "apb", "phy", },
705 		.num_clks = 2,
706 		.gpc_name = "mipi-dsi1",
707 		.rst_mask = BIT(0) | BIT(1),
708 		.clk_mask = BIT(0) | BIT(1),
709 		.mipi_phy_rst_mask = BIT(17),
710 	},
711 	[IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
712 		.name = "mediablk-mipi-csi2-1",
713 		.clk_names = (const char *[]){ "apb", "cam1" },
714 		.num_clks = 2,
715 		.gpc_name = "mipi-csi1",
716 		.rst_mask = BIT(2) | BIT(3),
717 		.clk_mask = BIT(2) | BIT(3),
718 		.mipi_phy_rst_mask = BIT(16),
719 	},
720 	[IMX8MP_MEDIABLK_PD_LCDIF_1] = {
721 		.name = "mediablk-lcdif-1",
722 		.clk_names = (const char *[]){ "disp1", "apb", "axi", },
723 		.num_clks = 3,
724 		.gpc_name = "lcdif1",
725 		.rst_mask = BIT(4) | BIT(5) | BIT(23),
726 		.clk_mask = BIT(4) | BIT(5) | BIT(23),
727 		.path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
728 		.num_paths = 2,
729 	},
730 	[IMX8MP_MEDIABLK_PD_ISI] = {
731 		.name = "mediablk-isi",
732 		.clk_names = (const char *[]){ "axi", "apb" },
733 		.num_clks = 2,
734 		.gpc_name = "isi",
735 		.rst_mask = BIT(6) | BIT(7),
736 		.clk_mask = BIT(6) | BIT(7),
737 		.path_names = (const char *[]){"isi0", "isi1", "isi2"},
738 		.num_paths = 3,
739 	},
740 	[IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
741 		.name = "mediablk-mipi-csi2-2",
742 		.clk_names = (const char *[]){ "apb", "cam2" },
743 		.num_clks = 2,
744 		.gpc_name = "mipi-csi2",
745 		.rst_mask = BIT(9) | BIT(10),
746 		.clk_mask = BIT(9) | BIT(10),
747 		.mipi_phy_rst_mask = BIT(30),
748 	},
749 	[IMX8MP_MEDIABLK_PD_LCDIF_2] = {
750 		.name = "mediablk-lcdif-2",
751 		.clk_names = (const char *[]){ "disp2", "apb", "axi", },
752 		.num_clks = 3,
753 		.gpc_name = "lcdif2",
754 		.rst_mask = BIT(11) | BIT(12) | BIT(24),
755 		.clk_mask = BIT(11) | BIT(12) | BIT(24),
756 		.path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
757 		.num_paths = 2,
758 	},
759 	[IMX8MP_MEDIABLK_PD_ISP] = {
760 		.name = "mediablk-isp",
761 		.clk_names = (const char *[]){ "isp", "axi", "apb" },
762 		.num_clks = 3,
763 		.gpc_name = "isp",
764 		.rst_mask = BIT(16) | BIT(17) | BIT(18),
765 		.clk_mask = BIT(16) | BIT(17) | BIT(18),
766 		.path_names = (const char *[]){"isp0", "isp1"},
767 		.num_paths = 2,
768 	},
769 	[IMX8MP_MEDIABLK_PD_DWE] = {
770 		.name = "mediablk-dwe",
771 		.clk_names = (const char *[]){ "axi", "apb" },
772 		.num_clks = 2,
773 		.gpc_name = "dwe",
774 		.rst_mask = BIT(19) | BIT(20) | BIT(21),
775 		.clk_mask = BIT(19) | BIT(20) | BIT(21),
776 		.path_names = (const char *[]){"dwe"},
777 		.num_paths = 1,
778 	},
779 	[IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
780 		.name = "mediablk-mipi-dsi-2",
781 		.clk_names = (const char *[]){ "phy", },
782 		.num_clks = 1,
783 		.gpc_name = "mipi-dsi2",
784 		.rst_mask = BIT(22),
785 		.clk_mask = BIT(22),
786 		.mipi_phy_rst_mask = BIT(29),
787 	},
788 };
789 
790 static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
791 	.max_reg = 0x138,
792 	.power_notifier_fn = imx8mp_media_power_notifier,
793 	.domains = imx8mp_media_blk_ctl_domain_data,
794 	.num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
795 };
796 
imx8mq_vpu_power_notifier(struct notifier_block * nb,unsigned long action,void * data)797 static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
798 				     unsigned long action, void *data)
799 {
800 	struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
801 						 power_nb);
802 
803 	if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
804 		return NOTIFY_OK;
805 
806 	/*
807 	 * The ADB in the VPUMIX domain has no separate reset and clock
808 	 * enable bits, but is ungated and reset together with the VPUs. The
809 	 * reset and clock enable inputs to the ADB is a logical OR of the
810 	 * VPU bits. In order to set the G2 fuse bits, the G2 clock must
811 	 * also be enabled.
812 	 */
813 	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
814 	regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
815 
816 	if (action == GENPD_NOTIFY_ON) {
817 		/*
818 		 * On power up we have no software backchannel to the GPC to
819 		 * wait for the ADB handshake to happen, so we just delay for a
820 		 * bit. On power down the GPC driver waits for the handshake.
821 		 */
822 		udelay(5);
823 
824 		/* set "fuse" bits to enable the VPUs */
825 		regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
826 		regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
827 		regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
828 	}
829 
830 	return NOTIFY_OK;
831 }
832 
833 static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
834 	[IMX8MQ_VPUBLK_PD_G1] = {
835 		.name = "vpublk-g1",
836 		.clk_names = (const char *[]){ "g1", },
837 		.num_clks = 1,
838 		.gpc_name = "g1",
839 		.rst_mask = BIT(1),
840 		.clk_mask = BIT(1),
841 	},
842 	[IMX8MQ_VPUBLK_PD_G2] = {
843 		.name = "vpublk-g2",
844 		.clk_names = (const char *[]){ "g2", },
845 		.num_clks = 1,
846 		.gpc_name = "g2",
847 		.rst_mask = BIT(0),
848 		.clk_mask = BIT(0),
849 	},
850 };
851 
852 static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
853 	.max_reg = 0x14,
854 	.power_notifier_fn = imx8mq_vpu_power_notifier,
855 	.domains = imx8mq_vpu_blk_ctl_domain_data,
856 	.num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
857 };
858 
859 static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
860 	{
861 		.compatible = "fsl,imx8mm-vpu-blk-ctrl",
862 		.data = &imx8mm_vpu_blk_ctl_dev_data
863 	}, {
864 		.compatible = "fsl,imx8mm-disp-blk-ctrl",
865 		.data = &imx8mm_disp_blk_ctl_dev_data
866 	}, {
867 		.compatible = "fsl,imx8mn-disp-blk-ctrl",
868 		.data = &imx8mn_disp_blk_ctl_dev_data
869 	}, {
870 		.compatible = "fsl,imx8mp-media-blk-ctrl",
871 		.data = &imx8mp_media_blk_ctl_dev_data
872 	}, {
873 		.compatible = "fsl,imx8mq-vpu-blk-ctrl",
874 		.data = &imx8mq_vpu_blk_ctl_dev_data
875 	}, {
876 		.compatible = "fsl,imx8mp-vpu-blk-ctrl",
877 		.data = &imx8mp_vpu_blk_ctl_dev_data
878 	}, {
879 		/* Sentinel */
880 	}
881 };
882 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
883 
884 static struct platform_driver imx8m_blk_ctrl_driver = {
885 	.probe = imx8m_blk_ctrl_probe,
886 	.remove = imx8m_blk_ctrl_remove,
887 	.driver = {
888 		.name = "imx8m-blk-ctrl",
889 		.pm = &imx8m_blk_ctrl_pm_ops,
890 		.of_match_table = imx8m_blk_ctrl_of_match,
891 	},
892 };
893 module_platform_driver(imx8m_blk_ctrl_driver);
894