1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2017 NXP
4 */
5
6#include <common.h>
7#include <clk.h>
8#include <dm.h>
9#include <malloc.h>
10#include <power-domain-uclass.h>
11#include <asm/global_data.h>
12#include <asm/io.h>
13#include <asm/mach-imx/sys_proto.h>
14#include <dm/device-internal.h>
15#include <dm/device.h>
16#include <dm/device_compat.h>
17#include <imx_sip.h>
18#include <linux/bitmap.h>
19#include <wait_bit.h>
20
21#include <dt-bindings/power/imx8mm-power.h>
22#include <dt-bindings/power/imx8mn-power.h>
23#include <dt-bindings/power/imx8mp-power.h>
24#include <dt-bindings/power/imx8mq-power.h>
25
26DECLARE_GLOBAL_DATA_PTR;
27
28#define GPC_PGC_CPU_MAPPING			0x0ec
29#define IMX8MP_GPC_PGC_CPU_MAPPING		0x1cc
30
31#define IMX8M_PCIE2_A53_DOMAIN			BIT(15)
32#define IMX8M_OTG2_A53_DOMAIN			BIT(5)
33#define IMX8M_OTG1_A53_DOMAIN			BIT(4)
34#define IMX8M_PCIE1_A53_DOMAIN			BIT(3)
35
36#define IMX8MM_OTG2_A53_DOMAIN			BIT(5)
37#define IMX8MM_OTG1_A53_DOMAIN			BIT(4)
38#define IMX8MM_PCIE_A53_DOMAIN			BIT(3)
39
40#define IMX8MN_OTG1_A53_DOMAIN			BIT(4)
41#define IMX8MN_MIPI_A53_DOMAIN			BIT(2)
42
43#define IMX8MP_HSIOMIX_A53_DOMAIN		BIT(19)
44#define IMX8MP_USB2_PHY_A53_DOMAIN		BIT(5)
45#define IMX8MP_USB1_PHY_A53_DOMAIN		BIT(4)
46#define IMX8MP_PCIE_PHY_A53_DOMAIN		BIT(3)
47
48#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ		0x0d8
49#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ		0x0e4
50
51#define GPC_PU_PGC_SW_PUP_REQ			0x0f8
52#define GPC_PU_PGC_SW_PDN_REQ			0x104
53
54#define IMX8M_PCIE2_SW_Pxx_REQ			BIT(13)
55#define IMX8M_OTG2_SW_Pxx_REQ			BIT(3)
56#define IMX8M_OTG1_SW_Pxx_REQ			BIT(2)
57#define IMX8M_PCIE1_SW_Pxx_REQ			BIT(1)
58
59#define IMX8MM_OTG2_SW_Pxx_REQ			BIT(3)
60#define IMX8MM_OTG1_SW_Pxx_REQ			BIT(2)
61#define IMX8MM_PCIE_SW_Pxx_REQ			BIT(1)
62
63#define IMX8MN_OTG1_SW_Pxx_REQ			BIT(2)
64#define IMX8MN_MIPI_SW_Pxx_REQ			BIT(0)
65
66#define IMX8MP_HSIOMIX_Pxx_REQ			BIT(17)
67#define IMX8MP_USB2_PHY_Pxx_REQ			BIT(3)
68#define IMX8MP_USB1_PHY_Pxx_REQ			BIT(2)
69#define IMX8MP_PCIE_PHY_SW_Pxx_REQ		BIT(1)
70
71#define GPC_M4_PU_PDN_FLG			0x1bc
72
73#define IMX8MP_GPC_PU_PWRHSK			0x190
74#define GPC_PU_PWRHSK				0x1fc
75
76#define IMX8MM_HSIO_HSK_PWRDNACKN		(BIT(23) | BIT(24))
77#define IMX8MM_HSIO_HSK_PWRDNREQN		(BIT(5) | BIT(6))
78
79#define IMX8MN_HSIO_HSK_PWRDNACKN		BIT(23)
80#define IMX8MN_HSIO_HSK_PWRDNREQN		BIT(5)
81
82#define IMX8MP_HSIOMIX_PWRDNACKN		BIT(28)
83#define IMX8MP_HSIOMIX_PWRDNREQN		BIT(12)
84
85/*
86 * The PGC offset values in Reference Manual
87 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
88 * GPC_PGC memory map are incorrect, below offset
89 * values are from design RTL.
90 */
91#define IMX8M_PGC_PCIE1			17
92#define IMX8M_PGC_OTG1			18
93#define IMX8M_PGC_OTG2			19
94#define IMX8M_PGC_PCIE2			29
95
96#define IMX8MM_PGC_PCIE			17
97#define IMX8MM_PGC_OTG1			18
98#define IMX8MM_PGC_OTG2			19
99
100#define IMX8MN_PGC_OTG1			18
101
102#define IMX8MP_PGC_PCIE			13
103#define IMX8MP_PGC_USB1			14
104#define IMX8MP_PGC_USB2			15
105#define IMX8MP_PGC_HSIOMIX		29
106
107#define GPC_PGC_CTRL(n)			(0x800 + (n) * 0x40)
108#define GPC_PGC_SR(n)			(GPC_PGC_CTRL(n) + 0xc)
109
110#define GPC_PGC_CTRL_PCR		BIT(0)
111
112struct imx_pgc_regs {
113	u16 map;
114	u16 pup;
115	u16 pdn;
116	u16 hsk;
117};
118
119struct imx_pgc_domain {
120	unsigned long pgc;
121
122	const struct {
123		u32 pxx;
124		u32 map;
125		u32 hskreq;
126		u32 hskack;
127	} bits;
128
129	const bool keep_clocks;
130};
131
132struct imx_pgc_domain_data {
133	const struct imx_pgc_domain *domains;
134	size_t domains_num;
135	const struct imx_pgc_regs *pgc_regs;
136};
137
138struct imx8m_power_domain_plat {
139	struct power_domain pd;
140	const struct imx_pgc_domain *domain;
141	const struct imx_pgc_regs *regs;
142	struct clk_bulk clk;
143	void __iomem *base;
144	int resource_id;
145	int has_pd;
146};
147
148#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MQ)
149static const struct imx_pgc_regs imx7_pgc_regs = {
150	.map = GPC_PGC_CPU_MAPPING,
151	.pup = GPC_PU_PGC_SW_PUP_REQ,
152	.pdn = GPC_PU_PGC_SW_PDN_REQ,
153	.hsk = GPC_PU_PWRHSK,
154};
155#endif
156
157#ifdef CONFIG_IMX8MQ
158static const struct imx_pgc_domain imx8m_pgc_domains[] = {
159	[IMX8M_POWER_DOMAIN_PCIE1] = {
160		.bits  = {
161			.pxx = IMX8M_PCIE1_SW_Pxx_REQ,
162			.map = IMX8M_PCIE1_A53_DOMAIN,
163		},
164		.pgc   = BIT(IMX8M_PGC_PCIE1),
165	},
166
167	[IMX8M_POWER_DOMAIN_USB_OTG1] = {
168		.bits  = {
169			.pxx = IMX8M_OTG1_SW_Pxx_REQ,
170			.map = IMX8M_OTG1_A53_DOMAIN,
171		},
172		.pgc   = BIT(IMX8M_PGC_OTG1),
173	},
174
175	[IMX8M_POWER_DOMAIN_USB_OTG2] = {
176		.bits  = {
177			.pxx = IMX8M_OTG2_SW_Pxx_REQ,
178			.map = IMX8M_OTG2_A53_DOMAIN,
179		},
180		.pgc   = BIT(IMX8M_PGC_OTG2),
181	},
182
183	[IMX8M_POWER_DOMAIN_PCIE2] = {
184		.bits  = {
185			.pxx = IMX8M_PCIE2_SW_Pxx_REQ,
186			.map = IMX8M_PCIE2_A53_DOMAIN,
187		},
188		.pgc   = BIT(IMX8M_PGC_PCIE2),
189	},
190};
191
192static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
193	.domains = imx8m_pgc_domains,
194	.domains_num = ARRAY_SIZE(imx8m_pgc_domains),
195	.pgc_regs = &imx7_pgc_regs,
196};
197#endif
198
199#ifdef CONFIG_IMX8MM
200static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
201	[IMX8MM_POWER_DOMAIN_HSIOMIX] = {
202		.bits  = {
203			.pxx = 0, /* no power sequence control */
204			.map = 0, /* no power sequence control */
205			.hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
206			.hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
207		},
208		.keep_clocks = true,
209	},
210
211	[IMX8MM_POWER_DOMAIN_PCIE] = {
212		.bits  = {
213			.pxx = IMX8MM_PCIE_SW_Pxx_REQ,
214			.map = IMX8MM_PCIE_A53_DOMAIN,
215		},
216		.pgc   = BIT(IMX8MM_PGC_PCIE),
217	},
218
219	[IMX8MM_POWER_DOMAIN_OTG1] = {
220		.bits  = {
221			.pxx = IMX8MM_OTG1_SW_Pxx_REQ,
222			.map = IMX8MM_OTG1_A53_DOMAIN,
223		},
224		.pgc   = BIT(IMX8MM_PGC_OTG1),
225	},
226
227	[IMX8MM_POWER_DOMAIN_OTG2] = {
228		.bits  = {
229			.pxx = IMX8MM_OTG2_SW_Pxx_REQ,
230			.map = IMX8MM_OTG2_A53_DOMAIN,
231		},
232		.pgc   = BIT(IMX8MM_PGC_OTG2),
233	},
234};
235
236static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
237	.domains = imx8mm_pgc_domains,
238	.domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
239	.pgc_regs = &imx7_pgc_regs,
240};
241#endif
242
243#ifdef CONFIG_IMX8MN
244static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
245	[IMX8MN_POWER_DOMAIN_HSIOMIX] = {
246		.bits  = {
247			.pxx = 0, /* no power sequence control */
248			.map = 0, /* no power sequence control */
249			.hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
250			.hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
251		},
252		.keep_clocks = true,
253	},
254
255	[IMX8MN_POWER_DOMAIN_OTG1] = {
256		.bits  = {
257			.pxx = IMX8MN_OTG1_SW_Pxx_REQ,
258			.map = IMX8MN_OTG1_A53_DOMAIN,
259		},
260		.pgc   = BIT(IMX8MN_PGC_OTG1),
261	},
262};
263
264static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
265	.domains = imx8mn_pgc_domains,
266	.domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
267	.pgc_regs = &imx7_pgc_regs,
268};
269#endif
270
271#ifdef CONFIG_IMX8MP
272static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
273	[IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
274		.bits = {
275			.pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
276			.map = IMX8MP_PCIE_PHY_A53_DOMAIN,
277		},
278		.pgc = BIT(IMX8MP_PGC_PCIE),
279	},
280
281	[IMX8MP_POWER_DOMAIN_USB1_PHY] = {
282		.bits = {
283			.pxx = IMX8MP_USB1_PHY_Pxx_REQ,
284			.map = IMX8MP_USB1_PHY_A53_DOMAIN,
285		},
286		.pgc = BIT(IMX8MP_PGC_USB1),
287	},
288
289	[IMX8MP_POWER_DOMAIN_USB2_PHY] = {
290		.bits = {
291			.pxx = IMX8MP_USB2_PHY_Pxx_REQ,
292			.map = IMX8MP_USB2_PHY_A53_DOMAIN,
293		},
294		.pgc = BIT(IMX8MP_PGC_USB2),
295	},
296
297	[IMX8MP_POWER_DOMAIN_HSIOMIX] = {
298		.bits = {
299			.pxx = IMX8MP_HSIOMIX_Pxx_REQ,
300			.map = IMX8MP_HSIOMIX_A53_DOMAIN,
301			.hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
302			.hskack = IMX8MP_HSIOMIX_PWRDNACKN,
303		},
304		.pgc = BIT(IMX8MP_PGC_HSIOMIX),
305		.keep_clocks = true,
306	},
307};
308
309static const struct imx_pgc_regs imx8mp_pgc_regs = {
310	.map = IMX8MP_GPC_PGC_CPU_MAPPING,
311	.pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
312	.pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
313	.hsk = IMX8MP_GPC_PU_PWRHSK,
314};
315
316static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
317	.domains = imx8mp_pgc_domains,
318	.domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
319	.pgc_regs = &imx8mp_pgc_regs,
320};
321#endif
322
323static int imx8m_power_domain_on(struct power_domain *power_domain)
324{
325	struct udevice *dev = power_domain->dev;
326	struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
327	const struct imx_pgc_domain *domain = pdata->domain;
328	const struct imx_pgc_regs *regs = pdata->regs;
329	void __iomem *base = pdata->base;
330	u32 pgc;
331	int ret;
332
333	if (pdata->clk.count) {
334		ret = clk_enable_bulk(&pdata->clk);
335		if (ret) {
336			dev_err(dev, "failed to enable reset clocks\n");
337			return ret;
338		}
339	}
340
341	/* delay for reset to propagate */
342	udelay(5);
343
344	if (domain->bits.pxx) {
345		/* request the domain to power up */
346		setbits_le32(base + regs->pup, domain->bits.pxx);
347
348		/*
349		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
350		 * for PUP_REQ/PDN_REQ bit to be cleared
351		 */
352		ret = wait_for_bit_le32(base + regs->pup, domain->bits.pxx,
353					false, 1000, false);
354		if (ret) {
355			dev_err(dev, "failed to command PGC\n");
356			goto out_clk_disable;
357		}
358
359		/* disable power control */
360		for_each_set_bit(pgc, &domain->pgc, 32) {
361			clrbits_le32(base + GPC_PGC_CTRL(pgc),
362				     GPC_PGC_CTRL_PCR);
363		}
364	}
365
366	/* delay for reset to propagate */
367	udelay(5);
368
369	/* request the ADB400 to power up */
370	if (domain->bits.hskreq)
371		setbits_le32(base + regs->hsk, domain->bits.hskreq);
372
373	/* Disable reset clocks for all devices in the domain */
374	if (!domain->keep_clocks && pdata->clk.count)
375		clk_disable_bulk(&pdata->clk);
376
377	return 0;
378
379out_clk_disable:
380	if (pdata->clk.count)
381		clk_disable_bulk(&pdata->clk);
382	return ret;
383}
384
385static int imx8m_power_domain_off(struct power_domain *power_domain)
386{
387	struct udevice *dev = power_domain->dev;
388	struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
389	const struct imx_pgc_domain *domain = pdata->domain;
390	const struct imx_pgc_regs *regs = pdata->regs;
391	void __iomem *base = pdata->base;
392	u32 pgc;
393	int ret;
394
395	/* Enable reset clocks for all devices in the domain */
396	if (!domain->keep_clocks && pdata->clk.count) {
397		ret = clk_enable_bulk(&pdata->clk);
398		if (ret)
399			return ret;
400	}
401
402	/* request the ADB400 to power down */
403	if (domain->bits.hskreq) {
404		clrbits_le32(base + regs->hsk, domain->bits.hskreq);
405
406		ret = wait_for_bit_le32(base + regs->hsk, domain->bits.hskack,
407					false, 1000, false);
408		if (ret) {
409			dev_err(dev, "failed to power down ADB400\n");
410			goto out_clk_disable;
411		}
412	}
413
414	if (domain->bits.pxx) {
415		/* enable power control */
416		for_each_set_bit(pgc, &domain->pgc, 32) {
417			setbits_le32(base + GPC_PGC_CTRL(pgc),
418				     GPC_PGC_CTRL_PCR);
419		}
420
421		/* request the domain to power down */
422		setbits_le32(base + regs->pdn, domain->bits.pxx);
423
424		/*
425		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
426		 * for PUP_REQ/PDN_REQ bit to be cleared
427		 */
428		ret = wait_for_bit_le32(base + regs->pdn, domain->bits.pxx,
429					false, 1000, false);
430		if (ret) {
431			dev_err(dev, "failed to command PGC\n");
432			goto out_clk_disable;
433		}
434	}
435
436	/* Disable reset clocks for all devices in the domain */
437	if (pdata->clk.count)
438		clk_disable_bulk(&pdata->clk);
439
440	if (pdata->has_pd)
441		power_domain_off(&pdata->pd);
442
443	return 0;
444
445out_clk_disable:
446	if (!domain->keep_clocks && pdata->clk.count)
447		clk_disable_bulk(&pdata->clk);
448
449	return ret;
450}
451
452static int imx8m_power_domain_of_xlate(struct power_domain *power_domain,
453				      struct ofnode_phandle_args *args)
454{
455	return 0;
456}
457
458static int imx8m_power_domain_bind(struct udevice *dev)
459{
460	int offset;
461	const char *name;
462	int ret = 0;
463
464	offset = dev_of_offset(dev);
465	for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
466	     offset = fdt_next_subnode(gd->fdt_blob, offset)) {
467		/* Bind the subnode to this driver */
468		name = fdt_get_name(gd->fdt_blob, offset, NULL);
469
470		/* Descend into 'pgc' subnode */
471		if (!strstr(name, "power-domain")) {
472			offset = fdt_first_subnode(gd->fdt_blob, offset);
473			name = fdt_get_name(gd->fdt_blob, offset, NULL);
474		}
475
476		ret = device_bind_with_driver_data(dev, dev->driver, name,
477						   dev->driver_data,
478						   offset_to_ofnode(offset),
479						   NULL);
480
481		if (ret == -ENODEV)
482			printf("Driver '%s' refuses to bind\n",
483			       dev->driver->name);
484
485		if (ret)
486			printf("Error binding driver '%s': %d\n",
487			       dev->driver->name, ret);
488	}
489
490	return 0;
491}
492
493static int imx8m_power_domain_probe(struct udevice *dev)
494{
495	struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
496	int ret;
497
498	/* Nothing to do for non-"power-domain" driver instances. */
499	if (!strstr(dev->name, "power-domain"))
500		return 0;
501
502	/* Grab optional power domain clock. */
503	ret = clk_get_bulk(dev, &pdata->clk);
504	if (ret && ret != -ENOENT) {
505		dev_err(dev, "Failed to get domain clock (%d)\n", ret);
506		return ret;
507	}
508
509	return 0;
510}
511
512static int imx8m_power_domain_of_to_plat(struct udevice *dev)
513{
514	struct imx8m_power_domain_plat *pdata = dev_get_plat(dev);
515	struct imx_pgc_domain_data *domain_data =
516		(struct imx_pgc_domain_data *)dev_get_driver_data(dev);
517
518	pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
519					    "reg", -1);
520	pdata->domain = &domain_data->domains[pdata->resource_id];
521	pdata->regs = domain_data->pgc_regs;
522	pdata->base = dev_read_addr_ptr(dev->parent);
523
524	if (!power_domain_get(dev, &pdata->pd))
525		pdata->has_pd = 1;
526
527	return 0;
528}
529
530static const struct udevice_id imx8m_power_domain_ids[] = {
531#ifdef CONFIG_IMX8MQ
532	{ .compatible = "fsl,imx8mq-gpc", .data = (long)&imx8m_pgc_domain_data },
533#endif
534#ifdef CONFIG_IMX8MM
535	{ .compatible = "fsl,imx8mm-gpc", .data = (long)&imx8mm_pgc_domain_data },
536#endif
537#ifdef CONFIG_IMX8MN
538	{ .compatible = "fsl,imx8mn-gpc", .data = (long)&imx8mn_pgc_domain_data },
539#endif
540#ifdef CONFIG_IMX8MP
541	{ .compatible = "fsl,imx8mp-gpc", .data = (long)&imx8mp_pgc_domain_data },
542#endif
543	{ }
544};
545
546struct power_domain_ops imx8m_power_domain_ops = {
547	.on = imx8m_power_domain_on,
548	.off = imx8m_power_domain_off,
549	.of_xlate = imx8m_power_domain_of_xlate,
550};
551
552U_BOOT_DRIVER(imx8m_power_domain) = {
553	.name = "imx8m_power_domain",
554	.id = UCLASS_POWER_DOMAIN,
555	.of_match = imx8m_power_domain_ids,
556	.bind = imx8m_power_domain_bind,
557	.probe = imx8m_power_domain_probe,
558	.of_to_plat = imx8m_power_domain_of_to_plat,
559	.plat_auto	= sizeof(struct imx8m_power_domain_plat),
560	.ops = &imx8m_power_domain_ops,
561};
562