1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip Generic power domain support.
5 * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
9 #include <linux/iopoll.h>
10 #include <linux/err.h>
11 #include <linux/pm_clock.h>
12 #include <linux/pm_domain.h>
13 #include <linux/of_address.h>
14 #include <linux/of_clk.h>
15 #include <linux/of_platform.h>
16 #include <linux/clk.h>
17 #include <linux/regmap.h>
18 #include <linux/mfd/syscon.h>
19 #include <dt-bindings/power/px30-power.h>
20 #include <dt-bindings/power/rk3036-power.h>
21 #include <dt-bindings/power/rk3066-power.h>
22 #include <dt-bindings/power/rk3128-power.h>
23 #include <dt-bindings/power/rk3188-power.h>
24 #include <dt-bindings/power/rk3228-power.h>
25 #include <dt-bindings/power/rk3288-power.h>
26 #include <dt-bindings/power/rk3328-power.h>
27 #include <dt-bindings/power/rk3366-power.h>
28 #include <dt-bindings/power/rk3368-power.h>
29 #include <dt-bindings/power/rk3399-power.h>
31 struct rockchip_domain_info
{
42 struct rockchip_pmu_info
{
49 u32 core_pwrcnt_offset
;
50 u32 gpu_pwrcnt_offset
;
52 unsigned int core_power_transition_time
;
53 unsigned int gpu_power_transition_time
;
56 const struct rockchip_domain_info
*domain_info
;
59 #define MAX_QOS_REGS_NUM 5
60 #define QOS_PRIORITY 0x08
62 #define QOS_BANDWIDTH 0x10
63 #define QOS_SATURATION 0x14
64 #define QOS_EXTCONTROL 0x18
66 struct rockchip_pm_domain
{
67 struct generic_pm_domain genpd
;
68 const struct rockchip_domain_info
*info
;
69 struct rockchip_pmu
*pmu
;
71 struct regmap
**qos_regmap
;
72 u32
*qos_save_regs
[MAX_QOS_REGS_NUM
];
74 struct clk_bulk_data
*clks
;
79 struct regmap
*regmap
;
80 const struct rockchip_pmu_info
*info
;
81 struct mutex mutex
; /* mutex lock for pmu */
82 struct genpd_onecell_data genpd_data
;
83 struct generic_pm_domain
*domains
[];
86 #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
88 #define DOMAIN(pwr, status, req, idle, ack, wakeup) \
91 .status_mask = (status), \
93 .idle_mask = (idle), \
95 .active_wakeup = (wakeup), \
98 #define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
100 .pwr_w_mask = (pwr) << 16, \
102 .status_mask = (status), \
103 .req_w_mask = (req) << 16, \
105 .idle_mask = (idle), \
107 .active_wakeup = wakeup, \
110 #define DOMAIN_RK3036(req, ack, idle, wakeup) \
113 .req_w_mask = (req) << 16, \
115 .idle_mask = (idle), \
116 .active_wakeup = wakeup, \
119 #define DOMAIN_PX30(pwr, status, req, wakeup) \
120 DOMAIN_M(pwr, status, req, (req) << 16, req, wakeup)
122 #define DOMAIN_RK3288(pwr, status, req, wakeup) \
123 DOMAIN(pwr, status, req, req, (req) << 16, wakeup)
125 #define DOMAIN_RK3328(pwr, status, req, wakeup) \
126 DOMAIN_M(pwr, pwr, req, (req) << 10, req, wakeup)
128 #define DOMAIN_RK3368(pwr, status, req, wakeup) \
129 DOMAIN(pwr, status, req, (req) << 16, req, wakeup)
131 #define DOMAIN_RK3399(pwr, status, req, wakeup) \
132 DOMAIN(pwr, status, req, req, req, wakeup)
134 static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain
*pd
)
136 struct rockchip_pmu
*pmu
= pd
->pmu
;
137 const struct rockchip_domain_info
*pd_info
= pd
->info
;
140 regmap_read(pmu
->regmap
, pmu
->info
->idle_offset
, &val
);
141 return (val
& pd_info
->idle_mask
) == pd_info
->idle_mask
;
144 static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu
*pmu
)
148 regmap_read(pmu
->regmap
, pmu
->info
->ack_offset
, &val
);
152 static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain
*pd
,
155 const struct rockchip_domain_info
*pd_info
= pd
->info
;
156 struct generic_pm_domain
*genpd
= &pd
->genpd
;
157 struct rockchip_pmu
*pmu
= pd
->pmu
;
158 unsigned int target_ack
;
163 if (pd_info
->req_mask
== 0)
165 else if (pd_info
->req_w_mask
)
166 regmap_write(pmu
->regmap
, pmu
->info
->req_offset
,
167 idle
? (pd_info
->req_mask
| pd_info
->req_w_mask
) :
168 pd_info
->req_w_mask
);
170 regmap_update_bits(pmu
->regmap
, pmu
->info
->req_offset
,
171 pd_info
->req_mask
, idle
? -1U : 0);
175 /* Wait util idle_ack = 1 */
176 target_ack
= idle
? pd_info
->ack_mask
: 0;
177 ret
= readx_poll_timeout_atomic(rockchip_pmu_read_ack
, pmu
, val
,
178 (val
& pd_info
->ack_mask
) == target_ack
,
182 "failed to get ack on domain '%s', val=0x%x\n",
187 ret
= readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle
, pd
,
188 is_idle
, is_idle
== idle
, 0, 10000);
191 "failed to set idle on domain '%s', val=%d\n",
192 genpd
->name
, is_idle
);
199 static int rockchip_pmu_save_qos(struct rockchip_pm_domain
*pd
)
203 for (i
= 0; i
< pd
->num_qos
; i
++) {
204 regmap_read(pd
->qos_regmap
[i
],
206 &pd
->qos_save_regs
[0][i
]);
207 regmap_read(pd
->qos_regmap
[i
],
209 &pd
->qos_save_regs
[1][i
]);
210 regmap_read(pd
->qos_regmap
[i
],
212 &pd
->qos_save_regs
[2][i
]);
213 regmap_read(pd
->qos_regmap
[i
],
215 &pd
->qos_save_regs
[3][i
]);
216 regmap_read(pd
->qos_regmap
[i
],
218 &pd
->qos_save_regs
[4][i
]);
223 static int rockchip_pmu_restore_qos(struct rockchip_pm_domain
*pd
)
227 for (i
= 0; i
< pd
->num_qos
; i
++) {
228 regmap_write(pd
->qos_regmap
[i
],
230 pd
->qos_save_regs
[0][i
]);
231 regmap_write(pd
->qos_regmap
[i
],
233 pd
->qos_save_regs
[1][i
]);
234 regmap_write(pd
->qos_regmap
[i
],
236 pd
->qos_save_regs
[2][i
]);
237 regmap_write(pd
->qos_regmap
[i
],
239 pd
->qos_save_regs
[3][i
]);
240 regmap_write(pd
->qos_regmap
[i
],
242 pd
->qos_save_regs
[4][i
]);
248 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain
*pd
)
250 struct rockchip_pmu
*pmu
= pd
->pmu
;
253 /* check idle status for idle-only domains */
254 if (pd
->info
->status_mask
== 0)
255 return !rockchip_pmu_domain_is_idle(pd
);
257 regmap_read(pmu
->regmap
, pmu
->info
->status_offset
, &val
);
259 /* 1'b0: power on, 1'b1: power off */
260 return !(val
& pd
->info
->status_mask
);
263 static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain
*pd
,
266 struct rockchip_pmu
*pmu
= pd
->pmu
;
267 struct generic_pm_domain
*genpd
= &pd
->genpd
;
270 if (pd
->info
->pwr_mask
== 0)
272 else if (pd
->info
->pwr_w_mask
)
273 regmap_write(pmu
->regmap
, pmu
->info
->pwr_offset
,
274 on
? pd
->info
->pwr_w_mask
:
275 (pd
->info
->pwr_mask
| pd
->info
->pwr_w_mask
));
277 regmap_update_bits(pmu
->regmap
, pmu
->info
->pwr_offset
,
278 pd
->info
->pwr_mask
, on
? 0 : -1U);
282 if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on
, pd
, is_on
,
283 is_on
== on
, 0, 10000)) {
285 "failed to set domain '%s', val=%d\n",
291 static int rockchip_pd_power(struct rockchip_pm_domain
*pd
, bool power_on
)
293 struct rockchip_pmu
*pmu
= pd
->pmu
;
296 mutex_lock(&pmu
->mutex
);
298 if (rockchip_pmu_domain_is_on(pd
) != power_on
) {
299 ret
= clk_bulk_enable(pd
->num_clks
, pd
->clks
);
301 dev_err(pmu
->dev
, "failed to enable clocks\n");
302 mutex_unlock(&pmu
->mutex
);
307 rockchip_pmu_save_qos(pd
);
309 /* if powering down, idle request to NIU first */
310 rockchip_pmu_set_idle_request(pd
, true);
313 rockchip_do_pmu_set_power_domain(pd
, power_on
);
316 /* if powering up, leave idle mode */
317 rockchip_pmu_set_idle_request(pd
, false);
319 rockchip_pmu_restore_qos(pd
);
322 clk_bulk_disable(pd
->num_clks
, pd
->clks
);
325 mutex_unlock(&pmu
->mutex
);
329 static int rockchip_pd_power_on(struct generic_pm_domain
*domain
)
331 struct rockchip_pm_domain
*pd
= to_rockchip_pd(domain
);
333 return rockchip_pd_power(pd
, true);
336 static int rockchip_pd_power_off(struct generic_pm_domain
*domain
)
338 struct rockchip_pm_domain
*pd
= to_rockchip_pd(domain
);
340 return rockchip_pd_power(pd
, false);
343 static int rockchip_pd_attach_dev(struct generic_pm_domain
*genpd
,
350 dev_dbg(dev
, "attaching to power domain '%s'\n", genpd
->name
);
352 error
= pm_clk_create(dev
);
354 dev_err(dev
, "pm_clk_create failed %d\n", error
);
359 while ((clk
= of_clk_get(dev
->of_node
, i
++)) && !IS_ERR(clk
)) {
360 dev_dbg(dev
, "adding clock '%pC' to list of PM clocks\n", clk
);
361 error
= pm_clk_add_clk(dev
, clk
);
363 dev_err(dev
, "pm_clk_add_clk failed %d\n", error
);
373 static void rockchip_pd_detach_dev(struct generic_pm_domain
*genpd
,
376 dev_dbg(dev
, "detaching from power domain '%s'\n", genpd
->name
);
381 static int rockchip_pm_add_one_domain(struct rockchip_pmu
*pmu
,
382 struct device_node
*node
)
384 const struct rockchip_domain_info
*pd_info
;
385 struct rockchip_pm_domain
*pd
;
386 struct device_node
*qos_node
;
391 error
= of_property_read_u32(node
, "reg", &id
);
394 "%pOFn: failed to retrieve domain id (reg): %d\n",
399 if (id
>= pmu
->info
->num_domains
) {
400 dev_err(pmu
->dev
, "%pOFn: invalid domain id %d\n",
405 pd_info
= &pmu
->info
->domain_info
[id
];
407 dev_err(pmu
->dev
, "%pOFn: undefined domain id %d\n",
412 pd
= devm_kzalloc(pmu
->dev
, sizeof(*pd
), GFP_KERNEL
);
419 pd
->num_clks
= of_clk_get_parent_count(node
);
420 if (pd
->num_clks
> 0) {
421 pd
->clks
= devm_kcalloc(pmu
->dev
, pd
->num_clks
,
422 sizeof(*pd
->clks
), GFP_KERNEL
);
426 dev_dbg(pmu
->dev
, "%pOFn: doesn't have clocks: %d\n",
431 for (i
= 0; i
< pd
->num_clks
; i
++) {
432 pd
->clks
[i
].clk
= of_clk_get(node
, i
);
433 if (IS_ERR(pd
->clks
[i
].clk
)) {
434 error
= PTR_ERR(pd
->clks
[i
].clk
);
436 "%pOFn: failed to get clk at index %d: %d\n",
442 error
= clk_bulk_prepare(pd
->num_clks
, pd
->clks
);
446 pd
->num_qos
= of_count_phandle_with_args(node
, "pm_qos",
449 if (pd
->num_qos
> 0) {
450 pd
->qos_regmap
= devm_kcalloc(pmu
->dev
, pd
->num_qos
,
451 sizeof(*pd
->qos_regmap
),
453 if (!pd
->qos_regmap
) {
455 goto err_unprepare_clocks
;
458 for (j
= 0; j
< MAX_QOS_REGS_NUM
; j
++) {
459 pd
->qos_save_regs
[j
] = devm_kcalloc(pmu
->dev
,
463 if (!pd
->qos_save_regs
[j
]) {
465 goto err_unprepare_clocks
;
469 for (j
= 0; j
< pd
->num_qos
; j
++) {
470 qos_node
= of_parse_phandle(node
, "pm_qos", j
);
473 goto err_unprepare_clocks
;
475 pd
->qos_regmap
[j
] = syscon_node_to_regmap(qos_node
);
476 if (IS_ERR(pd
->qos_regmap
[j
])) {
478 of_node_put(qos_node
);
479 goto err_unprepare_clocks
;
481 of_node_put(qos_node
);
485 error
= rockchip_pd_power(pd
, true);
488 "failed to power on domain '%pOFn': %d\n",
490 goto err_unprepare_clocks
;
493 pd
->genpd
.name
= node
->name
;
494 pd
->genpd
.power_off
= rockchip_pd_power_off
;
495 pd
->genpd
.power_on
= rockchip_pd_power_on
;
496 pd
->genpd
.attach_dev
= rockchip_pd_attach_dev
;
497 pd
->genpd
.detach_dev
= rockchip_pd_detach_dev
;
498 pd
->genpd
.flags
= GENPD_FLAG_PM_CLK
;
499 if (pd_info
->active_wakeup
)
500 pd
->genpd
.flags
|= GENPD_FLAG_ACTIVE_WAKEUP
;
501 pm_genpd_init(&pd
->genpd
, NULL
, false);
503 pmu
->genpd_data
.domains
[id
] = &pd
->genpd
;
506 err_unprepare_clocks
:
507 clk_bulk_unprepare(pd
->num_clks
, pd
->clks
);
509 clk_bulk_put(pd
->num_clks
, pd
->clks
);
513 static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain
*pd
)
518 * We're in the error cleanup already, so we only complain,
519 * but won't emit another error on top of the original one.
521 ret
= pm_genpd_remove(&pd
->genpd
);
523 dev_err(pd
->pmu
->dev
, "failed to remove domain '%s' : %d - state may be inconsistent\n",
524 pd
->genpd
.name
, ret
);
526 clk_bulk_unprepare(pd
->num_clks
, pd
->clks
);
527 clk_bulk_put(pd
->num_clks
, pd
->clks
);
529 /* protect the zeroing of pm->num_clks */
530 mutex_lock(&pd
->pmu
->mutex
);
532 mutex_unlock(&pd
->pmu
->mutex
);
534 /* devm will free our memory */
537 static void rockchip_pm_domain_cleanup(struct rockchip_pmu
*pmu
)
539 struct generic_pm_domain
*genpd
;
540 struct rockchip_pm_domain
*pd
;
543 for (i
= 0; i
< pmu
->genpd_data
.num_domains
; i
++) {
544 genpd
= pmu
->genpd_data
.domains
[i
];
546 pd
= to_rockchip_pd(genpd
);
547 rockchip_pm_remove_one_domain(pd
);
551 /* devm will free our memory */
554 static void rockchip_configure_pd_cnt(struct rockchip_pmu
*pmu
,
555 u32 domain_reg_offset
,
558 /* First configure domain power down transition count ... */
559 regmap_write(pmu
->regmap
, domain_reg_offset
, count
);
560 /* ... and then power up count. */
561 regmap_write(pmu
->regmap
, domain_reg_offset
+ 4, count
);
564 static int rockchip_pm_add_subdomain(struct rockchip_pmu
*pmu
,
565 struct device_node
*parent
)
567 struct device_node
*np
;
568 struct generic_pm_domain
*child_domain
, *parent_domain
;
571 for_each_child_of_node(parent
, np
) {
574 error
= of_property_read_u32(parent
, "reg", &idx
);
577 "%pOFn: failed to retrieve domain id (reg): %d\n",
581 parent_domain
= pmu
->genpd_data
.domains
[idx
];
583 error
= rockchip_pm_add_one_domain(pmu
, np
);
585 dev_err(pmu
->dev
, "failed to handle node %pOFn: %d\n",
590 error
= of_property_read_u32(np
, "reg", &idx
);
593 "%pOFn: failed to retrieve domain id (reg): %d\n",
597 child_domain
= pmu
->genpd_data
.domains
[idx
];
599 error
= pm_genpd_add_subdomain(parent_domain
, child_domain
);
601 dev_err(pmu
->dev
, "%s failed to add subdomain %s: %d\n",
602 parent_domain
->name
, child_domain
->name
, error
);
605 dev_dbg(pmu
->dev
, "%s add subdomain: %s\n",
606 parent_domain
->name
, child_domain
->name
);
609 rockchip_pm_add_subdomain(pmu
, np
);
619 static int rockchip_pm_domain_probe(struct platform_device
*pdev
)
621 struct device
*dev
= &pdev
->dev
;
622 struct device_node
*np
= dev
->of_node
;
623 struct device_node
*node
;
624 struct device
*parent
;
625 struct rockchip_pmu
*pmu
;
626 const struct of_device_id
*match
;
627 const struct rockchip_pmu_info
*pmu_info
;
631 dev_err(dev
, "device tree node not found\n");
635 match
= of_match_device(dev
->driver
->of_match_table
, dev
);
636 if (!match
|| !match
->data
) {
637 dev_err(dev
, "missing pmu data\n");
641 pmu_info
= match
->data
;
643 pmu
= devm_kzalloc(dev
,
644 struct_size(pmu
, domains
, pmu_info
->num_domains
),
649 pmu
->dev
= &pdev
->dev
;
650 mutex_init(&pmu
->mutex
);
652 pmu
->info
= pmu_info
;
654 pmu
->genpd_data
.domains
= pmu
->domains
;
655 pmu
->genpd_data
.num_domains
= pmu_info
->num_domains
;
657 parent
= dev
->parent
;
659 dev_err(dev
, "no parent for syscon devices\n");
663 pmu
->regmap
= syscon_node_to_regmap(parent
->of_node
);
664 if (IS_ERR(pmu
->regmap
)) {
665 dev_err(dev
, "no regmap available\n");
666 return PTR_ERR(pmu
->regmap
);
670 * Configure power up and down transition delays for CORE
673 if (pmu_info
->core_power_transition_time
)
674 rockchip_configure_pd_cnt(pmu
, pmu_info
->core_pwrcnt_offset
,
675 pmu_info
->core_power_transition_time
);
676 if (pmu_info
->gpu_pwrcnt_offset
)
677 rockchip_configure_pd_cnt(pmu
, pmu_info
->gpu_pwrcnt_offset
,
678 pmu_info
->gpu_power_transition_time
);
682 for_each_available_child_of_node(np
, node
) {
683 error
= rockchip_pm_add_one_domain(pmu
, node
);
685 dev_err(dev
, "failed to handle node %pOFn: %d\n",
691 error
= rockchip_pm_add_subdomain(pmu
, node
);
693 dev_err(dev
, "failed to handle subdomain node %pOFn: %d\n",
701 dev_dbg(dev
, "no power domains defined\n");
705 error
= of_genpd_add_provider_onecell(np
, &pmu
->genpd_data
);
707 dev_err(dev
, "failed to add provider: %d\n", error
);
714 rockchip_pm_domain_cleanup(pmu
);
718 static const struct rockchip_domain_info px30_pm_domains
[] = {
719 [PX30_PD_USB
] = DOMAIN_PX30(BIT(5), BIT(5), BIT(10), false),
720 [PX30_PD_SDCARD
] = DOMAIN_PX30(BIT(8), BIT(8), BIT(9), false),
721 [PX30_PD_GMAC
] = DOMAIN_PX30(BIT(10), BIT(10), BIT(6), false),
722 [PX30_PD_MMC_NAND
] = DOMAIN_PX30(BIT(11), BIT(11), BIT(5), false),
723 [PX30_PD_VPU
] = DOMAIN_PX30(BIT(12), BIT(12), BIT(14), false),
724 [PX30_PD_VO
] = DOMAIN_PX30(BIT(13), BIT(13), BIT(7), false),
725 [PX30_PD_VI
] = DOMAIN_PX30(BIT(14), BIT(14), BIT(8), false),
726 [PX30_PD_GPU
] = DOMAIN_PX30(BIT(15), BIT(15), BIT(2), false),
729 static const struct rockchip_domain_info rk3036_pm_domains
[] = {
730 [RK3036_PD_MSCH
] = DOMAIN_RK3036(BIT(14), BIT(23), BIT(30), true),
731 [RK3036_PD_CORE
] = DOMAIN_RK3036(BIT(13), BIT(17), BIT(24), false),
732 [RK3036_PD_PERI
] = DOMAIN_RK3036(BIT(12), BIT(18), BIT(25), false),
733 [RK3036_PD_VIO
] = DOMAIN_RK3036(BIT(11), BIT(19), BIT(26), false),
734 [RK3036_PD_VPU
] = DOMAIN_RK3036(BIT(10), BIT(20), BIT(27), false),
735 [RK3036_PD_GPU
] = DOMAIN_RK3036(BIT(9), BIT(21), BIT(28), false),
736 [RK3036_PD_SYS
] = DOMAIN_RK3036(BIT(8), BIT(22), BIT(29), false),
739 static const struct rockchip_domain_info rk3066_pm_domains
[] = {
740 [RK3066_PD_GPU
] = DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
741 [RK3066_PD_VIDEO
] = DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
742 [RK3066_PD_VIO
] = DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
743 [RK3066_PD_PERI
] = DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
744 [RK3066_PD_CPU
] = DOMAIN(0, BIT(5), BIT(1), BIT(26), BIT(31), false),
747 static const struct rockchip_domain_info rk3128_pm_domains
[] = {
748 [RK3128_PD_CORE
] = DOMAIN_RK3288(BIT(0), BIT(0), BIT(4), false),
749 [RK3128_PD_MSCH
] = DOMAIN_RK3288(0, 0, BIT(6), true),
750 [RK3128_PD_VIO
] = DOMAIN_RK3288(BIT(3), BIT(3), BIT(2), false),
751 [RK3128_PD_VIDEO
] = DOMAIN_RK3288(BIT(2), BIT(2), BIT(1), false),
752 [RK3128_PD_GPU
] = DOMAIN_RK3288(BIT(1), BIT(1), BIT(3), false),
755 static const struct rockchip_domain_info rk3188_pm_domains
[] = {
756 [RK3188_PD_GPU
] = DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
757 [RK3188_PD_VIDEO
] = DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
758 [RK3188_PD_VIO
] = DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
759 [RK3188_PD_PERI
] = DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
760 [RK3188_PD_CPU
] = DOMAIN(BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
763 static const struct rockchip_domain_info rk3228_pm_domains
[] = {
764 [RK3228_PD_CORE
] = DOMAIN_RK3036(BIT(0), BIT(0), BIT(16), true),
765 [RK3228_PD_MSCH
] = DOMAIN_RK3036(BIT(1), BIT(1), BIT(17), true),
766 [RK3228_PD_BUS
] = DOMAIN_RK3036(BIT(2), BIT(2), BIT(18), true),
767 [RK3228_PD_SYS
] = DOMAIN_RK3036(BIT(3), BIT(3), BIT(19), true),
768 [RK3228_PD_VIO
] = DOMAIN_RK3036(BIT(4), BIT(4), BIT(20), false),
769 [RK3228_PD_VOP
] = DOMAIN_RK3036(BIT(5), BIT(5), BIT(21), false),
770 [RK3228_PD_VPU
] = DOMAIN_RK3036(BIT(6), BIT(6), BIT(22), false),
771 [RK3228_PD_RKVDEC
] = DOMAIN_RK3036(BIT(7), BIT(7), BIT(23), false),
772 [RK3228_PD_GPU
] = DOMAIN_RK3036(BIT(8), BIT(8), BIT(24), false),
773 [RK3228_PD_PERI
] = DOMAIN_RK3036(BIT(9), BIT(9), BIT(25), true),
774 [RK3228_PD_GMAC
] = DOMAIN_RK3036(BIT(10), BIT(10), BIT(26), false),
777 static const struct rockchip_domain_info rk3288_pm_domains
[] = {
778 [RK3288_PD_VIO
] = DOMAIN_RK3288(BIT(7), BIT(7), BIT(4), false),
779 [RK3288_PD_HEVC
] = DOMAIN_RK3288(BIT(14), BIT(10), BIT(9), false),
780 [RK3288_PD_VIDEO
] = DOMAIN_RK3288(BIT(8), BIT(8), BIT(3), false),
781 [RK3288_PD_GPU
] = DOMAIN_RK3288(BIT(9), BIT(9), BIT(2), false),
784 static const struct rockchip_domain_info rk3328_pm_domains
[] = {
785 [RK3328_PD_CORE
] = DOMAIN_RK3328(0, BIT(0), BIT(0), false),
786 [RK3328_PD_GPU
] = DOMAIN_RK3328(0, BIT(1), BIT(1), false),
787 [RK3328_PD_BUS
] = DOMAIN_RK3328(0, BIT(2), BIT(2), true),
788 [RK3328_PD_MSCH
] = DOMAIN_RK3328(0, BIT(3), BIT(3), true),
789 [RK3328_PD_PERI
] = DOMAIN_RK3328(0, BIT(4), BIT(4), true),
790 [RK3328_PD_VIDEO
] = DOMAIN_RK3328(0, BIT(5), BIT(5), false),
791 [RK3328_PD_HEVC
] = DOMAIN_RK3328(0, BIT(6), BIT(6), false),
792 [RK3328_PD_VIO
] = DOMAIN_RK3328(0, BIT(8), BIT(8), false),
793 [RK3328_PD_VPU
] = DOMAIN_RK3328(0, BIT(9), BIT(9), false),
796 static const struct rockchip_domain_info rk3366_pm_domains
[] = {
797 [RK3366_PD_PERI
] = DOMAIN_RK3368(BIT(10), BIT(10), BIT(6), true),
798 [RK3366_PD_VIO
] = DOMAIN_RK3368(BIT(14), BIT(14), BIT(8), false),
799 [RK3366_PD_VIDEO
] = DOMAIN_RK3368(BIT(13), BIT(13), BIT(7), false),
800 [RK3366_PD_RKVDEC
] = DOMAIN_RK3368(BIT(11), BIT(11), BIT(7), false),
801 [RK3366_PD_WIFIBT
] = DOMAIN_RK3368(BIT(8), BIT(8), BIT(9), false),
802 [RK3366_PD_VPU
] = DOMAIN_RK3368(BIT(12), BIT(12), BIT(7), false),
803 [RK3366_PD_GPU
] = DOMAIN_RK3368(BIT(15), BIT(15), BIT(2), false),
806 static const struct rockchip_domain_info rk3368_pm_domains
[] = {
807 [RK3368_PD_PERI
] = DOMAIN_RK3368(BIT(13), BIT(12), BIT(6), true),
808 [RK3368_PD_VIO
] = DOMAIN_RK3368(BIT(15), BIT(14), BIT(8), false),
809 [RK3368_PD_VIDEO
] = DOMAIN_RK3368(BIT(14), BIT(13), BIT(7), false),
810 [RK3368_PD_GPU_0
] = DOMAIN_RK3368(BIT(16), BIT(15), BIT(2), false),
811 [RK3368_PD_GPU_1
] = DOMAIN_RK3368(BIT(17), BIT(16), BIT(2), false),
814 static const struct rockchip_domain_info rk3399_pm_domains
[] = {
815 [RK3399_PD_TCPD0
] = DOMAIN_RK3399(BIT(8), BIT(8), 0, false),
816 [RK3399_PD_TCPD1
] = DOMAIN_RK3399(BIT(9), BIT(9), 0, false),
817 [RK3399_PD_CCI
] = DOMAIN_RK3399(BIT(10), BIT(10), 0, true),
818 [RK3399_PD_CCI0
] = DOMAIN_RK3399(0, 0, BIT(15), true),
819 [RK3399_PD_CCI1
] = DOMAIN_RK3399(0, 0, BIT(16), true),
820 [RK3399_PD_PERILP
] = DOMAIN_RK3399(BIT(11), BIT(11), BIT(1), true),
821 [RK3399_PD_PERIHP
] = DOMAIN_RK3399(BIT(12), BIT(12), BIT(2), true),
822 [RK3399_PD_CENTER
] = DOMAIN_RK3399(BIT(13), BIT(13), BIT(14), true),
823 [RK3399_PD_VIO
] = DOMAIN_RK3399(BIT(14), BIT(14), BIT(17), false),
824 [RK3399_PD_GPU
] = DOMAIN_RK3399(BIT(15), BIT(15), BIT(0), false),
825 [RK3399_PD_VCODEC
] = DOMAIN_RK3399(BIT(16), BIT(16), BIT(3), false),
826 [RK3399_PD_VDU
] = DOMAIN_RK3399(BIT(17), BIT(17), BIT(4), false),
827 [RK3399_PD_RGA
] = DOMAIN_RK3399(BIT(18), BIT(18), BIT(5), false),
828 [RK3399_PD_IEP
] = DOMAIN_RK3399(BIT(19), BIT(19), BIT(6), false),
829 [RK3399_PD_VO
] = DOMAIN_RK3399(BIT(20), BIT(20), 0, false),
830 [RK3399_PD_VOPB
] = DOMAIN_RK3399(0, 0, BIT(7), false),
831 [RK3399_PD_VOPL
] = DOMAIN_RK3399(0, 0, BIT(8), false),
832 [RK3399_PD_ISP0
] = DOMAIN_RK3399(BIT(22), BIT(22), BIT(9), false),
833 [RK3399_PD_ISP1
] = DOMAIN_RK3399(BIT(23), BIT(23), BIT(10), false),
834 [RK3399_PD_HDCP
] = DOMAIN_RK3399(BIT(24), BIT(24), BIT(11), false),
835 [RK3399_PD_GMAC
] = DOMAIN_RK3399(BIT(25), BIT(25), BIT(23), true),
836 [RK3399_PD_EMMC
] = DOMAIN_RK3399(BIT(26), BIT(26), BIT(24), true),
837 [RK3399_PD_USB3
] = DOMAIN_RK3399(BIT(27), BIT(27), BIT(12), true),
838 [RK3399_PD_EDP
] = DOMAIN_RK3399(BIT(28), BIT(28), BIT(22), false),
839 [RK3399_PD_GIC
] = DOMAIN_RK3399(BIT(29), BIT(29), BIT(27), true),
840 [RK3399_PD_SD
] = DOMAIN_RK3399(BIT(30), BIT(30), BIT(28), true),
841 [RK3399_PD_SDIOAUDIO
] = DOMAIN_RK3399(BIT(31), BIT(31), BIT(29), true),
844 static const struct rockchip_pmu_info px30_pmu
= {
846 .status_offset
= 0x20,
851 .num_domains
= ARRAY_SIZE(px30_pm_domains
),
852 .domain_info
= px30_pm_domains
,
855 static const struct rockchip_pmu_info rk3036_pmu
= {
857 .idle_offset
= 0x14c,
860 .num_domains
= ARRAY_SIZE(rk3036_pm_domains
),
861 .domain_info
= rk3036_pm_domains
,
864 static const struct rockchip_pmu_info rk3066_pmu
= {
866 .status_offset
= 0x0c,
867 .req_offset
= 0x38, /* PMU_MISC_CON1 */
871 .num_domains
= ARRAY_SIZE(rk3066_pm_domains
),
872 .domain_info
= rk3066_pm_domains
,
875 static const struct rockchip_pmu_info rk3128_pmu
= {
877 .status_offset
= 0x08,
882 .num_domains
= ARRAY_SIZE(rk3128_pm_domains
),
883 .domain_info
= rk3128_pm_domains
,
886 static const struct rockchip_pmu_info rk3188_pmu
= {
888 .status_offset
= 0x0c,
889 .req_offset
= 0x38, /* PMU_MISC_CON1 */
893 .num_domains
= ARRAY_SIZE(rk3188_pm_domains
),
894 .domain_info
= rk3188_pm_domains
,
897 static const struct rockchip_pmu_info rk3228_pmu
= {
899 .idle_offset
= 0x488,
902 .num_domains
= ARRAY_SIZE(rk3228_pm_domains
),
903 .domain_info
= rk3228_pm_domains
,
906 static const struct rockchip_pmu_info rk3288_pmu
= {
908 .status_offset
= 0x0c,
913 .core_pwrcnt_offset
= 0x34,
914 .gpu_pwrcnt_offset
= 0x3c,
916 .core_power_transition_time
= 24, /* 1us */
917 .gpu_power_transition_time
= 24, /* 1us */
919 .num_domains
= ARRAY_SIZE(rk3288_pm_domains
),
920 .domain_info
= rk3288_pm_domains
,
923 static const struct rockchip_pmu_info rk3328_pmu
= {
925 .idle_offset
= 0x484,
928 .num_domains
= ARRAY_SIZE(rk3328_pm_domains
),
929 .domain_info
= rk3328_pm_domains
,
932 static const struct rockchip_pmu_info rk3366_pmu
= {
934 .status_offset
= 0x10,
939 .core_pwrcnt_offset
= 0x48,
940 .gpu_pwrcnt_offset
= 0x50,
942 .core_power_transition_time
= 24,
943 .gpu_power_transition_time
= 24,
945 .num_domains
= ARRAY_SIZE(rk3366_pm_domains
),
946 .domain_info
= rk3366_pm_domains
,
949 static const struct rockchip_pmu_info rk3368_pmu
= {
951 .status_offset
= 0x10,
956 .core_pwrcnt_offset
= 0x48,
957 .gpu_pwrcnt_offset
= 0x50,
959 .core_power_transition_time
= 24,
960 .gpu_power_transition_time
= 24,
962 .num_domains
= ARRAY_SIZE(rk3368_pm_domains
),
963 .domain_info
= rk3368_pm_domains
,
966 static const struct rockchip_pmu_info rk3399_pmu
= {
968 .status_offset
= 0x18,
973 /* ARM Trusted Firmware manages power transition times */
975 .num_domains
= ARRAY_SIZE(rk3399_pm_domains
),
976 .domain_info
= rk3399_pm_domains
,
979 static const struct of_device_id rockchip_pm_domain_dt_match
[] = {
981 .compatible
= "rockchip,px30-power-controller",
982 .data
= (void *)&px30_pmu
,
985 .compatible
= "rockchip,rk3036-power-controller",
986 .data
= (void *)&rk3036_pmu
,
989 .compatible
= "rockchip,rk3066-power-controller",
990 .data
= (void *)&rk3066_pmu
,
993 .compatible
= "rockchip,rk3128-power-controller",
994 .data
= (void *)&rk3128_pmu
,
997 .compatible
= "rockchip,rk3188-power-controller",
998 .data
= (void *)&rk3188_pmu
,
1001 .compatible
= "rockchip,rk3228-power-controller",
1002 .data
= (void *)&rk3228_pmu
,
1005 .compatible
= "rockchip,rk3288-power-controller",
1006 .data
= (void *)&rk3288_pmu
,
1009 .compatible
= "rockchip,rk3328-power-controller",
1010 .data
= (void *)&rk3328_pmu
,
1013 .compatible
= "rockchip,rk3366-power-controller",
1014 .data
= (void *)&rk3366_pmu
,
1017 .compatible
= "rockchip,rk3368-power-controller",
1018 .data
= (void *)&rk3368_pmu
,
1021 .compatible
= "rockchip,rk3399-power-controller",
1022 .data
= (void *)&rk3399_pmu
,
1027 static struct platform_driver rockchip_pm_domain_driver
= {
1028 .probe
= rockchip_pm_domain_probe
,
1030 .name
= "rockchip-pm-domain",
1031 .of_match_table
= rockchip_pm_domain_dt_match
,
1033 * We can't forcibly eject devices form power domain,
1034 * so we can't really remove power domains once they
1037 .suppress_bind_attrs
= true,
1041 static int __init
rockchip_pm_domain_drv_register(void)
1043 return platform_driver_register(&rockchip_pm_domain_driver
);
1045 postcore_initcall(rockchip_pm_domain_drv_register
);