xref: /linux/drivers/pmdomain/imx/imx8mp-blk-ctrl.c (revision e9ab2b83893dd03cf04d98faded81190e635233f)
1 // SPDX-License-Identifier: GPL-2.0+
2 
3 /*
4  * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/device.h>
11 #include <linux/interconnect.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_domain.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
18 
19 #include <dt-bindings/power/imx8mp-power.h>
20 
21 #define GPR_REG0		0x0
22 #define  PCIE_CLOCK_MODULE_EN	BIT(0)
23 #define  USB_CLOCK_MODULE_EN	BIT(1)
24 #define  PCIE_PHY_APB_RST	BIT(4)
25 #define  PCIE_PHY_INIT_RST	BIT(5)
26 #define GPR_REG1		0x4
27 #define  PLL_LOCK		BIT(13)
28 #define GPR_REG2		0x8
29 #define  P_PLL_MASK		GENMASK(5, 0)
30 #define  M_PLL_MASK		GENMASK(15, 6)
31 #define  S_PLL_MASK		GENMASK(18, 16)
32 #define GPR_REG3		0xc
33 #define  PLL_CKE		BIT(17)
34 #define  PLL_RST		BIT(31)
35 
36 struct imx8mp_blk_ctrl_domain;
37 
38 struct imx8mp_blk_ctrl {
39 	struct device *dev;
40 	struct notifier_block power_nb;
41 	struct device *bus_power_dev;
42 	struct regmap *regmap;
43 	struct imx8mp_blk_ctrl_domain *domains;
44 	struct genpd_onecell_data onecell_data;
45 	void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
46 	void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
47 };
48 
49 struct imx8mp_blk_ctrl_domain_data {
50 	const char *name;
51 	const char * const *clk_names;
52 	int num_clks;
53 	const char * const *path_names;
54 	int num_paths;
55 	const char *gpc_name;
56 };
57 
58 #define DOMAIN_MAX_CLKS 3
59 #define DOMAIN_MAX_PATHS 3
60 
61 struct imx8mp_blk_ctrl_domain {
62 	struct generic_pm_domain genpd;
63 	const struct imx8mp_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 imx8mp_blk_ctrl *bc;
68 	struct notifier_block power_nb;
69 	int num_paths;
70 	int id;
71 };
72 
73 struct imx8mp_blk_ctrl_data {
74 	int max_reg;
75 	int (*probe) (struct imx8mp_blk_ctrl *bc);
76 	notifier_fn_t power_notifier_fn;
77 	void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
78 	void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
79 	const struct imx8mp_blk_ctrl_domain_data *domains;
80 	int num_domains;
81 };
82 
83 static inline struct imx8mp_blk_ctrl_domain *
84 to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
85 {
86 	return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
87 }
88 
89 struct clk_hsio_pll {
90 	struct clk_hw	hw;
91 	struct regmap *regmap;
92 };
93 
94 static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
95 {
96 	return container_of(hw, struct clk_hsio_pll, hw);
97 }
98 
99 static int clk_hsio_pll_prepare(struct clk_hw *hw)
100 {
101 	struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
102 	u32 val;
103 
104 	/* set the PLL configuration */
105 	regmap_update_bits(clk->regmap, GPR_REG2,
106 			   P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
107 			   FIELD_PREP(P_PLL_MASK, 12) |
108 			   FIELD_PREP(M_PLL_MASK, 800) |
109 			   FIELD_PREP(S_PLL_MASK, 4));
110 
111 	/* de-assert PLL reset */
112 	regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
113 
114 	/* enable PLL */
115 	regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
116 
117 	return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
118 					val & PLL_LOCK, 10, 100);
119 }
120 
121 static void clk_hsio_pll_unprepare(struct clk_hw *hw)
122 {
123 	struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
124 
125 	regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
126 }
127 
128 static int clk_hsio_pll_is_prepared(struct clk_hw *hw)
129 {
130 	struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
131 
132 	return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK);
133 }
134 
135 static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
136 					      unsigned long parent_rate)
137 {
138 	return 100000000;
139 }
140 
141 static const struct clk_ops clk_hsio_pll_ops = {
142 	.prepare = clk_hsio_pll_prepare,
143 	.unprepare = clk_hsio_pll_unprepare,
144 	.is_prepared = clk_hsio_pll_is_prepared,
145 	.recalc_rate = clk_hsio_pll_recalc_rate,
146 };
147 
148 static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
149 {
150 	struct clk_hsio_pll *clk_hsio_pll;
151 	struct clk_hw *hw;
152 	struct clk_init_data init = {};
153 	int ret;
154 
155 	clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
156 	if (!clk_hsio_pll)
157 		return -ENOMEM;
158 
159 	init.name = "hsio_pll";
160 	init.ops = &clk_hsio_pll_ops;
161 	init.parent_names = (const char *[]){"osc_24m"};
162 	init.num_parents = 1;
163 
164 	clk_hsio_pll->regmap = bc->regmap;
165 	clk_hsio_pll->hw.init = &init;
166 
167 	hw = &clk_hsio_pll->hw;
168 	ret = devm_clk_hw_register(bc->bus_power_dev, hw);
169 	if (ret)
170 		return ret;
171 
172 	return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw);
173 }
174 
175 static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
176 					  struct imx8mp_blk_ctrl_domain *domain)
177 {
178 	switch (domain->id) {
179 	case IMX8MP_HSIOBLK_PD_USB:
180 		regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
181 		break;
182 	case IMX8MP_HSIOBLK_PD_PCIE:
183 		regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
184 		break;
185 	case IMX8MP_HSIOBLK_PD_PCIE_PHY:
186 		regmap_set_bits(bc->regmap, GPR_REG0,
187 				PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
188 		break;
189 	default:
190 		break;
191 	}
192 }
193 
194 static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
195 					   struct imx8mp_blk_ctrl_domain *domain)
196 {
197 	switch (domain->id) {
198 	case IMX8MP_HSIOBLK_PD_USB:
199 		regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
200 		break;
201 	case IMX8MP_HSIOBLK_PD_PCIE:
202 		regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
203 		break;
204 	case IMX8MP_HSIOBLK_PD_PCIE_PHY:
205 		regmap_clear_bits(bc->regmap, GPR_REG0,
206 				  PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
207 		break;
208 	default:
209 		break;
210 	}
211 }
212 
213 static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
214 				      unsigned long action, void *data)
215 {
216 	struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
217 						 power_nb);
218 	struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
219 	int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
220 	int ret;
221 
222 	switch (action) {
223 	case GENPD_NOTIFY_ON:
224 		/*
225 		 * enable USB clock for a moment for the power-on ADB handshake
226 		 * to proceed
227 		 */
228 		ret = clk_bulk_prepare_enable(num_clks, usb_clk);
229 		if (ret)
230 			return NOTIFY_BAD;
231 		regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
232 
233 		udelay(5);
234 
235 		regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
236 		clk_bulk_disable_unprepare(num_clks, usb_clk);
237 		break;
238 	case GENPD_NOTIFY_PRE_OFF:
239 		/* enable USB clock for the power-down ADB handshake to work */
240 		ret = clk_bulk_prepare_enable(num_clks, usb_clk);
241 		if (ret)
242 			return NOTIFY_BAD;
243 
244 		regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
245 		break;
246 	case GENPD_NOTIFY_OFF:
247 		clk_bulk_disable_unprepare(num_clks, usb_clk);
248 		break;
249 	default:
250 		break;
251 	}
252 
253 	return NOTIFY_OK;
254 }
255 
256 static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
257 	[IMX8MP_HSIOBLK_PD_USB] = {
258 		.name = "hsioblk-usb",
259 		.clk_names = (const char *[]){ "usb" },
260 		.num_clks = 1,
261 		.gpc_name = "usb",
262 		.path_names = (const char *[]){"usb1", "usb2"},
263 		.num_paths = 2,
264 	},
265 	[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
266 		.name = "hsioblk-usb-phy1",
267 		.gpc_name = "usb-phy1",
268 	},
269 	[IMX8MP_HSIOBLK_PD_USB_PHY2] = {
270 		.name = "hsioblk-usb-phy2",
271 		.gpc_name = "usb-phy2",
272 	},
273 	[IMX8MP_HSIOBLK_PD_PCIE] = {
274 		.name = "hsioblk-pcie",
275 		.clk_names = (const char *[]){ "pcie" },
276 		.num_clks = 1,
277 		.gpc_name = "pcie",
278 		.path_names = (const char *[]){"noc-pcie", "pcie"},
279 		.num_paths = 2,
280 	},
281 	[IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
282 		.name = "hsioblk-pcie-phy",
283 		.gpc_name = "pcie-phy",
284 	},
285 };
286 
287 static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
288 	.max_reg = 0x24,
289 	.probe = imx8mp_hsio_blk_ctrl_probe,
290 	.power_on = imx8mp_hsio_blk_ctrl_power_on,
291 	.power_off = imx8mp_hsio_blk_ctrl_power_off,
292 	.power_notifier_fn = imx8mp_hsio_power_notifier,
293 	.domains = imx8mp_hsio_domain_data,
294 	.num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
295 };
296 
297 #define HDMI_RTX_RESET_CTL0	0x20
298 #define HDMI_RTX_CLK_CTL0	0x40
299 #define HDMI_RTX_CLK_CTL1	0x50
300 #define HDMI_RTX_CLK_CTL2	0x60
301 #define HDMI_RTX_CLK_CTL3	0x70
302 #define HDMI_RTX_CLK_CTL4	0x80
303 #define HDMI_TX_CONTROL0	0x200
304 #define  HDMI_LCDIF_NOC_HURRY_MASK		GENMASK(14, 12)
305 
306 static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
307 					  struct imx8mp_blk_ctrl_domain *domain)
308 {
309 	switch (domain->id) {
310 	case IMX8MP_HDMIBLK_PD_IRQSTEER:
311 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
312 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
313 		break;
314 	case IMX8MP_HDMIBLK_PD_LCDIF:
315 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
316 				BIT(16) | BIT(17) | BIT(18) |
317 				BIT(19) | BIT(20));
318 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
319 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
320 				BIT(4) | BIT(5) | BIT(6));
321 		regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0,
322 				FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7));
323 		break;
324 	case IMX8MP_HDMIBLK_PD_PAI:
325 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
326 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
327 		break;
328 	case IMX8MP_HDMIBLK_PD_PVI:
329 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
330 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
331 		break;
332 	case IMX8MP_HDMIBLK_PD_TRNG:
333 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
334 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
335 		break;
336 	case IMX8MP_HDMIBLK_PD_HDMI_TX:
337 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
338 				BIT(2) | BIT(4) | BIT(5));
339 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
340 				BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
341 				BIT(18) | BIT(19) | BIT(20) | BIT(21));
342 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
343 				BIT(7) | BIT(10) | BIT(11));
344 		regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
345 		break;
346 	case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
347 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
348 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
349 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
350 		regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
351 		break;
352 	case IMX8MP_HDMIBLK_PD_HDCP:
353 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
354 		break;
355 	case IMX8MP_HDMIBLK_PD_HRV:
356 		regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
357 		regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
358 		break;
359 	default:
360 		break;
361 	}
362 }
363 
364 static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
365 					   struct imx8mp_blk_ctrl_domain *domain)
366 {
367 	switch (domain->id) {
368 	case IMX8MP_HDMIBLK_PD_IRQSTEER:
369 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
370 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
371 		break;
372 	case IMX8MP_HDMIBLK_PD_LCDIF:
373 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
374 				  BIT(4) | BIT(5) | BIT(6));
375 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
376 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
377 				  BIT(16) | BIT(17) | BIT(18) |
378 				  BIT(19) | BIT(20));
379 		break;
380 	case IMX8MP_HDMIBLK_PD_PAI:
381 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
382 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
383 		break;
384 	case IMX8MP_HDMIBLK_PD_PVI:
385 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
386 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
387 		break;
388 	case IMX8MP_HDMIBLK_PD_TRNG:
389 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
390 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
391 		break;
392 	case IMX8MP_HDMIBLK_PD_HDMI_TX:
393 		regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
394 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
395 				  BIT(7) | BIT(10) | BIT(11));
396 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
397 				  BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
398 				  BIT(18) | BIT(19) | BIT(20) | BIT(21));
399 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
400 				  BIT(2) | BIT(4) | BIT(5));
401 		break;
402 	case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
403 		regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
404 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
405 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
406 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
407 		break;
408 	case IMX8MP_HDMIBLK_PD_HDCP:
409 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
410 		break;
411 	case IMX8MP_HDMIBLK_PD_HRV:
412 		regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
413 		regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
414 		break;
415 	default:
416 		break;
417 	}
418 }
419 
420 static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
421 				      unsigned long action, void *data)
422 {
423 	struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
424 						 power_nb);
425 
426 	if (action != GENPD_NOTIFY_ON)
427 		return NOTIFY_OK;
428 
429 	/*
430 	 * Contrary to other blk-ctrls the reset and clock don't clear when the
431 	 * power domain is powered down. To ensure the proper reset pulsing,
432 	 * first clear them all to asserted state, then enable the bus clocks
433 	 * and then release the ADB reset.
434 	 */
435 	regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
436 	regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
437 	regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
438 	regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
439 			BIT(0) | BIT(1) | BIT(10));
440 	regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
441 
442 	/*
443 	 * On power up we have no software backchannel to the GPC to
444 	 * wait for the ADB handshake to happen, so we just delay for a
445 	 * bit. On power down the GPC driver waits for the handshake.
446 	 */
447 	udelay(5);
448 
449 	return NOTIFY_OK;
450 }
451 
452 static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
453 	[IMX8MP_HDMIBLK_PD_IRQSTEER] = {
454 		.name = "hdmiblk-irqsteer",
455 		.clk_names = (const char *[]){ "apb" },
456 		.num_clks = 1,
457 		.gpc_name = "irqsteer",
458 	},
459 	[IMX8MP_HDMIBLK_PD_LCDIF] = {
460 		.name = "hdmiblk-lcdif",
461 		.clk_names = (const char *[]){ "axi", "apb", "fdcc" },
462 		.num_clks = 3,
463 		.gpc_name = "lcdif",
464 		.path_names = (const char *[]){"lcdif-hdmi"},
465 		.num_paths = 1,
466 	},
467 	[IMX8MP_HDMIBLK_PD_PAI] = {
468 		.name = "hdmiblk-pai",
469 		.clk_names = (const char *[]){ "apb" },
470 		.num_clks = 1,
471 		.gpc_name = "pai",
472 	},
473 	[IMX8MP_HDMIBLK_PD_PVI] = {
474 		.name = "hdmiblk-pvi",
475 		.clk_names = (const char *[]){ "apb" },
476 		.num_clks = 1,
477 		.gpc_name = "pvi",
478 	},
479 	[IMX8MP_HDMIBLK_PD_TRNG] = {
480 		.name = "hdmiblk-trng",
481 		.clk_names = (const char *[]){ "apb" },
482 		.num_clks = 1,
483 		.gpc_name = "trng",
484 	},
485 	[IMX8MP_HDMIBLK_PD_HDMI_TX] = {
486 		.name = "hdmiblk-hdmi-tx",
487 		.clk_names = (const char *[]){ "apb", "ref_266m", "fdcc" },
488 		.num_clks = 3,
489 		.gpc_name = "hdmi-tx",
490 	},
491 	[IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
492 		.name = "hdmiblk-hdmi-tx-phy",
493 		.clk_names = (const char *[]){ "apb", "ref_24m" },
494 		.num_clks = 2,
495 		.gpc_name = "hdmi-tx-phy",
496 	},
497 	[IMX8MP_HDMIBLK_PD_HRV] = {
498 		.name = "hdmiblk-hrv",
499 		.clk_names = (const char *[]){ "axi", "apb" },
500 		.num_clks = 2,
501 		.gpc_name = "hrv",
502 		.path_names = (const char *[]){"hrv"},
503 		.num_paths = 1,
504 	},
505 	[IMX8MP_HDMIBLK_PD_HDCP] = {
506 		.name = "hdmiblk-hdcp",
507 		.clk_names = (const char *[]){ "axi", "apb" },
508 		.num_clks = 2,
509 		.gpc_name = "hdcp",
510 		.path_names = (const char *[]){"hdcp"},
511 		.num_paths = 1,
512 	},
513 };
514 
515 static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
516 	.max_reg = 0x23c,
517 	.power_on = imx8mp_hdmi_blk_ctrl_power_on,
518 	.power_off = imx8mp_hdmi_blk_ctrl_power_off,
519 	.power_notifier_fn = imx8mp_hdmi_power_notifier,
520 	.domains = imx8mp_hdmi_domain_data,
521 	.num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
522 };
523 
524 static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
525 {
526 	struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
527 	const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
528 	struct imx8mp_blk_ctrl *bc = domain->bc;
529 	int ret;
530 
531 	/* make sure bus domain is awake */
532 	ret = pm_runtime_resume_and_get(bc->bus_power_dev);
533 	if (ret < 0) {
534 		dev_err(bc->dev, "failed to power up bus domain\n");
535 		return ret;
536 	}
537 
538 	/* enable upstream clocks */
539 	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
540 	if (ret) {
541 		dev_err(bc->dev, "failed to enable clocks\n");
542 		goto bus_put;
543 	}
544 
545 	/* domain specific blk-ctrl manipulation */
546 	bc->power_on(bc, domain);
547 
548 	/* power up upstream GPC domain */
549 	ret = pm_runtime_resume_and_get(domain->power_dev);
550 	if (ret < 0) {
551 		dev_err(bc->dev, "failed to power up peripheral domain\n");
552 		goto clk_disable;
553 	}
554 
555 	ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
556 	if (ret)
557 		dev_err(bc->dev, "failed to set icc bw\n");
558 
559 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
560 
561 	return 0;
562 
563 clk_disable:
564 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
565 bus_put:
566 	pm_runtime_put(bc->bus_power_dev);
567 
568 	return ret;
569 }
570 
571 static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
572 {
573 	struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
574 	const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
575 	struct imx8mp_blk_ctrl *bc = domain->bc;
576 	int ret;
577 
578 	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
579 	if (ret) {
580 		dev_err(bc->dev, "failed to enable clocks\n");
581 		return ret;
582 	}
583 
584 	/* domain specific blk-ctrl manipulation */
585 	bc->power_off(bc, domain);
586 
587 	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
588 
589 	/* power down upstream GPC domain */
590 	pm_runtime_put(domain->power_dev);
591 
592 	/* allow bus domain to suspend */
593 	pm_runtime_put(bc->bus_power_dev);
594 
595 	return 0;
596 }
597 
598 static int imx8mp_blk_ctrl_gpc_notifier(struct notifier_block *nb,
599 					unsigned long action, void *data)
600 {
601 	struct imx8mp_blk_ctrl_domain *domain =
602 			container_of(nb, struct imx8mp_blk_ctrl_domain, power_nb);
603 
604 	if (action == GENPD_NOTIFY_PRE_OFF) {
605 		if (domain->genpd.status == GENPD_STATE_ON)
606 			return NOTIFY_BAD;
607 	}
608 
609 	return NOTIFY_OK;
610 }
611 
612 static struct lock_class_key blk_ctrl_genpd_lock_class;
613 
614 static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
615 {
616 	const struct imx8mp_blk_ctrl_data *bc_data;
617 	struct device *dev = &pdev->dev;
618 	struct imx8mp_blk_ctrl *bc;
619 	void __iomem *base;
620 	int num_domains, i, ret;
621 
622 	struct regmap_config regmap_config = {
623 		.reg_bits	= 32,
624 		.val_bits	= 32,
625 		.reg_stride	= 4,
626 	};
627 
628 	bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
629 	if (!bc)
630 		return -ENOMEM;
631 
632 	bc->dev = dev;
633 
634 	bc_data = of_device_get_match_data(dev);
635 	num_domains = bc_data->num_domains;
636 
637 	base = devm_platform_ioremap_resource(pdev, 0);
638 	if (IS_ERR(base))
639 		return PTR_ERR(base);
640 
641 	regmap_config.max_register = bc_data->max_reg;
642 	bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
643 	if (IS_ERR(bc->regmap))
644 		return dev_err_probe(dev, PTR_ERR(bc->regmap),
645 				     "failed to init regmap\n");
646 
647 	bc->domains = devm_kcalloc(dev, num_domains,
648 				   sizeof(struct imx8mp_blk_ctrl_domain),
649 				   GFP_KERNEL);
650 	if (!bc->domains)
651 		return -ENOMEM;
652 
653 	bc->onecell_data.num_domains = num_domains;
654 	bc->onecell_data.domains =
655 		devm_kcalloc(dev, num_domains,
656 			     sizeof(struct generic_pm_domain *), GFP_KERNEL);
657 	if (!bc->onecell_data.domains)
658 		return -ENOMEM;
659 
660 	bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
661 	if (IS_ERR(bc->bus_power_dev))
662 		return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
663 				     "failed to attach bus power domain\n");
664 
665 	bc->power_off = bc_data->power_off;
666 	bc->power_on = bc_data->power_on;
667 
668 	for (i = 0; i < num_domains; i++) {
669 		const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
670 		struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
671 		int j;
672 
673 		domain->data = data;
674 		domain->num_paths = data->num_paths;
675 
676 		for (j = 0; j < data->num_clks; j++)
677 			domain->clks[j].id = data->clk_names[j];
678 
679 		for (j = 0; j < data->num_paths; j++) {
680 			domain->paths[j].name = data->path_names[j];
681 			/* Fake value for now, just let ICC could configure NoC mode/priority */
682 			domain->paths[j].avg_bw = 1;
683 			domain->paths[j].peak_bw = 1;
684 		}
685 
686 		ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
687 		if (ret) {
688 			if (ret != -EPROBE_DEFER) {
689 				dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
690 				domain->num_paths = 0;
691 			} else {
692 				dev_err_probe(dev, ret, "failed to get noc entries\n");
693 				goto cleanup_pds;
694 			}
695 		}
696 
697 		ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
698 		if (ret) {
699 			dev_err_probe(dev, ret, "failed to get clock\n");
700 			goto cleanup_pds;
701 		}
702 
703 		domain->power_dev =
704 			dev_pm_domain_attach_by_name(dev, data->gpc_name);
705 		if (IS_ERR_OR_NULL(domain->power_dev)) {
706 			if (!domain->power_dev)
707 				ret = -ENODEV;
708 			else
709 				ret = PTR_ERR(domain->power_dev);
710 			dev_err_probe(dev, ret,
711 				      "failed to attach power domain %s\n",
712 				      data->gpc_name);
713 			goto cleanup_pds;
714 		}
715 
716 		domain->power_nb.notifier_call = imx8mp_blk_ctrl_gpc_notifier;
717 		ret = dev_pm_genpd_add_notifier(domain->power_dev, &domain->power_nb);
718 		if (ret) {
719 			dev_err_probe(dev, ret, "failed to add power notifier\n");
720 			dev_pm_domain_detach(domain->power_dev, true);
721 			goto cleanup_pds;
722 		}
723 
724 		domain->genpd.name = data->name;
725 		domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
726 		domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
727 		domain->bc = bc;
728 		domain->id = i;
729 
730 		ret = pm_genpd_init(&domain->genpd, NULL, true);
731 		if (ret) {
732 			dev_err_probe(dev, ret, "failed to init power domain\n");
733 			dev_pm_genpd_remove_notifier(domain->power_dev);
734 			dev_pm_domain_detach(domain->power_dev, true);
735 			goto cleanup_pds;
736 		}
737 
738 		/*
739 		 * We use runtime PM to trigger power on/off of the upstream GPC
740 		 * domain, as a strict hierarchical parent/child power domain
741 		 * setup doesn't allow us to meet the sequencing requirements.
742 		 * This means we have nested locking of genpd locks, without the
743 		 * nesting being visible at the genpd level, so we need a
744 		 * separate lock class to make lockdep aware of the fact that
745 		 * this are separate domain locks that can be nested without a
746 		 * self-deadlock.
747 		 */
748 		lockdep_set_class(&domain->genpd.mlock,
749 				  &blk_ctrl_genpd_lock_class);
750 
751 		bc->onecell_data.domains[i] = &domain->genpd;
752 	}
753 
754 	ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
755 	if (ret) {
756 		dev_err_probe(dev, ret, "failed to add power domain provider\n");
757 		goto cleanup_pds;
758 	}
759 
760 	bc->power_nb.notifier_call = bc_data->power_notifier_fn;
761 	ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
762 	if (ret) {
763 		dev_err_probe(dev, ret, "failed to add power notifier\n");
764 		goto cleanup_provider;
765 	}
766 
767 	if (bc_data->probe) {
768 		ret = bc_data->probe(bc);
769 		if (ret)
770 			goto cleanup_provider;
771 	}
772 
773 	dev_set_drvdata(dev, bc);
774 
775 	return 0;
776 
777 cleanup_provider:
778 	of_genpd_del_provider(dev->of_node);
779 cleanup_pds:
780 	for (i--; i >= 0; i--) {
781 		pm_genpd_remove(&bc->domains[i].genpd);
782 		dev_pm_genpd_remove_notifier(bc->domains[i].power_dev);
783 		dev_pm_domain_detach(bc->domains[i].power_dev, true);
784 	}
785 
786 	dev_pm_domain_detach(bc->bus_power_dev, true);
787 
788 	return ret;
789 }
790 
791 static void imx8mp_blk_ctrl_remove(struct platform_device *pdev)
792 {
793 	struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
794 	int i;
795 
796 	of_genpd_del_provider(pdev->dev.of_node);
797 
798 	for (i = 0; i < bc->onecell_data.num_domains; i++) {
799 		struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
800 
801 		pm_genpd_remove(&domain->genpd);
802 		dev_pm_genpd_remove_notifier(domain->power_dev);
803 		dev_pm_domain_detach(domain->power_dev, true);
804 	}
805 
806 	dev_pm_genpd_remove_notifier(bc->bus_power_dev);
807 
808 	dev_pm_domain_detach(bc->bus_power_dev, true);
809 }
810 
811 #ifdef CONFIG_PM_SLEEP
812 static int imx8mp_blk_ctrl_suspend(struct device *dev)
813 {
814 	struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
815 	int ret, i;
816 
817 	/*
818 	 * This may look strange, but is done so the generic PM_SLEEP code
819 	 * can power down our domains and more importantly power them up again
820 	 * after resume, without tripping over our usage of runtime PM to
821 	 * control the upstream GPC domains. Things happen in the right order
822 	 * in the system suspend/resume paths due to the device parent/child
823 	 * hierarchy.
824 	 */
825 	ret = pm_runtime_get_sync(bc->bus_power_dev);
826 	if (ret < 0) {
827 		pm_runtime_put_noidle(bc->bus_power_dev);
828 		return ret;
829 	}
830 
831 	for (i = 0; i < bc->onecell_data.num_domains; i++) {
832 		struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
833 
834 		ret = pm_runtime_get_sync(domain->power_dev);
835 		if (ret < 0) {
836 			pm_runtime_put_noidle(domain->power_dev);
837 			goto out_fail;
838 		}
839 	}
840 
841 	return 0;
842 
843 out_fail:
844 	for (i--; i >= 0; i--)
845 		pm_runtime_put(bc->domains[i].power_dev);
846 
847 	pm_runtime_put(bc->bus_power_dev);
848 
849 	return ret;
850 }
851 
852 static int imx8mp_blk_ctrl_resume(struct device *dev)
853 {
854 	struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
855 	int i;
856 
857 	for (i = 0; i < bc->onecell_data.num_domains; i++)
858 		pm_runtime_put(bc->domains[i].power_dev);
859 
860 	pm_runtime_put(bc->bus_power_dev);
861 
862 	return 0;
863 }
864 #endif
865 
866 static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
867 	SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
868 				imx8mp_blk_ctrl_resume)
869 };
870 
871 static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
872 	{
873 		.compatible = "fsl,imx8mp-hsio-blk-ctrl",
874 		.data = &imx8mp_hsio_blk_ctl_dev_data,
875 	}, {
876 		.compatible = "fsl,imx8mp-hdmi-blk-ctrl",
877 		.data = &imx8mp_hdmi_blk_ctl_dev_data,
878 	}, {
879 		/* Sentinel */
880 	}
881 };
882 MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
883 
884 static struct platform_driver imx8mp_blk_ctrl_driver = {
885 	.probe = imx8mp_blk_ctrl_probe,
886 	.remove = imx8mp_blk_ctrl_remove,
887 	.driver = {
888 		.name = "imx8mp-blk-ctrl",
889 		.pm = &imx8mp_blk_ctrl_pm_ops,
890 		.of_match_table = imx8mp_blk_ctrl_of_match,
891 		.suppress_bind_attrs = true,
892 	},
893 };
894 module_platform_driver(imx8mp_blk_ctrl_driver);
895 MODULE_LICENSE("GPL");
896