Linux Audio

Check our new training course

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