1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
4 * Copyright 2011-2013 Freescale Semiconductor, Inc.
8 #include <linux/delay.h>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_domain.h>
13 #include <linux/regmap.h>
14 #include <linux/regulator/consumer.h>
16 #define GPC_CNTR 0x000
18 #define GPC_PGC_CTRL_OFFS 0x0
19 #define GPC_PGC_PUPSCR_OFFS 0x4
20 #define GPC_PGC_PDNSCR_OFFS 0x8
21 #define GPC_PGC_SW2ISO_SHIFT 0x8
22 #define GPC_PGC_SW_SHIFT 0x0
24 #define GPC_PGC_PCI_PDN 0x200
25 #define GPC_PGC_PCI_SR 0x20c
27 #define GPC_PGC_GPU_PDN 0x260
28 #define GPC_PGC_GPU_PUPSCR 0x264
29 #define GPC_PGC_GPU_PDNSCR 0x268
30 #define GPC_PGC_GPU_SR 0x26c
32 #define GPC_PGC_DISP_PDN 0x240
33 #define GPC_PGC_DISP_SR 0x24c
35 #define GPU_VPU_PUP_REQ BIT(1)
36 #define GPU_VPU_PDN_REQ BIT(0)
40 #define PGC_DOMAIN_FLAG_NO_PD BIT(0)
42 struct imx_pm_domain
{
43 struct generic_pm_domain base
;
44 struct regmap
*regmap
;
45 struct regulator
*supply
;
46 struct clk
*clk
[GPC_CLK_MAX
];
48 unsigned int reg_offs
;
49 signed char cntr_pdn_bit
;
50 unsigned int ipg_rate_mhz
;
53 static inline struct imx_pm_domain
*
54 to_imx_pm_domain(struct generic_pm_domain
*genpd
)
56 return container_of(genpd
, struct imx_pm_domain
, base
);
59 static int imx6_pm_domain_power_off(struct generic_pm_domain
*genpd
)
61 struct imx_pm_domain
*pd
= to_imx_pm_domain(genpd
);
65 /* Read ISO and ISO2SW power down delays */
66 regmap_read(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_PDNSCR_OFFS
, &val
);
68 iso2sw
= (val
>> 8) & 0x3f;
70 /* Gate off domain when powered down */
71 regmap_update_bits(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_CTRL_OFFS
,
74 /* Request GPC to power down domain */
75 val
= BIT(pd
->cntr_pdn_bit
);
76 regmap_update_bits(pd
->regmap
, GPC_CNTR
, val
, val
);
78 /* Wait ISO + ISO2SW IPG clock cycles */
79 udelay(DIV_ROUND_UP(iso
+ iso2sw
, pd
->ipg_rate_mhz
));
82 regulator_disable(pd
->supply
);
87 static int imx6_pm_domain_power_on(struct generic_pm_domain
*genpd
)
89 struct imx_pm_domain
*pd
= to_imx_pm_domain(genpd
);
94 ret
= regulator_enable(pd
->supply
);
96 pr_err("%s: failed to enable regulator: %d\n",
102 /* Enable reset clocks for all devices in the domain */
103 for (i
= 0; i
< pd
->num_clks
; i
++)
104 clk_prepare_enable(pd
->clk
[i
]);
106 /* Gate off domain when powered down */
107 regmap_update_bits(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_CTRL_OFFS
,
110 /* Request GPC to power up domain */
111 req
= BIT(pd
->cntr_pdn_bit
+ 1);
112 regmap_update_bits(pd
->regmap
, GPC_CNTR
, req
, req
);
114 /* Wait for the PGC to handle the request */
115 ret
= regmap_read_poll_timeout(pd
->regmap
, GPC_CNTR
, val
, !(val
& req
),
118 pr_err("powerup request on domain %s timed out\n", genpd
->name
);
120 /* Wait for reset to propagate through peripherals */
123 /* Disable reset clocks for all devices in the domain */
124 for (i
= 0; i
< pd
->num_clks
; i
++)
125 clk_disable_unprepare(pd
->clk
[i
]);
130 static int imx_pgc_get_clocks(struct device
*dev
, struct imx_pm_domain
*domain
)
135 struct clk
*clk
= of_clk_get(dev
->of_node
, i
);
138 if (i
>= GPC_CLK_MAX
) {
139 dev_err(dev
, "more than %d clocks\n", GPC_CLK_MAX
);
143 domain
->clk
[i
] = clk
;
145 domain
->num_clks
= i
;
151 clk_put(domain
->clk
[i
]);
156 static void imx_pgc_put_clocks(struct imx_pm_domain
*domain
)
160 for (i
= domain
->num_clks
- 1; i
>= 0; i
--)
161 clk_put(domain
->clk
[i
]);
164 static int imx_pgc_parse_dt(struct device
*dev
, struct imx_pm_domain
*domain
)
166 /* try to get the domain supply regulator */
167 domain
->supply
= devm_regulator_get_optional(dev
, "power");
168 if (IS_ERR(domain
->supply
)) {
169 if (PTR_ERR(domain
->supply
) == -ENODEV
)
170 domain
->supply
= NULL
;
172 return PTR_ERR(domain
->supply
);
175 /* try to get all clocks needed for reset propagation */
176 return imx_pgc_get_clocks(dev
, domain
);
179 static int imx_pgc_power_domain_probe(struct platform_device
*pdev
)
181 struct imx_pm_domain
*domain
= pdev
->dev
.platform_data
;
182 struct device
*dev
= &pdev
->dev
;
185 /* if this PD is associated with a DT node try to parse it */
187 ret
= imx_pgc_parse_dt(dev
, domain
);
192 /* initially power on the domain */
193 if (domain
->base
.power_on
)
194 domain
->base
.power_on(&domain
->base
);
196 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
197 pm_genpd_init(&domain
->base
, NULL
, false);
198 ret
= of_genpd_add_provider_simple(dev
->of_node
, &domain
->base
);
203 device_link_add(dev
, dev
->parent
, DL_FLAG_AUTOREMOVE_CONSUMER
);
208 pm_genpd_remove(&domain
->base
);
209 imx_pgc_put_clocks(domain
);
214 static int imx_pgc_power_domain_remove(struct platform_device
*pdev
)
216 struct imx_pm_domain
*domain
= pdev
->dev
.platform_data
;
218 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
219 of_genpd_del_provider(pdev
->dev
.of_node
);
220 pm_genpd_remove(&domain
->base
);
221 imx_pgc_put_clocks(domain
);
227 static const struct platform_device_id imx_pgc_power_domain_id
[] = {
228 { "imx-pgc-power-domain"},
232 static struct platform_driver imx_pgc_power_domain_driver
= {
234 .name
= "imx-pgc-pd",
236 .probe
= imx_pgc_power_domain_probe
,
237 .remove
= imx_pgc_power_domain_remove
,
238 .id_table
= imx_pgc_power_domain_id
,
240 builtin_platform_driver(imx_pgc_power_domain_driver
)
242 #define GPC_PGC_DOMAIN_ARM 0
243 #define GPC_PGC_DOMAIN_PU 1
244 #define GPC_PGC_DOMAIN_DISPLAY 2
245 #define GPC_PGC_DOMAIN_PCI 3
247 static struct genpd_power_state imx6_pm_domain_pu_state
= {
248 .power_off_latency_ns
= 25000,
249 .power_on_latency_ns
= 2000000,
252 static struct imx_pm_domain imx_gpc_domains
[] = {
253 [GPC_PGC_DOMAIN_ARM
] = {
256 .flags
= GENPD_FLAG_ALWAYS_ON
,
259 [GPC_PGC_DOMAIN_PU
] = {
262 .power_off
= imx6_pm_domain_power_off
,
263 .power_on
= imx6_pm_domain_power_on
,
264 .states
= &imx6_pm_domain_pu_state
,
270 [GPC_PGC_DOMAIN_DISPLAY
] = {
273 .power_off
= imx6_pm_domain_power_off
,
274 .power_on
= imx6_pm_domain_power_on
,
279 [GPC_PGC_DOMAIN_PCI
] = {
282 .power_off
= imx6_pm_domain_power_off
,
283 .power_on
= imx6_pm_domain_power_on
,
290 struct imx_gpc_dt_data
{
292 bool err009619_present
;
293 bool err006287_present
;
296 static const struct imx_gpc_dt_data imx6q_dt_data
= {
298 .err009619_present
= false,
299 .err006287_present
= false,
302 static const struct imx_gpc_dt_data imx6qp_dt_data
= {
304 .err009619_present
= true,
305 .err006287_present
= false,
308 static const struct imx_gpc_dt_data imx6sl_dt_data
= {
310 .err009619_present
= false,
311 .err006287_present
= true,
314 static const struct imx_gpc_dt_data imx6sx_dt_data
= {
316 .err009619_present
= false,
317 .err006287_present
= false,
320 static const struct of_device_id imx_gpc_dt_ids
[] = {
321 { .compatible
= "fsl,imx6q-gpc", .data
= &imx6q_dt_data
},
322 { .compatible
= "fsl,imx6qp-gpc", .data
= &imx6qp_dt_data
},
323 { .compatible
= "fsl,imx6sl-gpc", .data
= &imx6sl_dt_data
},
324 { .compatible
= "fsl,imx6sx-gpc", .data
= &imx6sx_dt_data
},
328 static const struct regmap_range yes_ranges
[] = {
329 regmap_reg_range(GPC_CNTR
, GPC_CNTR
),
330 regmap_reg_range(GPC_PGC_PCI_PDN
, GPC_PGC_PCI_SR
),
331 regmap_reg_range(GPC_PGC_GPU_PDN
, GPC_PGC_GPU_SR
),
332 regmap_reg_range(GPC_PGC_DISP_PDN
, GPC_PGC_DISP_SR
),
335 static const struct regmap_access_table access_table
= {
336 .yes_ranges
= yes_ranges
,
337 .n_yes_ranges
= ARRAY_SIZE(yes_ranges
),
340 static const struct regmap_config imx_gpc_regmap_config
= {
344 .rd_table
= &access_table
,
345 .wr_table
= &access_table
,
346 .max_register
= 0x2ac,
350 static struct generic_pm_domain
*imx_gpc_onecell_domains
[] = {
351 &imx_gpc_domains
[GPC_PGC_DOMAIN_ARM
].base
,
352 &imx_gpc_domains
[GPC_PGC_DOMAIN_PU
].base
,
355 static struct genpd_onecell_data imx_gpc_onecell_data
= {
356 .domains
= imx_gpc_onecell_domains
,
360 static int imx_gpc_old_dt_init(struct device
*dev
, struct regmap
*regmap
,
361 unsigned int num_domains
)
363 struct imx_pm_domain
*domain
;
366 for (i
= 0; i
< num_domains
; i
++) {
367 domain
= &imx_gpc_domains
[i
];
368 domain
->regmap
= regmap
;
369 domain
->ipg_rate_mhz
= 66;
372 domain
->supply
= devm_regulator_get(dev
, "pu");
373 if (IS_ERR(domain
->supply
))
374 return PTR_ERR(domain
->supply
);
376 ret
= imx_pgc_get_clocks(dev
, domain
);
380 domain
->base
.power_on(&domain
->base
);
384 for (i
= 0; i
< num_domains
; i
++)
385 pm_genpd_init(&imx_gpc_domains
[i
].base
, NULL
, false);
387 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
388 ret
= of_genpd_add_provider_onecell(dev
->of_node
,
389 &imx_gpc_onecell_data
);
397 for (i
= 0; i
< num_domains
; i
++)
398 pm_genpd_remove(&imx_gpc_domains
[i
].base
);
399 imx_pgc_put_clocks(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
]);
404 static int imx_gpc_probe(struct platform_device
*pdev
)
406 const struct of_device_id
*of_id
=
407 of_match_device(imx_gpc_dt_ids
, &pdev
->dev
);
408 const struct imx_gpc_dt_data
*of_id_data
= of_id
->data
;
409 struct device_node
*pgc_node
;
410 struct regmap
*regmap
;
414 pgc_node
= of_get_child_by_name(pdev
->dev
.of_node
, "pgc");
416 /* bail out if DT too old and doesn't provide the necessary info */
417 if (!of_property_read_bool(pdev
->dev
.of_node
, "#power-domain-cells") &&
421 base
= devm_platform_ioremap_resource(pdev
, 0);
423 return PTR_ERR(base
);
425 regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
, NULL
, base
,
426 &imx_gpc_regmap_config
);
427 if (IS_ERR(regmap
)) {
428 ret
= PTR_ERR(regmap
);
429 dev_err(&pdev
->dev
, "failed to init regmap: %d\n",
435 * Disable PU power down by runtime PM if ERR009619 is present.
437 * The PRE clock will be paused for several cycles when turning on the
438 * PU domain LDO from power down state. If PRE is in use at that time,
439 * the IPU/PRG cannot get the correct display data from the PRE.
441 * This is not a concern when the whole system enters suspend state, so
442 * it's safe to power down PU in this case.
444 if (of_id_data
->err009619_present
)
445 imx_gpc_domains
[GPC_PGC_DOMAIN_PU
].base
.flags
|=
446 GENPD_FLAG_RPM_ALWAYS_ON
;
448 /* Keep DISP always on if ERR006287 is present */
449 if (of_id_data
->err006287_present
)
450 imx_gpc_domains
[GPC_PGC_DOMAIN_DISPLAY
].base
.flags
|=
451 GENPD_FLAG_ALWAYS_ON
;
454 ret
= imx_gpc_old_dt_init(&pdev
->dev
, regmap
,
455 of_id_data
->num_domains
);
459 struct imx_pm_domain
*domain
;
460 struct platform_device
*pd_pdev
;
461 struct device_node
*np
;
463 unsigned int ipg_rate_mhz
;
466 ipg_clk
= devm_clk_get(&pdev
->dev
, "ipg");
468 return PTR_ERR(ipg_clk
);
469 ipg_rate_mhz
= clk_get_rate(ipg_clk
) / 1000000;
471 for_each_child_of_node(pgc_node
, np
) {
472 ret
= of_property_read_u32(np
, "reg", &domain_index
);
477 if (domain_index
>= of_id_data
->num_domains
)
480 pd_pdev
= platform_device_alloc("imx-pgc-power-domain",
487 ret
= platform_device_add_data(pd_pdev
,
488 &imx_gpc_domains
[domain_index
],
489 sizeof(imx_gpc_domains
[domain_index
]));
491 platform_device_put(pd_pdev
);
495 domain
= pd_pdev
->dev
.platform_data
;
496 domain
->regmap
= regmap
;
497 domain
->ipg_rate_mhz
= ipg_rate_mhz
;
499 pd_pdev
->dev
.parent
= &pdev
->dev
;
500 pd_pdev
->dev
.of_node
= np
;
502 ret
= platform_device_add(pd_pdev
);
504 platform_device_put(pd_pdev
);
514 static int imx_gpc_remove(struct platform_device
*pdev
)
516 struct device_node
*pgc_node
;
519 pgc_node
= of_get_child_by_name(pdev
->dev
.of_node
, "pgc");
521 /* bail out if DT too old and doesn't provide the necessary info */
522 if (!of_property_read_bool(pdev
->dev
.of_node
, "#power-domain-cells") &&
527 * If the old DT binding is used the toplevel driver needs to
528 * de-register the power domains
531 of_genpd_del_provider(pdev
->dev
.of_node
);
533 ret
= pm_genpd_remove(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
].base
);
536 imx_pgc_put_clocks(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
]);
538 ret
= pm_genpd_remove(&imx_gpc_domains
[GPC_PGC_DOMAIN_ARM
].base
);
546 static struct platform_driver imx_gpc_driver
= {
549 .of_match_table
= imx_gpc_dt_ids
,
551 .probe
= imx_gpc_probe
,
552 .remove
= imx_gpc_remove
,
554 builtin_platform_driver(imx_gpc_driver
)