Loading...
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2017 Impinj, Inc
4 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
5 *
6 * Based on the code of analogus driver:
7 *
8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
9 */
10
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>
20
21#define GPC_LPCR_A_CORE_BSC 0x000
22
23#define GPC_PGC_CPU_MAPPING 0x0ec
24
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)
30
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)
44
45#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
46#define GPC_PU_PGC_SW_PDN_REQ 0x104
47
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)
53
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)
67
68#define GPC_M4_PU_PDN_FLG 0x1bc
69
70#define GPC_PU_PWRHSK 0x1fc
71
72#define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
73#define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
74#define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
75
76/*
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.
81 */
82#define IMX7_PGC_MIPI 16
83#define IMX7_PGC_PCIE 17
84#define IMX7_PGC_USB_HSIC 20
85
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
97
98#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
99#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
100
101#define GPC_PGC_CTRL_PCR BIT(0)
102
103#define GPC_CLK_MAX 6
104
105struct imx_pgc_domain {
106 struct generic_pm_domain genpd;
107 struct regmap *regmap;
108 struct regulator *regulator;
109 struct clk *clk[GPC_CLK_MAX];
110 int num_clks;
111
112 unsigned int pgc;
113
114 const struct {
115 u32 pxx;
116 u32 map;
117 u32 hsk;
118 } bits;
119
120 const int voltage;
121 struct device *dev;
122};
123
124struct imx_pgc_domain_data {
125 const struct imx_pgc_domain *domains;
126 size_t domains_num;
127 const struct regmap_access_table *reg_access_table;
128};
129
130static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
131 bool on)
132{
133 struct imx_pgc_domain *domain = container_of(genpd,
134 struct imx_pgc_domain,
135 genpd);
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);
140 int i, ret = 0;
141 u32 pxx_req;
142
143 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
144 domain->bits.map, domain->bits.map);
145
146 if (has_regulator && on) {
147 ret = regulator_enable(domain->regulator);
148 if (ret) {
149 dev_err(domain->dev, "failed to enable regulator\n");
150 goto unmap;
151 }
152 }
153
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]);
157
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);
161
162 if (domain->bits.hsk)
163 regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
164 domain->bits.hsk, on ? domain->bits.hsk : 0);
165
166 regmap_update_bits(domain->regmap, offset,
167 domain->bits.pxx, domain->bits.pxx);
168
169 /*
170 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
171 * for PUP_REQ/PDN_REQ bit to be cleared
172 */
173 ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req,
174 !(pxx_req & domain->bits.pxx),
175 0, USEC_PER_MSEC);
176 if (ret) {
177 dev_err(domain->dev, "failed to command PGC\n");
178 /*
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
184 */
185 on = !on;
186 }
187
188 if (enable_power_control)
189 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
190 GPC_PGC_CTRL_PCR, 0);
191
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]);
195
196 if (has_regulator && !on) {
197 int err;
198
199 err = regulator_disable(domain->regulator);
200 if (err)
201 dev_err(domain->dev,
202 "failed to disable regulator: %d\n", err);
203 /* Preserve earlier error code */
204 ret = ret ?: err;
205 }
206unmap:
207 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
208 domain->bits.map, 0);
209 return ret;
210}
211
212static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
213{
214 return imx_gpc_pu_pgc_sw_pxx_req(genpd, true);
215}
216
217static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
218{
219 return imx_gpc_pu_pgc_sw_pxx_req(genpd, false);
220}
221
222static const struct imx_pgc_domain imx7_pgc_domains[] = {
223 [IMX7_POWER_DOMAIN_MIPI_PHY] = {
224 .genpd = {
225 .name = "mipi-phy",
226 },
227 .bits = {
228 .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
229 .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
230 },
231 .voltage = 1000000,
232 .pgc = IMX7_PGC_MIPI,
233 },
234
235 [IMX7_POWER_DOMAIN_PCIE_PHY] = {
236 .genpd = {
237 .name = "pcie-phy",
238 },
239 .bits = {
240 .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
241 .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
242 },
243 .voltage = 1000000,
244 .pgc = IMX7_PGC_PCIE,
245 },
246
247 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
248 .genpd = {
249 .name = "usb-hsic-phy",
250 },
251 .bits = {
252 .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
253 .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
254 },
255 .voltage = 1200000,
256 .pgc = IMX7_PGC_USB_HSIC,
257 },
258};
259
260static const struct regmap_range imx7_yes_ranges[] = {
261 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
262 GPC_M4_PU_PDN_FLG),
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)),
269};
270
271static const struct regmap_access_table imx7_access_table = {
272 .yes_ranges = imx7_yes_ranges,
273 .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges),
274};
275
276static 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,
280};
281
282static const struct imx_pgc_domain imx8m_pgc_domains[] = {
283 [IMX8M_POWER_DOMAIN_MIPI] = {
284 .genpd = {
285 .name = "mipi",
286 },
287 .bits = {
288 .pxx = IMX8M_MIPI_SW_Pxx_REQ,
289 .map = IMX8M_MIPI_A53_DOMAIN,
290 },
291 .pgc = IMX8M_PGC_MIPI,
292 },
293
294 [IMX8M_POWER_DOMAIN_PCIE1] = {
295 .genpd = {
296 .name = "pcie1",
297 },
298 .bits = {
299 .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
300 .map = IMX8M_PCIE1_A53_DOMAIN,
301 },
302 .pgc = IMX8M_PGC_PCIE1,
303 },
304
305 [IMX8M_POWER_DOMAIN_USB_OTG1] = {
306 .genpd = {
307 .name = "usb-otg1",
308 },
309 .bits = {
310 .pxx = IMX8M_OTG1_SW_Pxx_REQ,
311 .map = IMX8M_OTG1_A53_DOMAIN,
312 },
313 .pgc = IMX8M_PGC_OTG1,
314 },
315
316 [IMX8M_POWER_DOMAIN_USB_OTG2] = {
317 .genpd = {
318 .name = "usb-otg2",
319 },
320 .bits = {
321 .pxx = IMX8M_OTG2_SW_Pxx_REQ,
322 .map = IMX8M_OTG2_A53_DOMAIN,
323 },
324 .pgc = IMX8M_PGC_OTG2,
325 },
326
327 [IMX8M_POWER_DOMAIN_DDR1] = {
328 .genpd = {
329 .name = "ddr1",
330 },
331 .bits = {
332 .pxx = IMX8M_DDR1_SW_Pxx_REQ,
333 .map = IMX8M_DDR2_A53_DOMAIN,
334 },
335 .pgc = IMX8M_PGC_DDR1,
336 },
337
338 [IMX8M_POWER_DOMAIN_GPU] = {
339 .genpd = {
340 .name = "gpu",
341 },
342 .bits = {
343 .pxx = IMX8M_GPU_SW_Pxx_REQ,
344 .map = IMX8M_GPU_A53_DOMAIN,
345 .hsk = IMX8M_GPU_HSK_PWRDNREQN,
346 },
347 .pgc = IMX8M_PGC_GPU,
348 },
349
350 [IMX8M_POWER_DOMAIN_VPU] = {
351 .genpd = {
352 .name = "vpu",
353 },
354 .bits = {
355 .pxx = IMX8M_VPU_SW_Pxx_REQ,
356 .map = IMX8M_VPU_A53_DOMAIN,
357 .hsk = IMX8M_VPU_HSK_PWRDNREQN,
358 },
359 .pgc = IMX8M_PGC_VPU,
360 },
361
362 [IMX8M_POWER_DOMAIN_DISP] = {
363 .genpd = {
364 .name = "disp",
365 },
366 .bits = {
367 .pxx = IMX8M_DISP_SW_Pxx_REQ,
368 .map = IMX8M_DISP_A53_DOMAIN,
369 .hsk = IMX8M_DISP_HSK_PWRDNREQN,
370 },
371 .pgc = IMX8M_PGC_DISP,
372 },
373
374 [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
375 .genpd = {
376 .name = "mipi-csi1",
377 },
378 .bits = {
379 .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
380 .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
381 },
382 .pgc = IMX8M_PGC_MIPI_CSI1,
383 },
384
385 [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
386 .genpd = {
387 .name = "mipi-csi2",
388 },
389 .bits = {
390 .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
391 .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
392 },
393 .pgc = IMX8M_PGC_MIPI_CSI2,
394 },
395
396 [IMX8M_POWER_DOMAIN_PCIE2] = {
397 .genpd = {
398 .name = "pcie2",
399 },
400 .bits = {
401 .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
402 .map = IMX8M_PCIE2_A53_DOMAIN,
403 },
404 .pgc = IMX8M_PGC_PCIE2,
405 },
406};
407
408static const struct regmap_range imx8m_yes_ranges[] = {
409 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
410 GPC_PU_PWRHSK),
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)),
433};
434
435static const struct regmap_access_table imx8m_access_table = {
436 .yes_ranges = imx8m_yes_ranges,
437 .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges),
438};
439
440static 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,
444};
445
446static int imx_pgc_get_clocks(struct imx_pgc_domain *domain)
447{
448 int i, ret;
449
450 for (i = 0; ; i++) {
451 struct clk *clk = of_clk_get(domain->dev->of_node, i);
452 if (IS_ERR(clk))
453 break;
454 if (i >= GPC_CLK_MAX) {
455 dev_err(domain->dev, "more than %d clocks\n",
456 GPC_CLK_MAX);
457 ret = -EINVAL;
458 goto clk_err;
459 }
460 domain->clk[i] = clk;
461 }
462 domain->num_clks = i;
463
464 return 0;
465
466clk_err:
467 while (i--)
468 clk_put(domain->clk[i]);
469
470 return ret;
471}
472
473static void imx_pgc_put_clocks(struct imx_pgc_domain *domain)
474{
475 int i;
476
477 for (i = domain->num_clks - 1; i >= 0; i--)
478 clk_put(domain->clk[i]);
479}
480
481static int imx_pgc_domain_probe(struct platform_device *pdev)
482{
483 struct imx_pgc_domain *domain = pdev->dev.platform_data;
484 int ret;
485
486 domain->dev = &pdev->dev;
487
488 domain->regulator = devm_regulator_get_optional(domain->dev, "power");
489 if (IS_ERR(domain->regulator)) {
490 if (PTR_ERR(domain->regulator) != -ENODEV) {
491 if (PTR_ERR(domain->regulator) != -EPROBE_DEFER)
492 dev_err(domain->dev, "Failed to get domain's regulator\n");
493 return PTR_ERR(domain->regulator);
494 }
495 } else if (domain->voltage) {
496 regulator_set_voltage(domain->regulator,
497 domain->voltage, domain->voltage);
498 }
499
500 ret = imx_pgc_get_clocks(domain);
501 if (ret) {
502 if (ret != -EPROBE_DEFER)
503 dev_err(domain->dev, "Failed to get domain's clocks\n");
504 return ret;
505 }
506
507 ret = pm_genpd_init(&domain->genpd, NULL, true);
508 if (ret) {
509 dev_err(domain->dev, "Failed to init power domain\n");
510 imx_pgc_put_clocks(domain);
511 return ret;
512 }
513
514 ret = of_genpd_add_provider_simple(domain->dev->of_node,
515 &domain->genpd);
516 if (ret) {
517 dev_err(domain->dev, "Failed to add genpd provider\n");
518 pm_genpd_remove(&domain->genpd);
519 imx_pgc_put_clocks(domain);
520 }
521
522 return ret;
523}
524
525static int imx_pgc_domain_remove(struct platform_device *pdev)
526{
527 struct imx_pgc_domain *domain = pdev->dev.platform_data;
528
529 of_genpd_del_provider(domain->dev->of_node);
530 pm_genpd_remove(&domain->genpd);
531 imx_pgc_put_clocks(domain);
532
533 return 0;
534}
535
536static const struct platform_device_id imx_pgc_domain_id[] = {
537 { "imx-pgc-domain", },
538 { },
539};
540
541static struct platform_driver imx_pgc_domain_driver = {
542 .driver = {
543 .name = "imx-pgc",
544 },
545 .probe = imx_pgc_domain_probe,
546 .remove = imx_pgc_domain_remove,
547 .id_table = imx_pgc_domain_id,
548};
549builtin_platform_driver(imx_pgc_domain_driver)
550
551static int imx_gpcv2_probe(struct platform_device *pdev)
552{
553 const struct imx_pgc_domain_data *domain_data =
554 of_device_get_match_data(&pdev->dev);
555
556 struct regmap_config regmap_config = {
557 .reg_bits = 32,
558 .val_bits = 32,
559 .reg_stride = 4,
560 .rd_table = domain_data->reg_access_table,
561 .wr_table = domain_data->reg_access_table,
562 .max_register = SZ_4K,
563 };
564 struct device *dev = &pdev->dev;
565 struct device_node *pgc_np, *np;
566 struct regmap *regmap;
567 void __iomem *base;
568 int ret;
569
570 pgc_np = of_get_child_by_name(dev->of_node, "pgc");
571 if (!pgc_np) {
572 dev_err(dev, "No power domains specified in DT\n");
573 return -EINVAL;
574 }
575
576 base = devm_platform_ioremap_resource(pdev, 0);
577 if (IS_ERR(base))
578 return PTR_ERR(base);
579
580 regmap = devm_regmap_init_mmio(dev, base, ®map_config);
581 if (IS_ERR(regmap)) {
582 ret = PTR_ERR(regmap);
583 dev_err(dev, "failed to init regmap (%d)\n", ret);
584 return ret;
585 }
586
587 for_each_child_of_node(pgc_np, np) {
588 struct platform_device *pd_pdev;
589 struct imx_pgc_domain *domain;
590 u32 domain_index;
591
592 ret = of_property_read_u32(np, "reg", &domain_index);
593 if (ret) {
594 dev_err(dev, "Failed to read 'reg' property\n");
595 of_node_put(np);
596 return ret;
597 }
598
599 if (domain_index >= domain_data->domains_num) {
600 dev_warn(dev,
601 "Domain index %d is out of bounds\n",
602 domain_index);
603 continue;
604 }
605
606 pd_pdev = platform_device_alloc("imx-pgc-domain",
607 domain_index);
608 if (!pd_pdev) {
609 dev_err(dev, "Failed to allocate platform device\n");
610 of_node_put(np);
611 return -ENOMEM;
612 }
613
614 ret = platform_device_add_data(pd_pdev,
615 &domain_data->domains[domain_index],
616 sizeof(domain_data->domains[domain_index]));
617 if (ret) {
618 platform_device_put(pd_pdev);
619 of_node_put(np);
620 return ret;
621 }
622
623 domain = pd_pdev->dev.platform_data;
624 domain->regmap = regmap;
625 domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req;
626 domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req;
627
628 pd_pdev->dev.parent = dev;
629 pd_pdev->dev.of_node = np;
630
631 ret = platform_device_add(pd_pdev);
632 if (ret) {
633 platform_device_put(pd_pdev);
634 of_node_put(np);
635 return ret;
636 }
637 }
638
639 return 0;
640}
641
642static const struct of_device_id imx_gpcv2_dt_ids[] = {
643 { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
644 { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
645 { }
646};
647
648static struct platform_driver imx_gpc_driver = {
649 .driver = {
650 .name = "imx-gpcv2",
651 .of_match_table = imx_gpcv2_dt_ids,
652 },
653 .probe = imx_gpcv2_probe,
654};
655builtin_platform_driver(imx_gpc_driver)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2017 Impinj, Inc
4 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
5 *
6 * Based on the code of analogus driver:
7 *
8 * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
9 */
10
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/pm_runtime.h>
16#include <linux/regmap.h>
17#include <linux/regulator/consumer.h>
18#include <linux/reset.h>
19#include <linux/sizes.h>
20#include <dt-bindings/power/imx7-power.h>
21#include <dt-bindings/power/imx8mq-power.h>
22#include <dt-bindings/power/imx8mm-power.h>
23#include <dt-bindings/power/imx8mn-power.h>
24
25#define GPC_LPCR_A_CORE_BSC 0x000
26
27#define GPC_PGC_CPU_MAPPING 0x0ec
28
29#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6)
30#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5)
31#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4)
32#define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3)
33#define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2)
34
35#define IMX8M_PCIE2_A53_DOMAIN BIT(15)
36#define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14)
37#define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13)
38#define IMX8M_DISP_A53_DOMAIN BIT(12)
39#define IMX8M_HDMI_A53_DOMAIN BIT(11)
40#define IMX8M_VPU_A53_DOMAIN BIT(10)
41#define IMX8M_GPU_A53_DOMAIN BIT(9)
42#define IMX8M_DDR2_A53_DOMAIN BIT(8)
43#define IMX8M_DDR1_A53_DOMAIN BIT(7)
44#define IMX8M_OTG2_A53_DOMAIN BIT(5)
45#define IMX8M_OTG1_A53_DOMAIN BIT(4)
46#define IMX8M_PCIE1_A53_DOMAIN BIT(3)
47#define IMX8M_MIPI_A53_DOMAIN BIT(2)
48
49#define IMX8MM_VPUH1_A53_DOMAIN BIT(15)
50#define IMX8MM_VPUG2_A53_DOMAIN BIT(14)
51#define IMX8MM_VPUG1_A53_DOMAIN BIT(13)
52#define IMX8MM_DISPMIX_A53_DOMAIN BIT(12)
53#define IMX8MM_VPUMIX_A53_DOMAIN BIT(10)
54#define IMX8MM_GPUMIX_A53_DOMAIN BIT(9)
55#define IMX8MM_GPU_A53_DOMAIN (BIT(8) | BIT(11))
56#define IMX8MM_DDR1_A53_DOMAIN BIT(7)
57#define IMX8MM_OTG2_A53_DOMAIN BIT(5)
58#define IMX8MM_OTG1_A53_DOMAIN BIT(4)
59#define IMX8MM_PCIE_A53_DOMAIN BIT(3)
60#define IMX8MM_MIPI_A53_DOMAIN BIT(2)
61
62#define IMX8MN_DISPMIX_A53_DOMAIN BIT(12)
63#define IMX8MN_GPUMIX_A53_DOMAIN BIT(9)
64#define IMX8MN_DDR1_A53_DOMAIN BIT(7)
65#define IMX8MN_OTG1_A53_DOMAIN BIT(4)
66#define IMX8MN_MIPI_A53_DOMAIN BIT(2)
67
68#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
69#define GPC_PU_PGC_SW_PDN_REQ 0x104
70
71#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
72#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
73#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
74#define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1)
75#define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0)
76
77#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13)
78#define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12)
79#define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11)
80#define IMX8M_DISP_SW_Pxx_REQ BIT(10)
81#define IMX8M_HDMI_SW_Pxx_REQ BIT(9)
82#define IMX8M_VPU_SW_Pxx_REQ BIT(8)
83#define IMX8M_GPU_SW_Pxx_REQ BIT(7)
84#define IMX8M_DDR2_SW_Pxx_REQ BIT(6)
85#define IMX8M_DDR1_SW_Pxx_REQ BIT(5)
86#define IMX8M_OTG2_SW_Pxx_REQ BIT(3)
87#define IMX8M_OTG1_SW_Pxx_REQ BIT(2)
88#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1)
89#define IMX8M_MIPI_SW_Pxx_REQ BIT(0)
90
91#define IMX8MM_VPUH1_SW_Pxx_REQ BIT(13)
92#define IMX8MM_VPUG2_SW_Pxx_REQ BIT(12)
93#define IMX8MM_VPUG1_SW_Pxx_REQ BIT(11)
94#define IMX8MM_DISPMIX_SW_Pxx_REQ BIT(10)
95#define IMX8MM_VPUMIX_SW_Pxx_REQ BIT(8)
96#define IMX8MM_GPUMIX_SW_Pxx_REQ BIT(7)
97#define IMX8MM_GPU_SW_Pxx_REQ (BIT(6) | BIT(9))
98#define IMX8MM_DDR1_SW_Pxx_REQ BIT(5)
99#define IMX8MM_OTG2_SW_Pxx_REQ BIT(3)
100#define IMX8MM_OTG1_SW_Pxx_REQ BIT(2)
101#define IMX8MM_PCIE_SW_Pxx_REQ BIT(1)
102#define IMX8MM_MIPI_SW_Pxx_REQ BIT(0)
103
104#define IMX8MN_DISPMIX_SW_Pxx_REQ BIT(10)
105#define IMX8MN_GPUMIX_SW_Pxx_REQ BIT(7)
106#define IMX8MN_DDR1_SW_Pxx_REQ BIT(5)
107#define IMX8MN_OTG1_SW_Pxx_REQ BIT(2)
108#define IMX8MN_MIPI_SW_Pxx_REQ BIT(0)
109
110#define GPC_M4_PU_PDN_FLG 0x1bc
111
112#define GPC_PU_PWRHSK 0x1fc
113
114#define IMX8M_GPU_HSK_PWRDNACKN BIT(26)
115#define IMX8M_VPU_HSK_PWRDNACKN BIT(25)
116#define IMX8M_DISP_HSK_PWRDNACKN BIT(24)
117#define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
118#define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
119#define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
120
121
122#define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29)
123#define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28))
124#define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26)
125#define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25)
126#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24))
127#define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11)
128#define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10))
129#define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8)
130#define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7)
131#define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6))
132
133#define IMX8MN_GPUMIX_HSK_PWRDNACKN (BIT(29) | BIT(27))
134#define IMX8MN_DISPMIX_HSK_PWRDNACKN BIT(25)
135#define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23)
136#define IMX8MN_GPUMIX_HSK_PWRDNREQN (BIT(11) | BIT(9))
137#define IMX8MN_DISPMIX_HSK_PWRDNREQN BIT(7)
138#define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5)
139
140/*
141 * The PGC offset values in Reference Manual
142 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
143 * GPC_PGC memory map are incorrect, below offset
144 * values are from design RTL.
145 */
146#define IMX7_PGC_MIPI 16
147#define IMX7_PGC_PCIE 17
148#define IMX7_PGC_USB_HSIC 20
149
150#define IMX8M_PGC_MIPI 16
151#define IMX8M_PGC_PCIE1 17
152#define IMX8M_PGC_OTG1 18
153#define IMX8M_PGC_OTG2 19
154#define IMX8M_PGC_DDR1 21
155#define IMX8M_PGC_GPU 23
156#define IMX8M_PGC_VPU 24
157#define IMX8M_PGC_DISP 26
158#define IMX8M_PGC_MIPI_CSI1 27
159#define IMX8M_PGC_MIPI_CSI2 28
160#define IMX8M_PGC_PCIE2 29
161
162#define IMX8MM_PGC_MIPI 16
163#define IMX8MM_PGC_PCIE 17
164#define IMX8MM_PGC_OTG1 18
165#define IMX8MM_PGC_OTG2 19
166#define IMX8MM_PGC_DDR1 21
167#define IMX8MM_PGC_GPU2D 22
168#define IMX8MM_PGC_GPUMIX 23
169#define IMX8MM_PGC_VPUMIX 24
170#define IMX8MM_PGC_GPU3D 25
171#define IMX8MM_PGC_DISPMIX 26
172#define IMX8MM_PGC_VPUG1 27
173#define IMX8MM_PGC_VPUG2 28
174#define IMX8MM_PGC_VPUH1 29
175
176#define IMX8MN_PGC_MIPI 16
177#define IMX8MN_PGC_OTG1 18
178#define IMX8MN_PGC_DDR1 21
179#define IMX8MN_PGC_GPUMIX 23
180#define IMX8MN_PGC_DISPMIX 26
181
182#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
183#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
184
185#define GPC_PGC_CTRL_PCR BIT(0)
186
187struct imx_pgc_domain {
188 struct generic_pm_domain genpd;
189 struct regmap *regmap;
190 struct regulator *regulator;
191 struct reset_control *reset;
192 struct clk_bulk_data *clks;
193 int num_clks;
194
195 unsigned int pgc;
196
197 const struct {
198 u32 pxx;
199 u32 map;
200 u32 hskreq;
201 u32 hskack;
202 } bits;
203
204 const int voltage;
205 struct device *dev;
206};
207
208struct imx_pgc_domain_data {
209 const struct imx_pgc_domain *domains;
210 size_t domains_num;
211 const struct regmap_access_table *reg_access_table;
212};
213
214static inline struct imx_pgc_domain *
215to_imx_pgc_domain(struct generic_pm_domain *genpd)
216{
217 return container_of(genpd, struct imx_pgc_domain, genpd);
218}
219
220static int imx_pgc_power_up(struct generic_pm_domain *genpd)
221{
222 struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
223 u32 reg_val;
224 int ret;
225
226 ret = pm_runtime_get_sync(domain->dev);
227 if (ret < 0) {
228 pm_runtime_put_noidle(domain->dev);
229 return ret;
230 }
231
232 if (!IS_ERR(domain->regulator)) {
233 ret = regulator_enable(domain->regulator);
234 if (ret) {
235 dev_err(domain->dev, "failed to enable regulator\n");
236 goto out_put_pm;
237 }
238 }
239
240 /* Enable reset clocks for all devices in the domain */
241 ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
242 if (ret) {
243 dev_err(domain->dev, "failed to enable reset clocks\n");
244 goto out_regulator_disable;
245 }
246
247 if (domain->bits.pxx) {
248 /* request the domain to power up */
249 regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
250 domain->bits.pxx, domain->bits.pxx);
251 /*
252 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
253 * for PUP_REQ/PDN_REQ bit to be cleared
254 */
255 ret = regmap_read_poll_timeout(domain->regmap,
256 GPC_PU_PGC_SW_PUP_REQ, reg_val,
257 !(reg_val & domain->bits.pxx),
258 0, USEC_PER_MSEC);
259 if (ret) {
260 dev_err(domain->dev, "failed to command PGC\n");
261 goto out_clk_disable;
262 }
263
264 /* disable power control */
265 regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
266 GPC_PGC_CTRL_PCR);
267 }
268
269 reset_control_assert(domain->reset);
270
271 /* delay for reset to propagate */
272 udelay(5);
273
274 reset_control_deassert(domain->reset);
275
276 /* request the ADB400 to power up */
277 if (domain->bits.hskreq) {
278 regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
279 domain->bits.hskreq, domain->bits.hskreq);
280
281 /*
282 * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val,
283 * (reg_val & domain->bits.hskack), 0,
284 * USEC_PER_MSEC);
285 * Technically we need the commented code to wait handshake. But that needs
286 * the BLK-CTL module BUS clk-en bit being set.
287 *
288 * There is a separate BLK-CTL module and we will have such a driver for it,
289 * that driver will set the BUS clk-en bit and handshake will be triggered
290 * automatically there. Just add a delay and suppose the handshake finish
291 * after that.
292 */
293 }
294
295 /* Disable reset clocks for all devices in the domain */
296 clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
297
298 return 0;
299
300out_clk_disable:
301 clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
302out_regulator_disable:
303 if (!IS_ERR(domain->regulator))
304 regulator_disable(domain->regulator);
305out_put_pm:
306 pm_runtime_put(domain->dev);
307
308 return ret;
309}
310
311static int imx_pgc_power_down(struct generic_pm_domain *genpd)
312{
313 struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
314 u32 reg_val;
315 int ret;
316
317 /* Enable reset clocks for all devices in the domain */
318 ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
319 if (ret) {
320 dev_err(domain->dev, "failed to enable reset clocks\n");
321 return ret;
322 }
323
324 /* request the ADB400 to power down */
325 if (domain->bits.hskreq) {
326 regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK,
327 domain->bits.hskreq);
328
329 ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK,
330 reg_val,
331 !(reg_val & domain->bits.hskack),
332 0, USEC_PER_MSEC);
333 if (ret) {
334 dev_err(domain->dev, "failed to power down ADB400\n");
335 goto out_clk_disable;
336 }
337 }
338
339 if (domain->bits.pxx) {
340 /* enable power control */
341 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
342 GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
343
344 /* request the domain to power down */
345 regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
346 domain->bits.pxx, domain->bits.pxx);
347 /*
348 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
349 * for PUP_REQ/PDN_REQ bit to be cleared
350 */
351 ret = regmap_read_poll_timeout(domain->regmap,
352 GPC_PU_PGC_SW_PDN_REQ, reg_val,
353 !(reg_val & domain->bits.pxx),
354 0, USEC_PER_MSEC);
355 if (ret) {
356 dev_err(domain->dev, "failed to command PGC\n");
357 goto out_clk_disable;
358 }
359 }
360
361 /* Disable reset clocks for all devices in the domain */
362 clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
363
364 if (!IS_ERR(domain->regulator)) {
365 ret = regulator_disable(domain->regulator);
366 if (ret) {
367 dev_err(domain->dev, "failed to disable regulator\n");
368 return ret;
369 }
370 }
371
372 pm_runtime_put(domain->dev);
373
374 return 0;
375
376out_clk_disable:
377 clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
378
379 return ret;
380}
381
382static const struct imx_pgc_domain imx7_pgc_domains[] = {
383 [IMX7_POWER_DOMAIN_MIPI_PHY] = {
384 .genpd = {
385 .name = "mipi-phy",
386 },
387 .bits = {
388 .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
389 .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
390 },
391 .voltage = 1000000,
392 .pgc = IMX7_PGC_MIPI,
393 },
394
395 [IMX7_POWER_DOMAIN_PCIE_PHY] = {
396 .genpd = {
397 .name = "pcie-phy",
398 },
399 .bits = {
400 .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
401 .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
402 },
403 .voltage = 1000000,
404 .pgc = IMX7_PGC_PCIE,
405 },
406
407 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
408 .genpd = {
409 .name = "usb-hsic-phy",
410 },
411 .bits = {
412 .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
413 .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
414 },
415 .voltage = 1200000,
416 .pgc = IMX7_PGC_USB_HSIC,
417 },
418};
419
420static const struct regmap_range imx7_yes_ranges[] = {
421 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
422 GPC_M4_PU_PDN_FLG),
423 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
424 GPC_PGC_SR(IMX7_PGC_MIPI)),
425 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
426 GPC_PGC_SR(IMX7_PGC_PCIE)),
427 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
428 GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
429};
430
431static const struct regmap_access_table imx7_access_table = {
432 .yes_ranges = imx7_yes_ranges,
433 .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges),
434};
435
436static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
437 .domains = imx7_pgc_domains,
438 .domains_num = ARRAY_SIZE(imx7_pgc_domains),
439 .reg_access_table = &imx7_access_table,
440};
441
442static const struct imx_pgc_domain imx8m_pgc_domains[] = {
443 [IMX8M_POWER_DOMAIN_MIPI] = {
444 .genpd = {
445 .name = "mipi",
446 },
447 .bits = {
448 .pxx = IMX8M_MIPI_SW_Pxx_REQ,
449 .map = IMX8M_MIPI_A53_DOMAIN,
450 },
451 .pgc = IMX8M_PGC_MIPI,
452 },
453
454 [IMX8M_POWER_DOMAIN_PCIE1] = {
455 .genpd = {
456 .name = "pcie1",
457 },
458 .bits = {
459 .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
460 .map = IMX8M_PCIE1_A53_DOMAIN,
461 },
462 .pgc = IMX8M_PGC_PCIE1,
463 },
464
465 [IMX8M_POWER_DOMAIN_USB_OTG1] = {
466 .genpd = {
467 .name = "usb-otg1",
468 },
469 .bits = {
470 .pxx = IMX8M_OTG1_SW_Pxx_REQ,
471 .map = IMX8M_OTG1_A53_DOMAIN,
472 },
473 .pgc = IMX8M_PGC_OTG1,
474 },
475
476 [IMX8M_POWER_DOMAIN_USB_OTG2] = {
477 .genpd = {
478 .name = "usb-otg2",
479 },
480 .bits = {
481 .pxx = IMX8M_OTG2_SW_Pxx_REQ,
482 .map = IMX8M_OTG2_A53_DOMAIN,
483 },
484 .pgc = IMX8M_PGC_OTG2,
485 },
486
487 [IMX8M_POWER_DOMAIN_DDR1] = {
488 .genpd = {
489 .name = "ddr1",
490 },
491 .bits = {
492 .pxx = IMX8M_DDR1_SW_Pxx_REQ,
493 .map = IMX8M_DDR2_A53_DOMAIN,
494 },
495 .pgc = IMX8M_PGC_DDR1,
496 },
497
498 [IMX8M_POWER_DOMAIN_GPU] = {
499 .genpd = {
500 .name = "gpu",
501 },
502 .bits = {
503 .pxx = IMX8M_GPU_SW_Pxx_REQ,
504 .map = IMX8M_GPU_A53_DOMAIN,
505 .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
506 .hskack = IMX8M_GPU_HSK_PWRDNACKN,
507 },
508 .pgc = IMX8M_PGC_GPU,
509 },
510
511 [IMX8M_POWER_DOMAIN_VPU] = {
512 .genpd = {
513 .name = "vpu",
514 },
515 .bits = {
516 .pxx = IMX8M_VPU_SW_Pxx_REQ,
517 .map = IMX8M_VPU_A53_DOMAIN,
518 .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
519 .hskack = IMX8M_VPU_HSK_PWRDNACKN,
520 },
521 .pgc = IMX8M_PGC_VPU,
522 },
523
524 [IMX8M_POWER_DOMAIN_DISP] = {
525 .genpd = {
526 .name = "disp",
527 },
528 .bits = {
529 .pxx = IMX8M_DISP_SW_Pxx_REQ,
530 .map = IMX8M_DISP_A53_DOMAIN,
531 .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
532 .hskack = IMX8M_DISP_HSK_PWRDNACKN,
533 },
534 .pgc = IMX8M_PGC_DISP,
535 },
536
537 [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
538 .genpd = {
539 .name = "mipi-csi1",
540 },
541 .bits = {
542 .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
543 .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
544 },
545 .pgc = IMX8M_PGC_MIPI_CSI1,
546 },
547
548 [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
549 .genpd = {
550 .name = "mipi-csi2",
551 },
552 .bits = {
553 .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
554 .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
555 },
556 .pgc = IMX8M_PGC_MIPI_CSI2,
557 },
558
559 [IMX8M_POWER_DOMAIN_PCIE2] = {
560 .genpd = {
561 .name = "pcie2",
562 },
563 .bits = {
564 .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
565 .map = IMX8M_PCIE2_A53_DOMAIN,
566 },
567 .pgc = IMX8M_PGC_PCIE2,
568 },
569};
570
571static const struct regmap_range imx8m_yes_ranges[] = {
572 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
573 GPC_PU_PWRHSK),
574 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
575 GPC_PGC_SR(IMX8M_PGC_MIPI)),
576 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
577 GPC_PGC_SR(IMX8M_PGC_PCIE1)),
578 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
579 GPC_PGC_SR(IMX8M_PGC_OTG1)),
580 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
581 GPC_PGC_SR(IMX8M_PGC_OTG2)),
582 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
583 GPC_PGC_SR(IMX8M_PGC_DDR1)),
584 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
585 GPC_PGC_SR(IMX8M_PGC_GPU)),
586 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
587 GPC_PGC_SR(IMX8M_PGC_VPU)),
588 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
589 GPC_PGC_SR(IMX8M_PGC_DISP)),
590 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
591 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
592 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
593 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
594 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
595 GPC_PGC_SR(IMX8M_PGC_PCIE2)),
596};
597
598static const struct regmap_access_table imx8m_access_table = {
599 .yes_ranges = imx8m_yes_ranges,
600 .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges),
601};
602
603static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
604 .domains = imx8m_pgc_domains,
605 .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
606 .reg_access_table = &imx8m_access_table,
607};
608
609static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
610 [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
611 .genpd = {
612 .name = "hsiomix",
613 },
614 .bits = {
615 .pxx = 0, /* no power sequence control */
616 .map = 0, /* no power sequence control */
617 .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
618 .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
619 },
620 },
621
622 [IMX8MM_POWER_DOMAIN_PCIE] = {
623 .genpd = {
624 .name = "pcie",
625 },
626 .bits = {
627 .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
628 .map = IMX8MM_PCIE_A53_DOMAIN,
629 },
630 .pgc = IMX8MM_PGC_PCIE,
631 },
632
633 [IMX8MM_POWER_DOMAIN_OTG1] = {
634 .genpd = {
635 .name = "usb-otg1",
636 },
637 .bits = {
638 .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
639 .map = IMX8MM_OTG1_A53_DOMAIN,
640 },
641 .pgc = IMX8MM_PGC_OTG1,
642 },
643
644 [IMX8MM_POWER_DOMAIN_OTG2] = {
645 .genpd = {
646 .name = "usb-otg2",
647 },
648 .bits = {
649 .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
650 .map = IMX8MM_OTG2_A53_DOMAIN,
651 },
652 .pgc = IMX8MM_PGC_OTG2,
653 },
654
655 [IMX8MM_POWER_DOMAIN_GPUMIX] = {
656 .genpd = {
657 .name = "gpumix",
658 },
659 .bits = {
660 .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
661 .map = IMX8MM_GPUMIX_A53_DOMAIN,
662 .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
663 .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
664 },
665 .pgc = IMX8MM_PGC_GPUMIX,
666 },
667
668 [IMX8MM_POWER_DOMAIN_GPU] = {
669 .genpd = {
670 .name = "gpu",
671 },
672 .bits = {
673 .pxx = IMX8MM_GPU_SW_Pxx_REQ,
674 .map = IMX8MM_GPU_A53_DOMAIN,
675 .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
676 .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
677 },
678 .pgc = IMX8MM_PGC_GPU2D,
679 },
680
681 [IMX8MM_POWER_DOMAIN_VPUMIX] = {
682 .genpd = {
683 .name = "vpumix",
684 },
685 .bits = {
686 .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
687 .map = IMX8MM_VPUMIX_A53_DOMAIN,
688 .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
689 .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
690 },
691 .pgc = IMX8MM_PGC_VPUMIX,
692 },
693
694 [IMX8MM_POWER_DOMAIN_VPUG1] = {
695 .genpd = {
696 .name = "vpu-g1",
697 },
698 .bits = {
699 .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
700 .map = IMX8MM_VPUG1_A53_DOMAIN,
701 },
702 .pgc = IMX8MM_PGC_VPUG1,
703 },
704
705 [IMX8MM_POWER_DOMAIN_VPUG2] = {
706 .genpd = {
707 .name = "vpu-g2",
708 },
709 .bits = {
710 .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
711 .map = IMX8MM_VPUG2_A53_DOMAIN,
712 },
713 .pgc = IMX8MM_PGC_VPUG2,
714 },
715
716 [IMX8MM_POWER_DOMAIN_VPUH1] = {
717 .genpd = {
718 .name = "vpu-h1",
719 },
720 .bits = {
721 .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
722 .map = IMX8MM_VPUH1_A53_DOMAIN,
723 },
724 .pgc = IMX8MM_PGC_VPUH1,
725 },
726
727 [IMX8MM_POWER_DOMAIN_DISPMIX] = {
728 .genpd = {
729 .name = "dispmix",
730 },
731 .bits = {
732 .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
733 .map = IMX8MM_DISPMIX_A53_DOMAIN,
734 .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
735 .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
736 },
737 .pgc = IMX8MM_PGC_DISPMIX,
738 },
739
740 [IMX8MM_POWER_DOMAIN_MIPI] = {
741 .genpd = {
742 .name = "mipi",
743 },
744 .bits = {
745 .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
746 .map = IMX8MM_MIPI_A53_DOMAIN,
747 },
748 .pgc = IMX8MM_PGC_MIPI,
749 },
750};
751
752static const struct regmap_range imx8mm_yes_ranges[] = {
753 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
754 GPC_PU_PWRHSK),
755 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
756 GPC_PGC_SR(IMX8MM_PGC_MIPI)),
757 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
758 GPC_PGC_SR(IMX8MM_PGC_PCIE)),
759 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
760 GPC_PGC_SR(IMX8MM_PGC_OTG1)),
761 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
762 GPC_PGC_SR(IMX8MM_PGC_OTG2)),
763 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
764 GPC_PGC_SR(IMX8MM_PGC_DDR1)),
765 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
766 GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
767 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
768 GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
769 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
770 GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
771 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
772 GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
773 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
774 GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
775 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
776 GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
777 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
778 GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
779 regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
780 GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
781};
782
783static const struct regmap_access_table imx8mm_access_table = {
784 .yes_ranges = imx8mm_yes_ranges,
785 .n_yes_ranges = ARRAY_SIZE(imx8mm_yes_ranges),
786};
787
788static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
789 .domains = imx8mm_pgc_domains,
790 .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
791 .reg_access_table = &imx8mm_access_table,
792};
793
794static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
795 [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
796 .genpd = {
797 .name = "hsiomix",
798 },
799 .bits = {
800 .pxx = 0, /* no power sequence control */
801 .map = 0, /* no power sequence control */
802 .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
803 .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
804 },
805 },
806
807 [IMX8MN_POWER_DOMAIN_OTG1] = {
808 .genpd = {
809 .name = "usb-otg1",
810 },
811 .bits = {
812 .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
813 .map = IMX8MN_OTG1_A53_DOMAIN,
814 },
815 .pgc = IMX8MN_PGC_OTG1,
816 },
817
818 [IMX8MN_POWER_DOMAIN_GPUMIX] = {
819 .genpd = {
820 .name = "gpumix",
821 },
822 .bits = {
823 .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
824 .map = IMX8MN_GPUMIX_A53_DOMAIN,
825 .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
826 .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
827 },
828 .pgc = IMX8MN_PGC_GPUMIX,
829 },
830};
831
832static const struct regmap_range imx8mn_yes_ranges[] = {
833 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
834 GPC_PU_PWRHSK),
835 regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI),
836 GPC_PGC_SR(IMX8MN_PGC_MIPI)),
837 regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1),
838 GPC_PGC_SR(IMX8MN_PGC_OTG1)),
839 regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1),
840 GPC_PGC_SR(IMX8MN_PGC_DDR1)),
841 regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX),
842 GPC_PGC_SR(IMX8MN_PGC_GPUMIX)),
843 regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX),
844 GPC_PGC_SR(IMX8MN_PGC_DISPMIX)),
845};
846
847static const struct regmap_access_table imx8mn_access_table = {
848 .yes_ranges = imx8mn_yes_ranges,
849 .n_yes_ranges = ARRAY_SIZE(imx8mn_yes_ranges),
850};
851
852static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
853 .domains = imx8mn_pgc_domains,
854 .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
855 .reg_access_table = &imx8mn_access_table,
856};
857
858static int imx_pgc_domain_probe(struct platform_device *pdev)
859{
860 struct imx_pgc_domain *domain = pdev->dev.platform_data;
861 int ret;
862
863 domain->dev = &pdev->dev;
864
865 domain->regulator = devm_regulator_get_optional(domain->dev, "power");
866 if (IS_ERR(domain->regulator)) {
867 if (PTR_ERR(domain->regulator) != -ENODEV)
868 return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
869 "Failed to get domain's regulator\n");
870 } else if (domain->voltage) {
871 regulator_set_voltage(domain->regulator,
872 domain->voltage, domain->voltage);
873 }
874
875 domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks);
876 if (domain->num_clks < 0)
877 return dev_err_probe(domain->dev, domain->num_clks,
878 "Failed to get domain's clocks\n");
879
880 domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev);
881 if (IS_ERR(domain->reset))
882 return dev_err_probe(domain->dev, PTR_ERR(domain->reset),
883 "Failed to get domain's resets\n");
884
885 pm_runtime_enable(domain->dev);
886
887 if (domain->bits.map)
888 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
889 domain->bits.map, domain->bits.map);
890
891 ret = pm_genpd_init(&domain->genpd, NULL, true);
892 if (ret) {
893 dev_err(domain->dev, "Failed to init power domain\n");
894 goto out_domain_unmap;
895 }
896
897 ret = of_genpd_add_provider_simple(domain->dev->of_node,
898 &domain->genpd);
899 if (ret) {
900 dev_err(domain->dev, "Failed to add genpd provider\n");
901 goto out_genpd_remove;
902 }
903
904 return 0;
905
906out_genpd_remove:
907 pm_genpd_remove(&domain->genpd);
908out_domain_unmap:
909 if (domain->bits.map)
910 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
911 domain->bits.map, 0);
912 pm_runtime_disable(domain->dev);
913
914 return ret;
915}
916
917static int imx_pgc_domain_remove(struct platform_device *pdev)
918{
919 struct imx_pgc_domain *domain = pdev->dev.platform_data;
920
921 of_genpd_del_provider(domain->dev->of_node);
922 pm_genpd_remove(&domain->genpd);
923
924 if (domain->bits.map)
925 regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
926 domain->bits.map, 0);
927
928 pm_runtime_disable(domain->dev);
929
930 return 0;
931}
932
933static const struct platform_device_id imx_pgc_domain_id[] = {
934 { "imx-pgc-domain", },
935 { },
936};
937
938static struct platform_driver imx_pgc_domain_driver = {
939 .driver = {
940 .name = "imx-pgc",
941 },
942 .probe = imx_pgc_domain_probe,
943 .remove = imx_pgc_domain_remove,
944 .id_table = imx_pgc_domain_id,
945};
946builtin_platform_driver(imx_pgc_domain_driver)
947
948static int imx_gpcv2_probe(struct platform_device *pdev)
949{
950 const struct imx_pgc_domain_data *domain_data =
951 of_device_get_match_data(&pdev->dev);
952
953 struct regmap_config regmap_config = {
954 .reg_bits = 32,
955 .val_bits = 32,
956 .reg_stride = 4,
957 .rd_table = domain_data->reg_access_table,
958 .wr_table = domain_data->reg_access_table,
959 .max_register = SZ_4K,
960 };
961 struct device *dev = &pdev->dev;
962 struct device_node *pgc_np, *np;
963 struct regmap *regmap;
964 void __iomem *base;
965 int ret;
966
967 pgc_np = of_get_child_by_name(dev->of_node, "pgc");
968 if (!pgc_np) {
969 dev_err(dev, "No power domains specified in DT\n");
970 return -EINVAL;
971 }
972
973 base = devm_platform_ioremap_resource(pdev, 0);
974 if (IS_ERR(base))
975 return PTR_ERR(base);
976
977 regmap = devm_regmap_init_mmio(dev, base, ®map_config);
978 if (IS_ERR(regmap)) {
979 ret = PTR_ERR(regmap);
980 dev_err(dev, "failed to init regmap (%d)\n", ret);
981 return ret;
982 }
983
984 for_each_child_of_node(pgc_np, np) {
985 struct platform_device *pd_pdev;
986 struct imx_pgc_domain *domain;
987 u32 domain_index;
988
989 ret = of_property_read_u32(np, "reg", &domain_index);
990 if (ret) {
991 dev_err(dev, "Failed to read 'reg' property\n");
992 of_node_put(np);
993 return ret;
994 }
995
996 if (domain_index >= domain_data->domains_num) {
997 dev_warn(dev,
998 "Domain index %d is out of bounds\n",
999 domain_index);
1000 continue;
1001 }
1002
1003 pd_pdev = platform_device_alloc("imx-pgc-domain",
1004 domain_index);
1005 if (!pd_pdev) {
1006 dev_err(dev, "Failed to allocate platform device\n");
1007 of_node_put(np);
1008 return -ENOMEM;
1009 }
1010
1011 ret = platform_device_add_data(pd_pdev,
1012 &domain_data->domains[domain_index],
1013 sizeof(domain_data->domains[domain_index]));
1014 if (ret) {
1015 platform_device_put(pd_pdev);
1016 of_node_put(np);
1017 return ret;
1018 }
1019
1020 domain = pd_pdev->dev.platform_data;
1021 domain->regmap = regmap;
1022 domain->genpd.power_on = imx_pgc_power_up;
1023 domain->genpd.power_off = imx_pgc_power_down;
1024
1025 pd_pdev->dev.parent = dev;
1026 pd_pdev->dev.of_node = np;
1027
1028 ret = platform_device_add(pd_pdev);
1029 if (ret) {
1030 platform_device_put(pd_pdev);
1031 of_node_put(np);
1032 return ret;
1033 }
1034 }
1035
1036 return 0;
1037}
1038
1039static const struct of_device_id imx_gpcv2_dt_ids[] = {
1040 { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
1041 { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
1042 { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, },
1043 { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
1044 { }
1045};
1046
1047static struct platform_driver imx_gpc_driver = {
1048 .driver = {
1049 .name = "imx-gpcv2",
1050 .of_match_table = imx_gpcv2_dt_ids,
1051 },
1052 .probe = imx_gpcv2_probe,
1053};
1054builtin_platform_driver(imx_gpc_driver)