1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2017 Impinj, Inc
4 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
6 * Based on the code of analogus driver:
8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
11 #include <linux/clk.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_domain.h>
15 #include <linux/regmap.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/sizes.h>
18 #include <dt-bindings/power/imx7-power.h>
19 #include <dt-bindings/power/imx8mq-power.h>
21 #define GPC_LPCR_A_CORE_BSC 0x000
23 #define GPC_PGC_CPU_MAPPING 0x0ec
25 #define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6)
26 #define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5)
27 #define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4)
28 #define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3)
29 #define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2)
31 #define IMX8M_PCIE2_A53_DOMAIN BIT(15)
32 #define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14)
33 #define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13)
34 #define IMX8M_DISP_A53_DOMAIN BIT(12)
35 #define IMX8M_HDMI_A53_DOMAIN BIT(11)
36 #define IMX8M_VPU_A53_DOMAIN BIT(10)
37 #define IMX8M_GPU_A53_DOMAIN BIT(9)
38 #define IMX8M_DDR2_A53_DOMAIN BIT(8)
39 #define IMX8M_DDR1_A53_DOMAIN BIT(7)
40 #define IMX8M_OTG2_A53_DOMAIN BIT(5)
41 #define IMX8M_OTG1_A53_DOMAIN BIT(4)
42 #define IMX8M_PCIE1_A53_DOMAIN BIT(3)
43 #define IMX8M_MIPI_A53_DOMAIN BIT(2)
45 #define GPC_PU_PGC_SW_PUP_REQ 0x0f8
46 #define GPC_PU_PGC_SW_PDN_REQ 0x104
48 #define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
49 #define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
50 #define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
51 #define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1)
52 #define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0)
54 #define IMX8M_PCIE2_SW_Pxx_REQ BIT(13)
55 #define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12)
56 #define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11)
57 #define IMX8M_DISP_SW_Pxx_REQ BIT(10)
58 #define IMX8M_HDMI_SW_Pxx_REQ BIT(9)
59 #define IMX8M_VPU_SW_Pxx_REQ BIT(8)
60 #define IMX8M_GPU_SW_Pxx_REQ BIT(7)
61 #define IMX8M_DDR2_SW_Pxx_REQ BIT(6)
62 #define IMX8M_DDR1_SW_Pxx_REQ BIT(5)
63 #define IMX8M_OTG2_SW_Pxx_REQ BIT(3)
64 #define IMX8M_OTG1_SW_Pxx_REQ BIT(2)
65 #define IMX8M_PCIE1_SW_Pxx_REQ BIT(1)
66 #define IMX8M_MIPI_SW_Pxx_REQ BIT(0)
68 #define GPC_M4_PU_PDN_FLG 0x1bc
70 #define GPC_PU_PWRHSK 0x1fc
72 #define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
73 #define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
74 #define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
77 * The PGC offset values in Reference Manual
78 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
79 * GPC_PGC memory map are incorrect, below offset
80 * values are from design RTL.
82 #define IMX7_PGC_MIPI 16
83 #define IMX7_PGC_PCIE 17
84 #define IMX7_PGC_USB_HSIC 20
86 #define IMX8M_PGC_MIPI 16
87 #define IMX8M_PGC_PCIE1 17
88 #define IMX8M_PGC_OTG1 18
89 #define IMX8M_PGC_OTG2 19
90 #define IMX8M_PGC_DDR1 21
91 #define IMX8M_PGC_GPU 23
92 #define IMX8M_PGC_VPU 24
93 #define IMX8M_PGC_DISP 26
94 #define IMX8M_PGC_MIPI_CSI1 27
95 #define IMX8M_PGC_MIPI_CSI2 28
96 #define IMX8M_PGC_PCIE2 29
98 #define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
99 #define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
101 #define GPC_PGC_CTRL_PCR BIT(0)
103 #define GPC_CLK_MAX 6
105 struct imx_pgc_domain
{
106 struct generic_pm_domain genpd
;
107 struct regmap
*regmap
;
108 struct regulator
*regulator
;
109 struct clk
*clk
[GPC_CLK_MAX
];
124 struct imx_pgc_domain_data
{
125 const struct imx_pgc_domain
*domains
;
127 const struct regmap_access_table
*reg_access_table
;
130 static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain
*genpd
,
133 struct imx_pgc_domain
*domain
= container_of(genpd
,
134 struct imx_pgc_domain
,
136 unsigned int offset
= on
?
137 GPC_PU_PGC_SW_PUP_REQ
: GPC_PU_PGC_SW_PDN_REQ
;
138 const bool enable_power_control
= !on
;
139 const bool has_regulator
= !IS_ERR(domain
->regulator
);
143 regmap_update_bits(domain
->regmap
, GPC_PGC_CPU_MAPPING
,
144 domain
->bits
.map
, domain
->bits
.map
);
146 if (has_regulator
&& on
) {
147 ret
= regulator_enable(domain
->regulator
);
149 dev_err(domain
->dev
, "failed to enable regulator\n");
154 /* Enable reset clocks for all devices in the domain */
155 for (i
= 0; i
< domain
->num_clks
; i
++)
156 clk_prepare_enable(domain
->clk
[i
]);
158 if (enable_power_control
)
159 regmap_update_bits(domain
->regmap
, GPC_PGC_CTRL(domain
->pgc
),
160 GPC_PGC_CTRL_PCR
, GPC_PGC_CTRL_PCR
);
162 if (domain
->bits
.hsk
)
163 regmap_update_bits(domain
->regmap
, GPC_PU_PWRHSK
,
164 domain
->bits
.hsk
, on
? domain
->bits
.hsk
: 0);
166 regmap_update_bits(domain
->regmap
, offset
,
167 domain
->bits
.pxx
, domain
->bits
.pxx
);
170 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
171 * for PUP_REQ/PDN_REQ bit to be cleared
173 ret
= regmap_read_poll_timeout(domain
->regmap
, offset
, pxx_req
,
174 !(pxx_req
& domain
->bits
.pxx
),
177 dev_err(domain
->dev
, "failed to command PGC\n");
179 * If we were in a process of enabling a
180 * domain and failed we might as well disable
181 * the regulator we just enabled. And if it
182 * was the opposite situation and we failed to
183 * power down -- keep the regulator on
188 if (enable_power_control
)
189 regmap_update_bits(domain
->regmap
, GPC_PGC_CTRL(domain
->pgc
),
190 GPC_PGC_CTRL_PCR
, 0);
192 /* Disable reset clocks for all devices in the domain */
193 for (i
= 0; i
< domain
->num_clks
; i
++)
194 clk_disable_unprepare(domain
->clk
[i
]);
196 if (has_regulator
&& !on
) {
199 err
= regulator_disable(domain
->regulator
);
202 "failed to disable regulator: %d\n", err
);
203 /* Preserve earlier error code */
207 regmap_update_bits(domain
->regmap
, GPC_PGC_CPU_MAPPING
,
208 domain
->bits
.map
, 0);
212 static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain
*genpd
)
214 return imx_gpc_pu_pgc_sw_pxx_req(genpd
, true);
217 static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain
*genpd
)
219 return imx_gpc_pu_pgc_sw_pxx_req(genpd
, false);
222 static const struct imx_pgc_domain imx7_pgc_domains
[] = {
223 [IMX7_POWER_DOMAIN_MIPI_PHY
] = {
228 .pxx
= IMX7_MIPI_PHY_SW_Pxx_REQ
,
229 .map
= IMX7_MIPI_PHY_A_CORE_DOMAIN
,
232 .pgc
= IMX7_PGC_MIPI
,
235 [IMX7_POWER_DOMAIN_PCIE_PHY
] = {
240 .pxx
= IMX7_PCIE_PHY_SW_Pxx_REQ
,
241 .map
= IMX7_PCIE_PHY_A_CORE_DOMAIN
,
244 .pgc
= IMX7_PGC_PCIE
,
247 [IMX7_POWER_DOMAIN_USB_HSIC_PHY
] = {
249 .name
= "usb-hsic-phy",
252 .pxx
= IMX7_USB_HSIC_PHY_SW_Pxx_REQ
,
253 .map
= IMX7_USB_HSIC_PHY_A_CORE_DOMAIN
,
256 .pgc
= IMX7_PGC_USB_HSIC
,
260 static const struct regmap_range imx7_yes_ranges
[] = {
261 regmap_reg_range(GPC_LPCR_A_CORE_BSC
,
263 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI
),
264 GPC_PGC_SR(IMX7_PGC_MIPI
)),
265 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE
),
266 GPC_PGC_SR(IMX7_PGC_PCIE
)),
267 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC
),
268 GPC_PGC_SR(IMX7_PGC_USB_HSIC
)),
271 static const struct regmap_access_table imx7_access_table
= {
272 .yes_ranges
= imx7_yes_ranges
,
273 .n_yes_ranges
= ARRAY_SIZE(imx7_yes_ranges
),
276 static const struct imx_pgc_domain_data imx7_pgc_domain_data
= {
277 .domains
= imx7_pgc_domains
,
278 .domains_num
= ARRAY_SIZE(imx7_pgc_domains
),
279 .reg_access_table
= &imx7_access_table
,
282 static const struct imx_pgc_domain imx8m_pgc_domains
[] = {
283 [IMX8M_POWER_DOMAIN_MIPI
] = {
288 .pxx
= IMX8M_MIPI_SW_Pxx_REQ
,
289 .map
= IMX8M_MIPI_A53_DOMAIN
,
291 .pgc
= IMX8M_PGC_MIPI
,
294 [IMX8M_POWER_DOMAIN_PCIE1
] = {
299 .pxx
= IMX8M_PCIE1_SW_Pxx_REQ
,
300 .map
= IMX8M_PCIE1_A53_DOMAIN
,
302 .pgc
= IMX8M_PGC_PCIE1
,
305 [IMX8M_POWER_DOMAIN_USB_OTG1
] = {
310 .pxx
= IMX8M_OTG1_SW_Pxx_REQ
,
311 .map
= IMX8M_OTG1_A53_DOMAIN
,
313 .pgc
= IMX8M_PGC_OTG1
,
316 [IMX8M_POWER_DOMAIN_USB_OTG2
] = {
321 .pxx
= IMX8M_OTG2_SW_Pxx_REQ
,
322 .map
= IMX8M_OTG2_A53_DOMAIN
,
324 .pgc
= IMX8M_PGC_OTG2
,
327 [IMX8M_POWER_DOMAIN_DDR1
] = {
332 .pxx
= IMX8M_DDR1_SW_Pxx_REQ
,
333 .map
= IMX8M_DDR2_A53_DOMAIN
,
335 .pgc
= IMX8M_PGC_DDR1
,
338 [IMX8M_POWER_DOMAIN_GPU
] = {
343 .pxx
= IMX8M_GPU_SW_Pxx_REQ
,
344 .map
= IMX8M_GPU_A53_DOMAIN
,
345 .hsk
= IMX8M_GPU_HSK_PWRDNREQN
,
347 .pgc
= IMX8M_PGC_GPU
,
350 [IMX8M_POWER_DOMAIN_VPU
] = {
355 .pxx
= IMX8M_VPU_SW_Pxx_REQ
,
356 .map
= IMX8M_VPU_A53_DOMAIN
,
357 .hsk
= IMX8M_VPU_HSK_PWRDNREQN
,
359 .pgc
= IMX8M_PGC_VPU
,
362 [IMX8M_POWER_DOMAIN_DISP
] = {
367 .pxx
= IMX8M_DISP_SW_Pxx_REQ
,
368 .map
= IMX8M_DISP_A53_DOMAIN
,
369 .hsk
= IMX8M_DISP_HSK_PWRDNREQN
,
371 .pgc
= IMX8M_PGC_DISP
,
374 [IMX8M_POWER_DOMAIN_MIPI_CSI1
] = {
379 .pxx
= IMX8M_MIPI_CSI1_SW_Pxx_REQ
,
380 .map
= IMX8M_MIPI_CSI1_A53_DOMAIN
,
382 .pgc
= IMX8M_PGC_MIPI_CSI1
,
385 [IMX8M_POWER_DOMAIN_MIPI_CSI2
] = {
390 .pxx
= IMX8M_MIPI_CSI2_SW_Pxx_REQ
,
391 .map
= IMX8M_MIPI_CSI2_A53_DOMAIN
,
393 .pgc
= IMX8M_PGC_MIPI_CSI2
,
396 [IMX8M_POWER_DOMAIN_PCIE2
] = {
401 .pxx
= IMX8M_PCIE2_SW_Pxx_REQ
,
402 .map
= IMX8M_PCIE2_A53_DOMAIN
,
404 .pgc
= IMX8M_PGC_PCIE2
,
408 static const struct regmap_range imx8m_yes_ranges
[] = {
409 regmap_reg_range(GPC_LPCR_A_CORE_BSC
,
411 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI
),
412 GPC_PGC_SR(IMX8M_PGC_MIPI
)),
413 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1
),
414 GPC_PGC_SR(IMX8M_PGC_PCIE1
)),
415 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1
),
416 GPC_PGC_SR(IMX8M_PGC_OTG1
)),
417 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2
),
418 GPC_PGC_SR(IMX8M_PGC_OTG2
)),
419 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1
),
420 GPC_PGC_SR(IMX8M_PGC_DDR1
)),
421 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU
),
422 GPC_PGC_SR(IMX8M_PGC_GPU
)),
423 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU
),
424 GPC_PGC_SR(IMX8M_PGC_VPU
)),
425 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP
),
426 GPC_PGC_SR(IMX8M_PGC_DISP
)),
427 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1
),
428 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1
)),
429 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2
),
430 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2
)),
431 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2
),
432 GPC_PGC_SR(IMX8M_PGC_PCIE2
)),
435 static const struct regmap_access_table imx8m_access_table
= {
436 .yes_ranges
= imx8m_yes_ranges
,
437 .n_yes_ranges
= ARRAY_SIZE(imx8m_yes_ranges
),
440 static const struct imx_pgc_domain_data imx8m_pgc_domain_data
= {
441 .domains
= imx8m_pgc_domains
,
442 .domains_num
= ARRAY_SIZE(imx8m_pgc_domains
),
443 .reg_access_table
= &imx8m_access_table
,
446 static int imx_pgc_get_clocks(struct imx_pgc_domain
*domain
)
451 struct clk
*clk
= of_clk_get(domain
->dev
->of_node
, i
);
454 if (i
>= GPC_CLK_MAX
) {
455 dev_err(domain
->dev
, "more than %d clocks\n",
460 domain
->clk
[i
] = clk
;
462 domain
->num_clks
= i
;
468 clk_put(domain
->clk
[i
]);
473 static void imx_pgc_put_clocks(struct imx_pgc_domain
*domain
)
477 for (i
= domain
->num_clks
- 1; i
>= 0; i
--)
478 clk_put(domain
->clk
[i
]);
481 static int imx_pgc_domain_probe(struct platform_device
*pdev
)
483 struct imx_pgc_domain
*domain
= pdev
->dev
.platform_data
;
486 domain
->dev
= &pdev
->dev
;
488 domain
->regulator
= devm_regulator_get_optional(domain
->dev
, "power");
489 if (IS_ERR(domain
->regulator
)) {
490 if (PTR_ERR(domain
->regulator
) != -ENODEV
)
491 return dev_err_probe(domain
->dev
, PTR_ERR(domain
->regulator
),
492 "Failed to get domain's regulator\n");
493 } else if (domain
->voltage
) {
494 regulator_set_voltage(domain
->regulator
,
495 domain
->voltage
, domain
->voltage
);
498 ret
= imx_pgc_get_clocks(domain
);
500 return dev_err_probe(domain
->dev
, ret
, "Failed to get domain's clocks\n");
502 ret
= pm_genpd_init(&domain
->genpd
, NULL
, true);
504 dev_err(domain
->dev
, "Failed to init power domain\n");
505 imx_pgc_put_clocks(domain
);
509 ret
= of_genpd_add_provider_simple(domain
->dev
->of_node
,
512 dev_err(domain
->dev
, "Failed to add genpd provider\n");
513 pm_genpd_remove(&domain
->genpd
);
514 imx_pgc_put_clocks(domain
);
520 static int imx_pgc_domain_remove(struct platform_device
*pdev
)
522 struct imx_pgc_domain
*domain
= pdev
->dev
.platform_data
;
524 of_genpd_del_provider(domain
->dev
->of_node
);
525 pm_genpd_remove(&domain
->genpd
);
526 imx_pgc_put_clocks(domain
);
531 static const struct platform_device_id imx_pgc_domain_id
[] = {
532 { "imx-pgc-domain", },
536 static struct platform_driver imx_pgc_domain_driver
= {
540 .probe
= imx_pgc_domain_probe
,
541 .remove
= imx_pgc_domain_remove
,
542 .id_table
= imx_pgc_domain_id
,
544 builtin_platform_driver(imx_pgc_domain_driver
)
546 static int imx_gpcv2_probe(struct platform_device
*pdev
)
548 const struct imx_pgc_domain_data
*domain_data
=
549 of_device_get_match_data(&pdev
->dev
);
551 struct regmap_config regmap_config
= {
555 .rd_table
= domain_data
->reg_access_table
,
556 .wr_table
= domain_data
->reg_access_table
,
557 .max_register
= SZ_4K
,
559 struct device
*dev
= &pdev
->dev
;
560 struct device_node
*pgc_np
, *np
;
561 struct regmap
*regmap
;
565 pgc_np
= of_get_child_by_name(dev
->of_node
, "pgc");
567 dev_err(dev
, "No power domains specified in DT\n");
571 base
= devm_platform_ioremap_resource(pdev
, 0);
573 return PTR_ERR(base
);
575 regmap
= devm_regmap_init_mmio(dev
, base
, ®map_config
);
576 if (IS_ERR(regmap
)) {
577 ret
= PTR_ERR(regmap
);
578 dev_err(dev
, "failed to init regmap (%d)\n", ret
);
582 for_each_child_of_node(pgc_np
, np
) {
583 struct platform_device
*pd_pdev
;
584 struct imx_pgc_domain
*domain
;
587 ret
= of_property_read_u32(np
, "reg", &domain_index
);
589 dev_err(dev
, "Failed to read 'reg' property\n");
594 if (domain_index
>= domain_data
->domains_num
) {
596 "Domain index %d is out of bounds\n",
601 pd_pdev
= platform_device_alloc("imx-pgc-domain",
604 dev_err(dev
, "Failed to allocate platform device\n");
609 ret
= platform_device_add_data(pd_pdev
,
610 &domain_data
->domains
[domain_index
],
611 sizeof(domain_data
->domains
[domain_index
]));
613 platform_device_put(pd_pdev
);
618 domain
= pd_pdev
->dev
.platform_data
;
619 domain
->regmap
= regmap
;
620 domain
->genpd
.power_on
= imx_gpc_pu_pgc_sw_pup_req
;
621 domain
->genpd
.power_off
= imx_gpc_pu_pgc_sw_pdn_req
;
623 pd_pdev
->dev
.parent
= dev
;
624 pd_pdev
->dev
.of_node
= np
;
626 ret
= platform_device_add(pd_pdev
);
628 platform_device_put(pd_pdev
);
637 static const struct of_device_id imx_gpcv2_dt_ids
[] = {
638 { .compatible
= "fsl,imx7d-gpc", .data
= &imx7_pgc_domain_data
, },
639 { .compatible
= "fsl,imx8mq-gpc", .data
= &imx8m_pgc_domain_data
, },
643 static struct platform_driver imx_gpc_driver
= {
646 .of_match_table
= imx_gpcv2_dt_ids
,
648 .probe
= imx_gpcv2_probe
,
650 builtin_platform_driver(imx_gpc_driver
)