2 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
3 * Copyright 2011-2013 Freescale Semiconductor, Inc.
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
13 #include <linux/clk.h>
14 #include <linux/delay.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_domain.h>
19 #include <linux/regmap.h>
20 #include <linux/regulator/consumer.h>
22 #define GPC_CNTR 0x000
24 #define GPC_PGC_CTRL_OFFS 0x0
25 #define GPC_PGC_PUPSCR_OFFS 0x4
26 #define GPC_PGC_PDNSCR_OFFS 0x8
27 #define GPC_PGC_SW2ISO_SHIFT 0x8
28 #define GPC_PGC_SW_SHIFT 0x0
30 #define GPC_PGC_PCI_PDN 0x200
31 #define GPC_PGC_PCI_SR 0x20c
33 #define GPC_PGC_GPU_PDN 0x260
34 #define GPC_PGC_GPU_PUPSCR 0x264
35 #define GPC_PGC_GPU_PDNSCR 0x268
36 #define GPC_PGC_GPU_SR 0x26c
38 #define GPC_PGC_DISP_PDN 0x240
39 #define GPC_PGC_DISP_SR 0x24c
41 #define GPU_VPU_PUP_REQ BIT(1)
42 #define GPU_VPU_PDN_REQ BIT(0)
46 #define PGC_DOMAIN_FLAG_NO_PD BIT(0)
48 struct imx_pm_domain
{
49 struct generic_pm_domain base
;
50 struct regmap
*regmap
;
51 struct regulator
*supply
;
52 struct clk
*clk
[GPC_CLK_MAX
];
54 unsigned int reg_offs
;
55 signed char cntr_pdn_bit
;
56 unsigned int ipg_rate_mhz
;
60 static inline struct imx_pm_domain
*
61 to_imx_pm_domain(struct generic_pm_domain
*genpd
)
63 return container_of(genpd
, struct imx_pm_domain
, base
);
66 static int imx6_pm_domain_power_off(struct generic_pm_domain
*genpd
)
68 struct imx_pm_domain
*pd
= to_imx_pm_domain(genpd
);
72 if (pd
->flags
& PGC_DOMAIN_FLAG_NO_PD
)
75 /* Read ISO and ISO2SW power down delays */
76 regmap_read(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_PDNSCR_OFFS
, &val
);
78 iso2sw
= (val
>> 8) & 0x3f;
80 /* Gate off domain when powered down */
81 regmap_update_bits(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_CTRL_OFFS
,
84 /* Request GPC to power down domain */
85 val
= BIT(pd
->cntr_pdn_bit
);
86 regmap_update_bits(pd
->regmap
, GPC_CNTR
, val
, val
);
88 /* Wait ISO + ISO2SW IPG clock cycles */
89 udelay(DIV_ROUND_UP(iso
+ iso2sw
, pd
->ipg_rate_mhz
));
92 regulator_disable(pd
->supply
);
97 static int imx6_pm_domain_power_on(struct generic_pm_domain
*genpd
)
99 struct imx_pm_domain
*pd
= to_imx_pm_domain(genpd
);
104 ret
= regulator_enable(pd
->supply
);
106 pr_err("%s: failed to enable regulator: %d\n",
112 /* Enable reset clocks for all devices in the domain */
113 for (i
= 0; i
< pd
->num_clks
; i
++)
114 clk_prepare_enable(pd
->clk
[i
]);
116 /* Gate off domain when powered down */
117 regmap_update_bits(pd
->regmap
, pd
->reg_offs
+ GPC_PGC_CTRL_OFFS
,
120 /* Request GPC to power up domain */
121 req
= BIT(pd
->cntr_pdn_bit
+ 1);
122 regmap_update_bits(pd
->regmap
, GPC_CNTR
, req
, req
);
124 /* Wait for the PGC to handle the request */
125 ret
= regmap_read_poll_timeout(pd
->regmap
, GPC_CNTR
, val
, !(val
& req
),
128 pr_err("powerup request on domain %s timed out\n", genpd
->name
);
130 /* Wait for reset to propagate through peripherals */
133 /* Disable reset clocks for all devices in the domain */
134 for (i
= 0; i
< pd
->num_clks
; i
++)
135 clk_disable_unprepare(pd
->clk
[i
]);
140 static int imx_pgc_get_clocks(struct device
*dev
, struct imx_pm_domain
*domain
)
145 struct clk
*clk
= of_clk_get(dev
->of_node
, i
);
148 if (i
>= GPC_CLK_MAX
) {
149 dev_err(dev
, "more than %d clocks\n", GPC_CLK_MAX
);
153 domain
->clk
[i
] = clk
;
155 domain
->num_clks
= i
;
161 clk_put(domain
->clk
[i
]);
166 static void imx_pgc_put_clocks(struct imx_pm_domain
*domain
)
170 for (i
= domain
->num_clks
- 1; i
>= 0; i
--)
171 clk_put(domain
->clk
[i
]);
174 static int imx_pgc_parse_dt(struct device
*dev
, struct imx_pm_domain
*domain
)
176 /* try to get the domain supply regulator */
177 domain
->supply
= devm_regulator_get_optional(dev
, "power");
178 if (IS_ERR(domain
->supply
)) {
179 if (PTR_ERR(domain
->supply
) == -ENODEV
)
180 domain
->supply
= NULL
;
182 return PTR_ERR(domain
->supply
);
185 /* try to get all clocks needed for reset propagation */
186 return imx_pgc_get_clocks(dev
, domain
);
189 static int imx_pgc_power_domain_probe(struct platform_device
*pdev
)
191 struct imx_pm_domain
*domain
= pdev
->dev
.platform_data
;
192 struct device
*dev
= &pdev
->dev
;
195 /* if this PD is associated with a DT node try to parse it */
197 ret
= imx_pgc_parse_dt(dev
, domain
);
202 /* initially power on the domain */
203 if (domain
->base
.power_on
)
204 domain
->base
.power_on(&domain
->base
);
206 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
207 pm_genpd_init(&domain
->base
, NULL
, false);
208 ret
= of_genpd_add_provider_simple(dev
->of_node
, &domain
->base
);
213 device_link_add(dev
, dev
->parent
, DL_FLAG_AUTOREMOVE
);
218 pm_genpd_remove(&domain
->base
);
219 imx_pgc_put_clocks(domain
);
224 static int imx_pgc_power_domain_remove(struct platform_device
*pdev
)
226 struct imx_pm_domain
*domain
= pdev
->dev
.platform_data
;
228 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
229 of_genpd_del_provider(pdev
->dev
.of_node
);
230 pm_genpd_remove(&domain
->base
);
231 imx_pgc_put_clocks(domain
);
237 static const struct platform_device_id imx_pgc_power_domain_id
[] = {
238 { "imx-pgc-power-domain"},
242 static struct platform_driver imx_pgc_power_domain_driver
= {
244 .name
= "imx-pgc-pd",
246 .probe
= imx_pgc_power_domain_probe
,
247 .remove
= imx_pgc_power_domain_remove
,
248 .id_table
= imx_pgc_power_domain_id
,
250 builtin_platform_driver(imx_pgc_power_domain_driver
)
252 #define GPC_PGC_DOMAIN_ARM 0
253 #define GPC_PGC_DOMAIN_PU 1
254 #define GPC_PGC_DOMAIN_DISPLAY 2
256 static struct genpd_power_state imx6_pm_domain_pu_state
= {
257 .power_off_latency_ns
= 25000,
258 .power_on_latency_ns
= 2000000,
261 static struct imx_pm_domain imx_gpc_domains
[] = {
269 .power_off
= imx6_pm_domain_power_off
,
270 .power_on
= imx6_pm_domain_power_on
,
271 .states
= &imx6_pm_domain_pu_state
,
279 .power_off
= imx6_pm_domain_power_off
,
280 .power_on
= imx6_pm_domain_power_on
,
287 struct imx_gpc_dt_data
{
289 bool err009619_present
;
292 static const struct imx_gpc_dt_data imx6q_dt_data
= {
294 .err009619_present
= false,
297 static const struct imx_gpc_dt_data imx6qp_dt_data
= {
299 .err009619_present
= true,
302 static const struct imx_gpc_dt_data imx6sl_dt_data
= {
304 .err009619_present
= false,
307 static const struct of_device_id imx_gpc_dt_ids
[] = {
308 { .compatible
= "fsl,imx6q-gpc", .data
= &imx6q_dt_data
},
309 { .compatible
= "fsl,imx6qp-gpc", .data
= &imx6qp_dt_data
},
310 { .compatible
= "fsl,imx6sl-gpc", .data
= &imx6sl_dt_data
},
314 static const struct regmap_range yes_ranges
[] = {
315 regmap_reg_range(GPC_CNTR
, GPC_CNTR
),
316 regmap_reg_range(GPC_PGC_PCI_PDN
, GPC_PGC_PCI_SR
),
317 regmap_reg_range(GPC_PGC_GPU_PDN
, GPC_PGC_GPU_SR
),
318 regmap_reg_range(GPC_PGC_DISP_PDN
, GPC_PGC_DISP_SR
),
321 static const struct regmap_access_table access_table
= {
322 .yes_ranges
= yes_ranges
,
323 .n_yes_ranges
= ARRAY_SIZE(yes_ranges
),
326 static const struct regmap_config imx_gpc_regmap_config
= {
330 .rd_table
= &access_table
,
331 .wr_table
= &access_table
,
332 .max_register
= 0x2ac,
336 static struct generic_pm_domain
*imx_gpc_onecell_domains
[] = {
337 &imx_gpc_domains
[0].base
,
338 &imx_gpc_domains
[1].base
,
341 static struct genpd_onecell_data imx_gpc_onecell_data
= {
342 .domains
= imx_gpc_onecell_domains
,
346 static int imx_gpc_old_dt_init(struct device
*dev
, struct regmap
*regmap
,
347 unsigned int num_domains
)
349 struct imx_pm_domain
*domain
;
352 for (i
= 0; i
< num_domains
; i
++) {
353 domain
= &imx_gpc_domains
[i
];
354 domain
->regmap
= regmap
;
355 domain
->ipg_rate_mhz
= 66;
358 domain
->supply
= devm_regulator_get(dev
, "pu");
359 if (IS_ERR(domain
->supply
))
360 return PTR_ERR(domain
->supply
);;
362 ret
= imx_pgc_get_clocks(dev
, domain
);
366 domain
->base
.power_on(&domain
->base
);
370 for (i
= 0; i
< num_domains
; i
++)
371 pm_genpd_init(&imx_gpc_domains
[i
].base
, NULL
, false);
373 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS
)) {
374 ret
= of_genpd_add_provider_onecell(dev
->of_node
,
375 &imx_gpc_onecell_data
);
383 for (i
= 0; i
< num_domains
; i
++)
384 pm_genpd_remove(&imx_gpc_domains
[i
].base
);
385 imx_pgc_put_clocks(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
]);
390 static int imx_gpc_probe(struct platform_device
*pdev
)
392 const struct of_device_id
*of_id
=
393 of_match_device(imx_gpc_dt_ids
, &pdev
->dev
);
394 const struct imx_gpc_dt_data
*of_id_data
= of_id
->data
;
395 struct device_node
*pgc_node
;
396 struct regmap
*regmap
;
397 struct resource
*res
;
401 pgc_node
= of_get_child_by_name(pdev
->dev
.of_node
, "pgc");
403 /* bail out if DT too old and doesn't provide the necessary info */
404 if (!of_property_read_bool(pdev
->dev
.of_node
, "#power-domain-cells") &&
408 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
409 base
= devm_ioremap_resource(&pdev
->dev
, res
);
411 return PTR_ERR(base
);
413 regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
, NULL
, base
,
414 &imx_gpc_regmap_config
);
415 if (IS_ERR(regmap
)) {
416 ret
= PTR_ERR(regmap
);
417 dev_err(&pdev
->dev
, "failed to init regmap: %d\n",
422 /* Disable PU power down in normal operation if ERR009619 is present */
423 if (of_id_data
->err009619_present
)
424 imx_gpc_domains
[GPC_PGC_DOMAIN_PU
].flags
|=
425 PGC_DOMAIN_FLAG_NO_PD
;
428 ret
= imx_gpc_old_dt_init(&pdev
->dev
, regmap
,
429 of_id_data
->num_domains
);
433 struct imx_pm_domain
*domain
;
434 struct platform_device
*pd_pdev
;
435 struct device_node
*np
;
437 unsigned int ipg_rate_mhz
;
440 ipg_clk
= devm_clk_get(&pdev
->dev
, "ipg");
442 return PTR_ERR(ipg_clk
);
443 ipg_rate_mhz
= clk_get_rate(ipg_clk
) / 1000000;
445 for_each_child_of_node(pgc_node
, np
) {
446 ret
= of_property_read_u32(np
, "reg", &domain_index
);
451 if (domain_index
>= of_id_data
->num_domains
)
454 domain
= &imx_gpc_domains
[domain_index
];
455 domain
->regmap
= regmap
;
456 domain
->ipg_rate_mhz
= ipg_rate_mhz
;
458 pd_pdev
= platform_device_alloc("imx-pgc-power-domain",
464 pd_pdev
->dev
.platform_data
= domain
;
465 pd_pdev
->dev
.parent
= &pdev
->dev
;
466 pd_pdev
->dev
.of_node
= np
;
468 ret
= platform_device_add(pd_pdev
);
470 platform_device_put(pd_pdev
);
480 static int imx_gpc_remove(struct platform_device
*pdev
)
482 struct device_node
*pgc_node
;
485 pgc_node
= of_get_child_by_name(pdev
->dev
.of_node
, "pgc");
487 /* bail out if DT too old and doesn't provide the necessary info */
488 if (!of_property_read_bool(pdev
->dev
.of_node
, "#power-domain-cells") &&
493 * If the old DT binding is used the toplevel driver needs to
494 * de-register the power domains
497 of_genpd_del_provider(pdev
->dev
.of_node
);
499 ret
= pm_genpd_remove(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
].base
);
502 imx_pgc_put_clocks(&imx_gpc_domains
[GPC_PGC_DOMAIN_PU
]);
504 ret
= pm_genpd_remove(&imx_gpc_domains
[GPC_PGC_DOMAIN_ARM
].base
);
512 static struct platform_driver imx_gpc_driver
= {
515 .of_match_table
= imx_gpc_dt_ids
,
517 .probe
= imx_gpc_probe
,
518 .remove
= imx_gpc_remove
,
520 builtin_platform_driver(imx_gpc_driver
)