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