This source file includes following definitions.
- rockchip_pmu_domain_is_idle
- rockchip_pmu_read_ack
- rockchip_pmu_set_idle_request
- rockchip_pmu_save_qos
- rockchip_pmu_restore_qos
- rockchip_pmu_domain_is_on
- rockchip_do_pmu_set_power_domain
- rockchip_pd_power
- rockchip_pd_power_on
- rockchip_pd_power_off
- rockchip_pd_attach_dev
- rockchip_pd_detach_dev
- rockchip_pm_add_one_domain
- rockchip_pm_remove_one_domain
- rockchip_pm_domain_cleanup
- rockchip_configure_pd_cnt
- rockchip_pm_add_subdomain
- rockchip_pm_domain_probe
- rockchip_pm_domain_drv_register
1
2
3
4
5
6
7
8 #include <linux/io.h>
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>
30
31 struct rockchip_domain_info {
32 int pwr_mask;
33 int status_mask;
34 int req_mask;
35 int idle_mask;
36 int ack_mask;
37 bool active_wakeup;
38 int pwr_w_mask;
39 int req_w_mask;
40 };
41
42 struct rockchip_pmu_info {
43 u32 pwr_offset;
44 u32 status_offset;
45 u32 req_offset;
46 u32 idle_offset;
47 u32 ack_offset;
48
49 u32 core_pwrcnt_offset;
50 u32 gpu_pwrcnt_offset;
51
52 unsigned int core_power_transition_time;
53 unsigned int gpu_power_transition_time;
54
55 int num_domains;
56 const struct rockchip_domain_info *domain_info;
57 };
58
59 #define MAX_QOS_REGS_NUM 5
60 #define QOS_PRIORITY 0x08
61 #define QOS_MODE 0x0c
62 #define QOS_BANDWIDTH 0x10
63 #define QOS_SATURATION 0x14
64 #define QOS_EXTCONTROL 0x18
65
66 struct rockchip_pm_domain {
67 struct generic_pm_domain genpd;
68 const struct rockchip_domain_info *info;
69 struct rockchip_pmu *pmu;
70 int num_qos;
71 struct regmap **qos_regmap;
72 u32 *qos_save_regs[MAX_QOS_REGS_NUM];
73 int num_clks;
74 struct clk_bulk_data *clks;
75 };
76
77 struct rockchip_pmu {
78 struct device *dev;
79 struct regmap *regmap;
80 const struct rockchip_pmu_info *info;
81 struct mutex mutex;
82 struct genpd_onecell_data genpd_data;
83 struct generic_pm_domain *domains[];
84 };
85
86 #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
87
88 #define DOMAIN(pwr, status, req, idle, ack, wakeup) \
89 { \
90 .pwr_mask = (pwr), \
91 .status_mask = (status), \
92 .req_mask = (req), \
93 .idle_mask = (idle), \
94 .ack_mask = (ack), \
95 .active_wakeup = (wakeup), \
96 }
97
98 #define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
99 { \
100 .pwr_w_mask = (pwr) << 16, \
101 .pwr_mask = (pwr), \
102 .status_mask = (status), \
103 .req_w_mask = (req) << 16, \
104 .req_mask = (req), \
105 .idle_mask = (idle), \
106 .ack_mask = (ack), \
107 .active_wakeup = wakeup, \
108 }
109
110 #define DOMAIN_RK3036(req, ack, idle, wakeup) \
111 { \
112 .req_mask = (req), \
113 .req_w_mask = (req) << 16, \
114 .ack_mask = (ack), \
115 .idle_mask = (idle), \
116 .active_wakeup = wakeup, \
117 }
118
119 #define DOMAIN_PX30(pwr, status, req, wakeup) \
120 DOMAIN_M(pwr, status, req, (req) << 16, req, wakeup)
121
122 #define DOMAIN_RK3288(pwr, status, req, wakeup) \
123 DOMAIN(pwr, status, req, req, (req) << 16, wakeup)
124
125 #define DOMAIN_RK3328(pwr, status, req, wakeup) \
126 DOMAIN_M(pwr, pwr, req, (req) << 10, req, wakeup)
127
128 #define DOMAIN_RK3368(pwr, status, req, wakeup) \
129 DOMAIN(pwr, status, req, (req) << 16, req, wakeup)
130
131 #define DOMAIN_RK3399(pwr, status, req, wakeup) \
132 DOMAIN(pwr, status, req, req, req, wakeup)
133
134 static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
135 {
136 struct rockchip_pmu *pmu = pd->pmu;
137 const struct rockchip_domain_info *pd_info = pd->info;
138 unsigned int val;
139
140 regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
141 return (val & pd_info->idle_mask) == pd_info->idle_mask;
142 }
143
144 static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
145 {
146 unsigned int val;
147
148 regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
149 return val;
150 }
151
152 static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
153 bool idle)
154 {
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;
159 unsigned int val;
160 bool is_idle;
161 int ret;
162
163 if (pd_info->req_mask == 0)
164 return 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);
169 else
170 regmap_update_bits(pmu->regmap, pmu->info->req_offset,
171 pd_info->req_mask, idle ? -1U : 0);
172
173 dsb(sy);
174
175
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,
179 0, 10000);
180 if (ret) {
181 dev_err(pmu->dev,
182 "failed to get ack on domain '%s', val=0x%x\n",
183 genpd->name, val);
184 return ret;
185 }
186
187 ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
188 is_idle, is_idle == idle, 0, 10000);
189 if (ret) {
190 dev_err(pmu->dev,
191 "failed to set idle on domain '%s', val=%d\n",
192 genpd->name, is_idle);
193 return ret;
194 }
195
196 return 0;
197 }
198
199 static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
200 {
201 int i;
202
203 for (i = 0; i < pd->num_qos; i++) {
204 regmap_read(pd->qos_regmap[i],
205 QOS_PRIORITY,
206 &pd->qos_save_regs[0][i]);
207 regmap_read(pd->qos_regmap[i],
208 QOS_MODE,
209 &pd->qos_save_regs[1][i]);
210 regmap_read(pd->qos_regmap[i],
211 QOS_BANDWIDTH,
212 &pd->qos_save_regs[2][i]);
213 regmap_read(pd->qos_regmap[i],
214 QOS_SATURATION,
215 &pd->qos_save_regs[3][i]);
216 regmap_read(pd->qos_regmap[i],
217 QOS_EXTCONTROL,
218 &pd->qos_save_regs[4][i]);
219 }
220 return 0;
221 }
222
223 static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
224 {
225 int i;
226
227 for (i = 0; i < pd->num_qos; i++) {
228 regmap_write(pd->qos_regmap[i],
229 QOS_PRIORITY,
230 pd->qos_save_regs[0][i]);
231 regmap_write(pd->qos_regmap[i],
232 QOS_MODE,
233 pd->qos_save_regs[1][i]);
234 regmap_write(pd->qos_regmap[i],
235 QOS_BANDWIDTH,
236 pd->qos_save_regs[2][i]);
237 regmap_write(pd->qos_regmap[i],
238 QOS_SATURATION,
239 pd->qos_save_regs[3][i]);
240 regmap_write(pd->qos_regmap[i],
241 QOS_EXTCONTROL,
242 pd->qos_save_regs[4][i]);
243 }
244
245 return 0;
246 }
247
248 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
249 {
250 struct rockchip_pmu *pmu = pd->pmu;
251 unsigned int val;
252
253
254 if (pd->info->status_mask == 0)
255 return !rockchip_pmu_domain_is_idle(pd);
256
257 regmap_read(pmu->regmap, pmu->info->status_offset, &val);
258
259
260 return !(val & pd->info->status_mask);
261 }
262
263 static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
264 bool on)
265 {
266 struct rockchip_pmu *pmu = pd->pmu;
267 struct generic_pm_domain *genpd = &pd->genpd;
268 bool is_on;
269
270 if (pd->info->pwr_mask == 0)
271 return;
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));
276 else
277 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
278 pd->info->pwr_mask, on ? 0 : -1U);
279
280 dsb(sy);
281
282 if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
283 is_on == on, 0, 10000)) {
284 dev_err(pmu->dev,
285 "failed to set domain '%s', val=%d\n",
286 genpd->name, is_on);
287 return;
288 }
289 }
290
291 static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
292 {
293 struct rockchip_pmu *pmu = pd->pmu;
294 int ret;
295
296 mutex_lock(&pmu->mutex);
297
298 if (rockchip_pmu_domain_is_on(pd) != power_on) {
299 ret = clk_bulk_enable(pd->num_clks, pd->clks);
300 if (ret < 0) {
301 dev_err(pmu->dev, "failed to enable clocks\n");
302 mutex_unlock(&pmu->mutex);
303 return ret;
304 }
305
306 if (!power_on) {
307 rockchip_pmu_save_qos(pd);
308
309
310 rockchip_pmu_set_idle_request(pd, true);
311 }
312
313 rockchip_do_pmu_set_power_domain(pd, power_on);
314
315 if (power_on) {
316
317 rockchip_pmu_set_idle_request(pd, false);
318
319 rockchip_pmu_restore_qos(pd);
320 }
321
322 clk_bulk_disable(pd->num_clks, pd->clks);
323 }
324
325 mutex_unlock(&pmu->mutex);
326 return 0;
327 }
328
329 static int rockchip_pd_power_on(struct generic_pm_domain *domain)
330 {
331 struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
332
333 return rockchip_pd_power(pd, true);
334 }
335
336 static int rockchip_pd_power_off(struct generic_pm_domain *domain)
337 {
338 struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
339
340 return rockchip_pd_power(pd, false);
341 }
342
343 static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
344 struct device *dev)
345 {
346 struct clk *clk;
347 int i;
348 int error;
349
350 dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
351
352 error = pm_clk_create(dev);
353 if (error) {
354 dev_err(dev, "pm_clk_create failed %d\n", error);
355 return error;
356 }
357
358 i = 0;
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);
362 if (error) {
363 dev_err(dev, "pm_clk_add_clk failed %d\n", error);
364 clk_put(clk);
365 pm_clk_destroy(dev);
366 return error;
367 }
368 }
369
370 return 0;
371 }
372
373 static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
374 struct device *dev)
375 {
376 dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
377
378 pm_clk_destroy(dev);
379 }
380
381 static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
382 struct device_node *node)
383 {
384 const struct rockchip_domain_info *pd_info;
385 struct rockchip_pm_domain *pd;
386 struct device_node *qos_node;
387 int i, j;
388 u32 id;
389 int error;
390
391 error = of_property_read_u32(node, "reg", &id);
392 if (error) {
393 dev_err(pmu->dev,
394 "%pOFn: failed to retrieve domain id (reg): %d\n",
395 node, error);
396 return -EINVAL;
397 }
398
399 if (id >= pmu->info->num_domains) {
400 dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
401 node, id);
402 return -EINVAL;
403 }
404
405 pd_info = &pmu->info->domain_info[id];
406 if (!pd_info) {
407 dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
408 node, id);
409 return -EINVAL;
410 }
411
412 pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
413 if (!pd)
414 return -ENOMEM;
415
416 pd->info = pd_info;
417 pd->pmu = pmu;
418
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);
423 if (!pd->clks)
424 return -ENOMEM;
425 } else {
426 dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
427 node, pd->num_clks);
428 pd->num_clks = 0;
429 }
430
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);
435 dev_err(pmu->dev,
436 "%pOFn: failed to get clk at index %d: %d\n",
437 node, i, error);
438 return error;
439 }
440 }
441
442 error = clk_bulk_prepare(pd->num_clks, pd->clks);
443 if (error)
444 goto err_put_clocks;
445
446 pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
447 NULL);
448
449 if (pd->num_qos > 0) {
450 pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
451 sizeof(*pd->qos_regmap),
452 GFP_KERNEL);
453 if (!pd->qos_regmap) {
454 error = -ENOMEM;
455 goto err_unprepare_clocks;
456 }
457
458 for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
459 pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
460 pd->num_qos,
461 sizeof(u32),
462 GFP_KERNEL);
463 if (!pd->qos_save_regs[j]) {
464 error = -ENOMEM;
465 goto err_unprepare_clocks;
466 }
467 }
468
469 for (j = 0; j < pd->num_qos; j++) {
470 qos_node = of_parse_phandle(node, "pm_qos", j);
471 if (!qos_node) {
472 error = -ENODEV;
473 goto err_unprepare_clocks;
474 }
475 pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
476 if (IS_ERR(pd->qos_regmap[j])) {
477 error = -ENODEV;
478 of_node_put(qos_node);
479 goto err_unprepare_clocks;
480 }
481 of_node_put(qos_node);
482 }
483 }
484
485 error = rockchip_pd_power(pd, true);
486 if (error) {
487 dev_err(pmu->dev,
488 "failed to power on domain '%pOFn': %d\n",
489 node, error);
490 goto err_unprepare_clocks;
491 }
492
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);
502
503 pmu->genpd_data.domains[id] = &pd->genpd;
504 return 0;
505
506 err_unprepare_clocks:
507 clk_bulk_unprepare(pd->num_clks, pd->clks);
508 err_put_clocks:
509 clk_bulk_put(pd->num_clks, pd->clks);
510 return error;
511 }
512
513 static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
514 {
515 int ret;
516
517
518
519
520
521 ret = pm_genpd_remove(&pd->genpd);
522 if (ret < 0)
523 dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
524 pd->genpd.name, ret);
525
526 clk_bulk_unprepare(pd->num_clks, pd->clks);
527 clk_bulk_put(pd->num_clks, pd->clks);
528
529
530 mutex_lock(&pd->pmu->mutex);
531 pd->num_clks = 0;
532 mutex_unlock(&pd->pmu->mutex);
533
534
535 }
536
537 static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
538 {
539 struct generic_pm_domain *genpd;
540 struct rockchip_pm_domain *pd;
541 int i;
542
543 for (i = 0; i < pmu->genpd_data.num_domains; i++) {
544 genpd = pmu->genpd_data.domains[i];
545 if (genpd) {
546 pd = to_rockchip_pd(genpd);
547 rockchip_pm_remove_one_domain(pd);
548 }
549 }
550
551
552 }
553
554 static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
555 u32 domain_reg_offset,
556 unsigned int count)
557 {
558
559 regmap_write(pmu->regmap, domain_reg_offset, count);
560
561 regmap_write(pmu->regmap, domain_reg_offset + 4, count);
562 }
563
564 static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
565 struct device_node *parent)
566 {
567 struct device_node *np;
568 struct generic_pm_domain *child_domain, *parent_domain;
569 int error;
570
571 for_each_child_of_node(parent, np) {
572 u32 idx;
573
574 error = of_property_read_u32(parent, "reg", &idx);
575 if (error) {
576 dev_err(pmu->dev,
577 "%pOFn: failed to retrieve domain id (reg): %d\n",
578 parent, error);
579 goto err_out;
580 }
581 parent_domain = pmu->genpd_data.domains[idx];
582
583 error = rockchip_pm_add_one_domain(pmu, np);
584 if (error) {
585 dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
586 np, error);
587 goto err_out;
588 }
589
590 error = of_property_read_u32(np, "reg", &idx);
591 if (error) {
592 dev_err(pmu->dev,
593 "%pOFn: failed to retrieve domain id (reg): %d\n",
594 np, error);
595 goto err_out;
596 }
597 child_domain = pmu->genpd_data.domains[idx];
598
599 error = pm_genpd_add_subdomain(parent_domain, child_domain);
600 if (error) {
601 dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
602 parent_domain->name, child_domain->name, error);
603 goto err_out;
604 } else {
605 dev_dbg(pmu->dev, "%s add subdomain: %s\n",
606 parent_domain->name, child_domain->name);
607 }
608
609 rockchip_pm_add_subdomain(pmu, np);
610 }
611
612 return 0;
613
614 err_out:
615 of_node_put(np);
616 return error;
617 }
618
619 static int rockchip_pm_domain_probe(struct platform_device *pdev)
620 {
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;
628 int error;
629
630 if (!np) {
631 dev_err(dev, "device tree node not found\n");
632 return -ENODEV;
633 }
634
635 match = of_match_device(dev->driver->of_match_table, dev);
636 if (!match || !match->data) {
637 dev_err(dev, "missing pmu data\n");
638 return -EINVAL;
639 }
640
641 pmu_info = match->data;
642
643 pmu = devm_kzalloc(dev,
644 struct_size(pmu, domains, pmu_info->num_domains),
645 GFP_KERNEL);
646 if (!pmu)
647 return -ENOMEM;
648
649 pmu->dev = &pdev->dev;
650 mutex_init(&pmu->mutex);
651
652 pmu->info = pmu_info;
653
654 pmu->genpd_data.domains = pmu->domains;
655 pmu->genpd_data.num_domains = pmu_info->num_domains;
656
657 parent = dev->parent;
658 if (!parent) {
659 dev_err(dev, "no parent for syscon devices\n");
660 return -ENODEV;
661 }
662
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);
667 }
668
669
670
671
672
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);
679
680 error = -ENODEV;
681
682 for_each_available_child_of_node(np, node) {
683 error = rockchip_pm_add_one_domain(pmu, node);
684 if (error) {
685 dev_err(dev, "failed to handle node %pOFn: %d\n",
686 node, error);
687 of_node_put(node);
688 goto err_out;
689 }
690
691 error = rockchip_pm_add_subdomain(pmu, node);
692 if (error < 0) {
693 dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
694 node, error);
695 of_node_put(node);
696 goto err_out;
697 }
698 }
699
700 if (error) {
701 dev_dbg(dev, "no power domains defined\n");
702 goto err_out;
703 }
704
705 error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
706 if (error) {
707 dev_err(dev, "failed to add provider: %d\n", error);
708 goto err_out;
709 }
710
711 return 0;
712
713 err_out:
714 rockchip_pm_domain_cleanup(pmu);
715 return error;
716 }
717
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),
727 };
728
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),
737 };
738
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),
745 };
746
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),
753 };
754
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),
761 };
762
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),
775 };
776
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),
782 };
783
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),
794 };
795
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),
804 };
805
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),
812 };
813
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),
842 };
843
844 static const struct rockchip_pmu_info px30_pmu = {
845 .pwr_offset = 0x18,
846 .status_offset = 0x20,
847 .req_offset = 0x64,
848 .idle_offset = 0x6c,
849 .ack_offset = 0x6c,
850
851 .num_domains = ARRAY_SIZE(px30_pm_domains),
852 .domain_info = px30_pm_domains,
853 };
854
855 static const struct rockchip_pmu_info rk3036_pmu = {
856 .req_offset = 0x148,
857 .idle_offset = 0x14c,
858 .ack_offset = 0x14c,
859
860 .num_domains = ARRAY_SIZE(rk3036_pm_domains),
861 .domain_info = rk3036_pm_domains,
862 };
863
864 static const struct rockchip_pmu_info rk3066_pmu = {
865 .pwr_offset = 0x08,
866 .status_offset = 0x0c,
867 .req_offset = 0x38,
868 .idle_offset = 0x0c,
869 .ack_offset = 0x0c,
870
871 .num_domains = ARRAY_SIZE(rk3066_pm_domains),
872 .domain_info = rk3066_pm_domains,
873 };
874
875 static const struct rockchip_pmu_info rk3128_pmu = {
876 .pwr_offset = 0x04,
877 .status_offset = 0x08,
878 .req_offset = 0x0c,
879 .idle_offset = 0x10,
880 .ack_offset = 0x10,
881
882 .num_domains = ARRAY_SIZE(rk3128_pm_domains),
883 .domain_info = rk3128_pm_domains,
884 };
885
886 static const struct rockchip_pmu_info rk3188_pmu = {
887 .pwr_offset = 0x08,
888 .status_offset = 0x0c,
889 .req_offset = 0x38,
890 .idle_offset = 0x0c,
891 .ack_offset = 0x0c,
892
893 .num_domains = ARRAY_SIZE(rk3188_pm_domains),
894 .domain_info = rk3188_pm_domains,
895 };
896
897 static const struct rockchip_pmu_info rk3228_pmu = {
898 .req_offset = 0x40c,
899 .idle_offset = 0x488,
900 .ack_offset = 0x488,
901
902 .num_domains = ARRAY_SIZE(rk3228_pm_domains),
903 .domain_info = rk3228_pm_domains,
904 };
905
906 static const struct rockchip_pmu_info rk3288_pmu = {
907 .pwr_offset = 0x08,
908 .status_offset = 0x0c,
909 .req_offset = 0x10,
910 .idle_offset = 0x14,
911 .ack_offset = 0x14,
912
913 .core_pwrcnt_offset = 0x34,
914 .gpu_pwrcnt_offset = 0x3c,
915
916 .core_power_transition_time = 24,
917 .gpu_power_transition_time = 24,
918
919 .num_domains = ARRAY_SIZE(rk3288_pm_domains),
920 .domain_info = rk3288_pm_domains,
921 };
922
923 static const struct rockchip_pmu_info rk3328_pmu = {
924 .req_offset = 0x414,
925 .idle_offset = 0x484,
926 .ack_offset = 0x484,
927
928 .num_domains = ARRAY_SIZE(rk3328_pm_domains),
929 .domain_info = rk3328_pm_domains,
930 };
931
932 static const struct rockchip_pmu_info rk3366_pmu = {
933 .pwr_offset = 0x0c,
934 .status_offset = 0x10,
935 .req_offset = 0x3c,
936 .idle_offset = 0x40,
937 .ack_offset = 0x40,
938
939 .core_pwrcnt_offset = 0x48,
940 .gpu_pwrcnt_offset = 0x50,
941
942 .core_power_transition_time = 24,
943 .gpu_power_transition_time = 24,
944
945 .num_domains = ARRAY_SIZE(rk3366_pm_domains),
946 .domain_info = rk3366_pm_domains,
947 };
948
949 static const struct rockchip_pmu_info rk3368_pmu = {
950 .pwr_offset = 0x0c,
951 .status_offset = 0x10,
952 .req_offset = 0x3c,
953 .idle_offset = 0x40,
954 .ack_offset = 0x40,
955
956 .core_pwrcnt_offset = 0x48,
957 .gpu_pwrcnt_offset = 0x50,
958
959 .core_power_transition_time = 24,
960 .gpu_power_transition_time = 24,
961
962 .num_domains = ARRAY_SIZE(rk3368_pm_domains),
963 .domain_info = rk3368_pm_domains,
964 };
965
966 static const struct rockchip_pmu_info rk3399_pmu = {
967 .pwr_offset = 0x14,
968 .status_offset = 0x18,
969 .req_offset = 0x60,
970 .idle_offset = 0x64,
971 .ack_offset = 0x68,
972
973
974
975 .num_domains = ARRAY_SIZE(rk3399_pm_domains),
976 .domain_info = rk3399_pm_domains,
977 };
978
979 static const struct of_device_id rockchip_pm_domain_dt_match[] = {
980 {
981 .compatible = "rockchip,px30-power-controller",
982 .data = (void *)&px30_pmu,
983 },
984 {
985 .compatible = "rockchip,rk3036-power-controller",
986 .data = (void *)&rk3036_pmu,
987 },
988 {
989 .compatible = "rockchip,rk3066-power-controller",
990 .data = (void *)&rk3066_pmu,
991 },
992 {
993 .compatible = "rockchip,rk3128-power-controller",
994 .data = (void *)&rk3128_pmu,
995 },
996 {
997 .compatible = "rockchip,rk3188-power-controller",
998 .data = (void *)&rk3188_pmu,
999 },
1000 {
1001 .compatible = "rockchip,rk3228-power-controller",
1002 .data = (void *)&rk3228_pmu,
1003 },
1004 {
1005 .compatible = "rockchip,rk3288-power-controller",
1006 .data = (void *)&rk3288_pmu,
1007 },
1008 {
1009 .compatible = "rockchip,rk3328-power-controller",
1010 .data = (void *)&rk3328_pmu,
1011 },
1012 {
1013 .compatible = "rockchip,rk3366-power-controller",
1014 .data = (void *)&rk3366_pmu,
1015 },
1016 {
1017 .compatible = "rockchip,rk3368-power-controller",
1018 .data = (void *)&rk3368_pmu,
1019 },
1020 {
1021 .compatible = "rockchip,rk3399-power-controller",
1022 .data = (void *)&rk3399_pmu,
1023 },
1024 { },
1025 };
1026
1027 static struct platform_driver rockchip_pm_domain_driver = {
1028 .probe = rockchip_pm_domain_probe,
1029 .driver = {
1030 .name = "rockchip-pm-domain",
1031 .of_match_table = rockchip_pm_domain_dt_match,
1032
1033
1034
1035
1036
1037 .suppress_bind_attrs = true,
1038 },
1039 };
1040
1041 static int __init rockchip_pm_domain_drv_register(void)
1042 {
1043 return platform_driver_register(&rockchip_pm_domain_driver);
1044 }
1045 postcore_initcall(rockchip_pm_domain_drv_register);