Merge tag 'riscv-for-linus-5.15-mw0' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / soc / rockchip / pm_domains.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip Generic power domain support.
4  *
5  * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
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 #include <dt-bindings/power/rk3568-power.h>
31
32 struct rockchip_domain_info {
33         const char *name;
34         int pwr_mask;
35         int status_mask;
36         int req_mask;
37         int idle_mask;
38         int ack_mask;
39         bool active_wakeup;
40         int pwr_w_mask;
41         int req_w_mask;
42 };
43
44 struct rockchip_pmu_info {
45         u32 pwr_offset;
46         u32 status_offset;
47         u32 req_offset;
48         u32 idle_offset;
49         u32 ack_offset;
50
51         u32 core_pwrcnt_offset;
52         u32 gpu_pwrcnt_offset;
53
54         unsigned int core_power_transition_time;
55         unsigned int gpu_power_transition_time;
56
57         int num_domains;
58         const struct rockchip_domain_info *domain_info;
59 };
60
61 #define MAX_QOS_REGS_NUM        5
62 #define QOS_PRIORITY            0x08
63 #define QOS_MODE                0x0c
64 #define QOS_BANDWIDTH           0x10
65 #define QOS_SATURATION          0x14
66 #define QOS_EXTCONTROL          0x18
67
68 struct rockchip_pm_domain {
69         struct generic_pm_domain genpd;
70         const struct rockchip_domain_info *info;
71         struct rockchip_pmu *pmu;
72         int num_qos;
73         struct regmap **qos_regmap;
74         u32 *qos_save_regs[MAX_QOS_REGS_NUM];
75         int num_clks;
76         struct clk_bulk_data *clks;
77 };
78
79 struct rockchip_pmu {
80         struct device *dev;
81         struct regmap *regmap;
82         const struct rockchip_pmu_info *info;
83         struct mutex mutex; /* mutex lock for pmu */
84         struct genpd_onecell_data genpd_data;
85         struct generic_pm_domain *domains[];
86 };
87
88 #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
89
90 #define DOMAIN(_name, pwr, status, req, idle, ack, wakeup)      \
91 {                                                       \
92         .name = _name,                          \
93         .pwr_mask = (pwr),                              \
94         .status_mask = (status),                        \
95         .req_mask = (req),                              \
96         .idle_mask = (idle),                            \
97         .ack_mask = (ack),                              \
98         .active_wakeup = (wakeup),                      \
99 }
100
101 #define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup)    \
102 {                                                       \
103         .name = _name,                          \
104         .pwr_w_mask = (pwr) << 16,                      \
105         .pwr_mask = (pwr),                              \
106         .status_mask = (status),                        \
107         .req_w_mask = (req) << 16,                      \
108         .req_mask = (req),                              \
109         .idle_mask = (idle),                            \
110         .ack_mask = (ack),                              \
111         .active_wakeup = wakeup,                        \
112 }
113
114 #define DOMAIN_RK3036(_name, req, ack, idle, wakeup)            \
115 {                                                       \
116         .name = _name,                          \
117         .req_mask = (req),                              \
118         .req_w_mask = (req) << 16,                      \
119         .ack_mask = (ack),                              \
120         .idle_mask = (idle),                            \
121         .active_wakeup = wakeup,                        \
122 }
123
124 #define DOMAIN_PX30(name, pwr, status, req, wakeup)             \
125         DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
126
127 #define DOMAIN_RK3288(name, pwr, status, req, wakeup)           \
128         DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
129
130 #define DOMAIN_RK3328(name, pwr, status, req, wakeup)           \
131         DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup)
132
133 #define DOMAIN_RK3368(name, pwr, status, req, wakeup)           \
134         DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup)
135
136 #define DOMAIN_RK3399(name, pwr, status, req, wakeup)           \
137         DOMAIN(name, pwr, status, req, req, req, wakeup)
138
139 #define DOMAIN_RK3568(name, pwr, req, wakeup)           \
140         DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
141
142 static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
143 {
144         struct rockchip_pmu *pmu = pd->pmu;
145         const struct rockchip_domain_info *pd_info = pd->info;
146         unsigned int val;
147
148         regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
149         return (val & pd_info->idle_mask) == pd_info->idle_mask;
150 }
151
152 static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
153 {
154         unsigned int val;
155
156         regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
157         return val;
158 }
159
160 static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
161                                          bool idle)
162 {
163         const struct rockchip_domain_info *pd_info = pd->info;
164         struct generic_pm_domain *genpd = &pd->genpd;
165         struct rockchip_pmu *pmu = pd->pmu;
166         unsigned int target_ack;
167         unsigned int val;
168         bool is_idle;
169         int ret;
170
171         if (pd_info->req_mask == 0)
172                 return 0;
173         else if (pd_info->req_w_mask)
174                 regmap_write(pmu->regmap, pmu->info->req_offset,
175                              idle ? (pd_info->req_mask | pd_info->req_w_mask) :
176                              pd_info->req_w_mask);
177         else
178                 regmap_update_bits(pmu->regmap, pmu->info->req_offset,
179                                    pd_info->req_mask, idle ? -1U : 0);
180
181         dsb(sy);
182
183         /* Wait util idle_ack = 1 */
184         target_ack = idle ? pd_info->ack_mask : 0;
185         ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
186                                         (val & pd_info->ack_mask) == target_ack,
187                                         0, 10000);
188         if (ret) {
189                 dev_err(pmu->dev,
190                         "failed to get ack on domain '%s', val=0x%x\n",
191                         genpd->name, val);
192                 return ret;
193         }
194
195         ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
196                                         is_idle, is_idle == idle, 0, 10000);
197         if (ret) {
198                 dev_err(pmu->dev,
199                         "failed to set idle on domain '%s', val=%d\n",
200                         genpd->name, is_idle);
201                 return ret;
202         }
203
204         return 0;
205 }
206
207 static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
208 {
209         int i;
210
211         for (i = 0; i < pd->num_qos; i++) {
212                 regmap_read(pd->qos_regmap[i],
213                             QOS_PRIORITY,
214                             &pd->qos_save_regs[0][i]);
215                 regmap_read(pd->qos_regmap[i],
216                             QOS_MODE,
217                             &pd->qos_save_regs[1][i]);
218                 regmap_read(pd->qos_regmap[i],
219                             QOS_BANDWIDTH,
220                             &pd->qos_save_regs[2][i]);
221                 regmap_read(pd->qos_regmap[i],
222                             QOS_SATURATION,
223                             &pd->qos_save_regs[3][i]);
224                 regmap_read(pd->qos_regmap[i],
225                             QOS_EXTCONTROL,
226                             &pd->qos_save_regs[4][i]);
227         }
228         return 0;
229 }
230
231 static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
232 {
233         int i;
234
235         for (i = 0; i < pd->num_qos; i++) {
236                 regmap_write(pd->qos_regmap[i],
237                              QOS_PRIORITY,
238                              pd->qos_save_regs[0][i]);
239                 regmap_write(pd->qos_regmap[i],
240                              QOS_MODE,
241                              pd->qos_save_regs[1][i]);
242                 regmap_write(pd->qos_regmap[i],
243                              QOS_BANDWIDTH,
244                              pd->qos_save_regs[2][i]);
245                 regmap_write(pd->qos_regmap[i],
246                              QOS_SATURATION,
247                              pd->qos_save_regs[3][i]);
248                 regmap_write(pd->qos_regmap[i],
249                              QOS_EXTCONTROL,
250                              pd->qos_save_regs[4][i]);
251         }
252
253         return 0;
254 }
255
256 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
257 {
258         struct rockchip_pmu *pmu = pd->pmu;
259         unsigned int val;
260
261         /* check idle status for idle-only domains */
262         if (pd->info->status_mask == 0)
263                 return !rockchip_pmu_domain_is_idle(pd);
264
265         regmap_read(pmu->regmap, pmu->info->status_offset, &val);
266
267         /* 1'b0: power on, 1'b1: power off */
268         return !(val & pd->info->status_mask);
269 }
270
271 static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
272                                              bool on)
273 {
274         struct rockchip_pmu *pmu = pd->pmu;
275         struct generic_pm_domain *genpd = &pd->genpd;
276         bool is_on;
277
278         if (pd->info->pwr_mask == 0)
279                 return;
280         else if (pd->info->pwr_w_mask)
281                 regmap_write(pmu->regmap, pmu->info->pwr_offset,
282                              on ? pd->info->pwr_w_mask :
283                              (pd->info->pwr_mask | pd->info->pwr_w_mask));
284         else
285                 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
286                                    pd->info->pwr_mask, on ? 0 : -1U);
287
288         dsb(sy);
289
290         if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
291                                       is_on == on, 0, 10000)) {
292                 dev_err(pmu->dev,
293                         "failed to set domain '%s', val=%d\n",
294                         genpd->name, is_on);
295                 return;
296         }
297 }
298
299 static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
300 {
301         struct rockchip_pmu *pmu = pd->pmu;
302         int ret;
303
304         mutex_lock(&pmu->mutex);
305
306         if (rockchip_pmu_domain_is_on(pd) != power_on) {
307                 ret = clk_bulk_enable(pd->num_clks, pd->clks);
308                 if (ret < 0) {
309                         dev_err(pmu->dev, "failed to enable clocks\n");
310                         mutex_unlock(&pmu->mutex);
311                         return ret;
312                 }
313
314                 if (!power_on) {
315                         rockchip_pmu_save_qos(pd);
316
317                         /* if powering down, idle request to NIU first */
318                         rockchip_pmu_set_idle_request(pd, true);
319                 }
320
321                 rockchip_do_pmu_set_power_domain(pd, power_on);
322
323                 if (power_on) {
324                         /* if powering up, leave idle mode */
325                         rockchip_pmu_set_idle_request(pd, false);
326
327                         rockchip_pmu_restore_qos(pd);
328                 }
329
330                 clk_bulk_disable(pd->num_clks, pd->clks);
331         }
332
333         mutex_unlock(&pmu->mutex);
334         return 0;
335 }
336
337 static int rockchip_pd_power_on(struct generic_pm_domain *domain)
338 {
339         struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
340
341         return rockchip_pd_power(pd, true);
342 }
343
344 static int rockchip_pd_power_off(struct generic_pm_domain *domain)
345 {
346         struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
347
348         return rockchip_pd_power(pd, false);
349 }
350
351 static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
352                                   struct device *dev)
353 {
354         struct clk *clk;
355         int i;
356         int error;
357
358         dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
359
360         error = pm_clk_create(dev);
361         if (error) {
362                 dev_err(dev, "pm_clk_create failed %d\n", error);
363                 return error;
364         }
365
366         i = 0;
367         while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
368                 dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
369                 error = pm_clk_add_clk(dev, clk);
370                 if (error) {
371                         dev_err(dev, "pm_clk_add_clk failed %d\n", error);
372                         clk_put(clk);
373                         pm_clk_destroy(dev);
374                         return error;
375                 }
376         }
377
378         return 0;
379 }
380
381 static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
382                                    struct device *dev)
383 {
384         dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
385
386         pm_clk_destroy(dev);
387 }
388
389 static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
390                                       struct device_node *node)
391 {
392         const struct rockchip_domain_info *pd_info;
393         struct rockchip_pm_domain *pd;
394         struct device_node *qos_node;
395         int i, j;
396         u32 id;
397         int error;
398
399         error = of_property_read_u32(node, "reg", &id);
400         if (error) {
401                 dev_err(pmu->dev,
402                         "%pOFn: failed to retrieve domain id (reg): %d\n",
403                         node, error);
404                 return -EINVAL;
405         }
406
407         if (id >= pmu->info->num_domains) {
408                 dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
409                         node, id);
410                 return -EINVAL;
411         }
412
413         pd_info = &pmu->info->domain_info[id];
414         if (!pd_info) {
415                 dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
416                         node, id);
417                 return -EINVAL;
418         }
419
420         pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
421         if (!pd)
422                 return -ENOMEM;
423
424         pd->info = pd_info;
425         pd->pmu = pmu;
426
427         pd->num_clks = of_clk_get_parent_count(node);
428         if (pd->num_clks > 0) {
429                 pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
430                                         sizeof(*pd->clks), GFP_KERNEL);
431                 if (!pd->clks)
432                         return -ENOMEM;
433         } else {
434                 dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
435                         node, pd->num_clks);
436                 pd->num_clks = 0;
437         }
438
439         for (i = 0; i < pd->num_clks; i++) {
440                 pd->clks[i].clk = of_clk_get(node, i);
441                 if (IS_ERR(pd->clks[i].clk)) {
442                         error = PTR_ERR(pd->clks[i].clk);
443                         dev_err(pmu->dev,
444                                 "%pOFn: failed to get clk at index %d: %d\n",
445                                 node, i, error);
446                         return error;
447                 }
448         }
449
450         error = clk_bulk_prepare(pd->num_clks, pd->clks);
451         if (error)
452                 goto err_put_clocks;
453
454         pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
455                                                  NULL);
456
457         if (pd->num_qos > 0) {
458                 pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
459                                               sizeof(*pd->qos_regmap),
460                                               GFP_KERNEL);
461                 if (!pd->qos_regmap) {
462                         error = -ENOMEM;
463                         goto err_unprepare_clocks;
464                 }
465
466                 for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
467                         pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
468                                                             pd->num_qos,
469                                                             sizeof(u32),
470                                                             GFP_KERNEL);
471                         if (!pd->qos_save_regs[j]) {
472                                 error = -ENOMEM;
473                                 goto err_unprepare_clocks;
474                         }
475                 }
476
477                 for (j = 0; j < pd->num_qos; j++) {
478                         qos_node = of_parse_phandle(node, "pm_qos", j);
479                         if (!qos_node) {
480                                 error = -ENODEV;
481                                 goto err_unprepare_clocks;
482                         }
483                         pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
484                         if (IS_ERR(pd->qos_regmap[j])) {
485                                 error = -ENODEV;
486                                 of_node_put(qos_node);
487                                 goto err_unprepare_clocks;
488                         }
489                         of_node_put(qos_node);
490                 }
491         }
492
493         error = rockchip_pd_power(pd, true);
494         if (error) {
495                 dev_err(pmu->dev,
496                         "failed to power on domain '%pOFn': %d\n",
497                         node, error);
498                 goto err_unprepare_clocks;
499         }
500
501         if (pd->info->name)
502                 pd->genpd.name = pd->info->name;
503         else
504                 pd->genpd.name = kbasename(node->full_name);
505         pd->genpd.power_off = rockchip_pd_power_off;
506         pd->genpd.power_on = rockchip_pd_power_on;
507         pd->genpd.attach_dev = rockchip_pd_attach_dev;
508         pd->genpd.detach_dev = rockchip_pd_detach_dev;
509         pd->genpd.flags = GENPD_FLAG_PM_CLK;
510         if (pd_info->active_wakeup)
511                 pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
512         pm_genpd_init(&pd->genpd, NULL, false);
513
514         pmu->genpd_data.domains[id] = &pd->genpd;
515         return 0;
516
517 err_unprepare_clocks:
518         clk_bulk_unprepare(pd->num_clks, pd->clks);
519 err_put_clocks:
520         clk_bulk_put(pd->num_clks, pd->clks);
521         return error;
522 }
523
524 static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
525 {
526         int ret;
527
528         /*
529          * We're in the error cleanup already, so we only complain,
530          * but won't emit another error on top of the original one.
531          */
532         ret = pm_genpd_remove(&pd->genpd);
533         if (ret < 0)
534                 dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
535                         pd->genpd.name, ret);
536
537         clk_bulk_unprepare(pd->num_clks, pd->clks);
538         clk_bulk_put(pd->num_clks, pd->clks);
539
540         /* protect the zeroing of pm->num_clks */
541         mutex_lock(&pd->pmu->mutex);
542         pd->num_clks = 0;
543         mutex_unlock(&pd->pmu->mutex);
544
545         /* devm will free our memory */
546 }
547
548 static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
549 {
550         struct generic_pm_domain *genpd;
551         struct rockchip_pm_domain *pd;
552         int i;
553
554         for (i = 0; i < pmu->genpd_data.num_domains; i++) {
555                 genpd = pmu->genpd_data.domains[i];
556                 if (genpd) {
557                         pd = to_rockchip_pd(genpd);
558                         rockchip_pm_remove_one_domain(pd);
559                 }
560         }
561
562         /* devm will free our memory */
563 }
564
565 static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
566                                       u32 domain_reg_offset,
567                                       unsigned int count)
568 {
569         /* First configure domain power down transition count ... */
570         regmap_write(pmu->regmap, domain_reg_offset, count);
571         /* ... and then power up count. */
572         regmap_write(pmu->regmap, domain_reg_offset + 4, count);
573 }
574
575 static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
576                                      struct device_node *parent)
577 {
578         struct device_node *np;
579         struct generic_pm_domain *child_domain, *parent_domain;
580         int error;
581
582         for_each_child_of_node(parent, np) {
583                 u32 idx;
584
585                 error = of_property_read_u32(parent, "reg", &idx);
586                 if (error) {
587                         dev_err(pmu->dev,
588                                 "%pOFn: failed to retrieve domain id (reg): %d\n",
589                                 parent, error);
590                         goto err_out;
591                 }
592                 parent_domain = pmu->genpd_data.domains[idx];
593
594                 error = rockchip_pm_add_one_domain(pmu, np);
595                 if (error) {
596                         dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
597                                 np, error);
598                         goto err_out;
599                 }
600
601                 error = of_property_read_u32(np, "reg", &idx);
602                 if (error) {
603                         dev_err(pmu->dev,
604                                 "%pOFn: failed to retrieve domain id (reg): %d\n",
605                                 np, error);
606                         goto err_out;
607                 }
608                 child_domain = pmu->genpd_data.domains[idx];
609
610                 error = pm_genpd_add_subdomain(parent_domain, child_domain);
611                 if (error) {
612                         dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
613                                 parent_domain->name, child_domain->name, error);
614                         goto err_out;
615                 } else {
616                         dev_dbg(pmu->dev, "%s add subdomain: %s\n",
617                                 parent_domain->name, child_domain->name);
618                 }
619
620                 rockchip_pm_add_subdomain(pmu, np);
621         }
622
623         return 0;
624
625 err_out:
626         of_node_put(np);
627         return error;
628 }
629
630 static int rockchip_pm_domain_probe(struct platform_device *pdev)
631 {
632         struct device *dev = &pdev->dev;
633         struct device_node *np = dev->of_node;
634         struct device_node *node;
635         struct device *parent;
636         struct rockchip_pmu *pmu;
637         const struct of_device_id *match;
638         const struct rockchip_pmu_info *pmu_info;
639         int error;
640
641         if (!np) {
642                 dev_err(dev, "device tree node not found\n");
643                 return -ENODEV;
644         }
645
646         match = of_match_device(dev->driver->of_match_table, dev);
647         if (!match || !match->data) {
648                 dev_err(dev, "missing pmu data\n");
649                 return -EINVAL;
650         }
651
652         pmu_info = match->data;
653
654         pmu = devm_kzalloc(dev,
655                            struct_size(pmu, domains, pmu_info->num_domains),
656                            GFP_KERNEL);
657         if (!pmu)
658                 return -ENOMEM;
659
660         pmu->dev = &pdev->dev;
661         mutex_init(&pmu->mutex);
662
663         pmu->info = pmu_info;
664
665         pmu->genpd_data.domains = pmu->domains;
666         pmu->genpd_data.num_domains = pmu_info->num_domains;
667
668         parent = dev->parent;
669         if (!parent) {
670                 dev_err(dev, "no parent for syscon devices\n");
671                 return -ENODEV;
672         }
673
674         pmu->regmap = syscon_node_to_regmap(parent->of_node);
675         if (IS_ERR(pmu->regmap)) {
676                 dev_err(dev, "no regmap available\n");
677                 return PTR_ERR(pmu->regmap);
678         }
679
680         /*
681          * Configure power up and down transition delays for CORE
682          * and GPU domains.
683          */
684         if (pmu_info->core_power_transition_time)
685                 rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
686                                         pmu_info->core_power_transition_time);
687         if (pmu_info->gpu_pwrcnt_offset)
688                 rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
689                                         pmu_info->gpu_power_transition_time);
690
691         error = -ENODEV;
692
693         for_each_available_child_of_node(np, node) {
694                 error = rockchip_pm_add_one_domain(pmu, node);
695                 if (error) {
696                         dev_err(dev, "failed to handle node %pOFn: %d\n",
697                                 node, error);
698                         of_node_put(node);
699                         goto err_out;
700                 }
701
702                 error = rockchip_pm_add_subdomain(pmu, node);
703                 if (error < 0) {
704                         dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
705                                 node, error);
706                         of_node_put(node);
707                         goto err_out;
708                 }
709         }
710
711         if (error) {
712                 dev_dbg(dev, "no power domains defined\n");
713                 goto err_out;
714         }
715
716         error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
717         if (error) {
718                 dev_err(dev, "failed to add provider: %d\n", error);
719                 goto err_out;
720         }
721
722         return 0;
723
724 err_out:
725         rockchip_pm_domain_cleanup(pmu);
726         return error;
727 }
728
729 static const struct rockchip_domain_info px30_pm_domains[] = {
730         [PX30_PD_USB]           = DOMAIN_PX30("usb",      BIT(5),  BIT(5),  BIT(10), false),
731         [PX30_PD_SDCARD]        = DOMAIN_PX30("sdcard",   BIT(8),  BIT(8),  BIT(9),  false),
732         [PX30_PD_GMAC]          = DOMAIN_PX30("gmac",     BIT(10), BIT(10), BIT(6),  false),
733         [PX30_PD_MMC_NAND]      = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5),  false),
734         [PX30_PD_VPU]           = DOMAIN_PX30("vpu",      BIT(12), BIT(12), BIT(14), false),
735         [PX30_PD_VO]            = DOMAIN_PX30("vo",       BIT(13), BIT(13), BIT(7),  false),
736         [PX30_PD_VI]            = DOMAIN_PX30("vi",       BIT(14), BIT(14), BIT(8),  false),
737         [PX30_PD_GPU]           = DOMAIN_PX30("gpu",      BIT(15), BIT(15), BIT(2),  false),
738 };
739
740 static const struct rockchip_domain_info rk3036_pm_domains[] = {
741         [RK3036_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
742         [RK3036_PD_CORE]        = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
743         [RK3036_PD_PERI]        = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false),
744         [RK3036_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(11), BIT(19), BIT(26), false),
745         [RK3036_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(10), BIT(20), BIT(27), false),
746         [RK3036_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(9),  BIT(21), BIT(28), false),
747         [RK3036_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(8),  BIT(22), BIT(29), false),
748 };
749
750 static const struct rockchip_domain_info rk3066_pm_domains[] = {
751         [RK3066_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
752         [RK3066_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
753         [RK3066_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
754         [RK3066_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
755         [RK3066_PD_CPU]         = DOMAIN("cpu",   0,      BIT(5), BIT(1), BIT(26), BIT(31), false),
756 };
757
758 static const struct rockchip_domain_info rk3128_pm_domains[] = {
759         [RK3128_PD_CORE]        = DOMAIN_RK3288("core",  BIT(0), BIT(0), BIT(4), false),
760         [RK3128_PD_MSCH]        = DOMAIN_RK3288("msch",  0,      0,      BIT(6), true),
761         [RK3128_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(3), BIT(3), BIT(2), false),
762         [RK3128_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false),
763         [RK3128_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(1), BIT(1), BIT(3), false),
764 };
765
766 static const struct rockchip_domain_info rk3188_pm_domains[] = {
767         [RK3188_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
768         [RK3188_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
769         [RK3188_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
770         [RK3188_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
771         [RK3188_PD_CPU]         = DOMAIN("cpu",   BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
772 };
773
774 static const struct rockchip_domain_info rk3228_pm_domains[] = {
775         [RK3228_PD_CORE]        = DOMAIN_RK3036("core", BIT(0),  BIT(0),  BIT(16), true),
776         [RK3228_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(1),  BIT(1),  BIT(17), true),
777         [RK3228_PD_BUS]         = DOMAIN_RK3036("bus",  BIT(2),  BIT(2),  BIT(18), true),
778         [RK3228_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(3),  BIT(3),  BIT(19), true),
779         [RK3228_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(4),  BIT(4),  BIT(20), false),
780         [RK3228_PD_VOP]         = DOMAIN_RK3036("vop",  BIT(5),  BIT(5),  BIT(21), false),
781         [RK3228_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(6),  BIT(6),  BIT(22), false),
782         [RK3228_PD_RKVDEC]      = DOMAIN_RK3036("vdec", BIT(7),  BIT(7),  BIT(23), false),
783         [RK3228_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(8),  BIT(8),  BIT(24), false),
784         [RK3228_PD_PERI]        = DOMAIN_RK3036("peri", BIT(9),  BIT(9),  BIT(25), true),
785         [RK3228_PD_GMAC]        = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false),
786 };
787
788 static const struct rockchip_domain_info rk3288_pm_domains[] = {
789         [RK3288_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(7),  BIT(7),  BIT(4), false),
790         [RK3288_PD_HEVC]        = DOMAIN_RK3288("hevc",  BIT(14), BIT(10), BIT(9), false),
791         [RK3288_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(8),  BIT(8),  BIT(3), false),
792         [RK3288_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(9),  BIT(9),  BIT(2), false),
793 };
794
795 static const struct rockchip_domain_info rk3328_pm_domains[] = {
796         [RK3328_PD_CORE]        = DOMAIN_RK3328("core",  0, BIT(0), BIT(0), false),
797         [RK3328_PD_GPU]         = DOMAIN_RK3328("gpu",   0, BIT(1), BIT(1), false),
798         [RK3328_PD_BUS]         = DOMAIN_RK3328("bus",   0, BIT(2), BIT(2), true),
799         [RK3328_PD_MSCH]        = DOMAIN_RK3328("msch",  0, BIT(3), BIT(3), true),
800         [RK3328_PD_PERI]        = DOMAIN_RK3328("peri",  0, BIT(4), BIT(4), true),
801         [RK3328_PD_VIDEO]       = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false),
802         [RK3328_PD_HEVC]        = DOMAIN_RK3328("hevc",  0, BIT(6), BIT(6), false),
803         [RK3328_PD_VIO]         = DOMAIN_RK3328("vio",   0, BIT(8), BIT(8), false),
804         [RK3328_PD_VPU]         = DOMAIN_RK3328("vpu",   0, BIT(9), BIT(9), false),
805 };
806
807 static const struct rockchip_domain_info rk3366_pm_domains[] = {
808         [RK3366_PD_PERI]        = DOMAIN_RK3368("peri",   BIT(10), BIT(10), BIT(6), true),
809         [RK3366_PD_VIO]         = DOMAIN_RK3368("vio",    BIT(14), BIT(14), BIT(8), false),
810         [RK3366_PD_VIDEO]       = DOMAIN_RK3368("video",  BIT(13), BIT(13), BIT(7), false),
811         [RK3366_PD_RKVDEC]      = DOMAIN_RK3368("vdec",   BIT(11), BIT(11), BIT(7), false),
812         [RK3366_PD_WIFIBT]      = DOMAIN_RK3368("wifibt", BIT(8),  BIT(8),  BIT(9), false),
813         [RK3366_PD_VPU]         = DOMAIN_RK3368("vpu",    BIT(12), BIT(12), BIT(7), false),
814         [RK3366_PD_GPU]         = DOMAIN_RK3368("gpu",    BIT(15), BIT(15), BIT(2), false),
815 };
816
817 static const struct rockchip_domain_info rk3368_pm_domains[] = {
818         [RK3368_PD_PERI]        = DOMAIN_RK3368("peri",  BIT(13), BIT(12), BIT(6), true),
819         [RK3368_PD_VIO]         = DOMAIN_RK3368("vio",   BIT(15), BIT(14), BIT(8), false),
820         [RK3368_PD_VIDEO]       = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false),
821         [RK3368_PD_GPU_0]       = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false),
822         [RK3368_PD_GPU_1]       = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false),
823 };
824
825 static const struct rockchip_domain_info rk3399_pm_domains[] = {
826         [RK3399_PD_TCPD0]       = DOMAIN_RK3399("tcpd0",     BIT(8),  BIT(8),  0,       false),
827         [RK3399_PD_TCPD1]       = DOMAIN_RK3399("tcpd1",     BIT(9),  BIT(9),  0,       false),
828         [RK3399_PD_CCI]         = DOMAIN_RK3399("cci",       BIT(10), BIT(10), 0,       true),
829         [RK3399_PD_CCI0]        = DOMAIN_RK3399("cci0",      0,       0,       BIT(15), true),
830         [RK3399_PD_CCI1]        = DOMAIN_RK3399("cci1",      0,       0,       BIT(16), true),
831         [RK3399_PD_PERILP]      = DOMAIN_RK3399("perilp",    BIT(11), BIT(11), BIT(1),  true),
832         [RK3399_PD_PERIHP]      = DOMAIN_RK3399("perihp",    BIT(12), BIT(12), BIT(2),  true),
833         [RK3399_PD_CENTER]      = DOMAIN_RK3399("center",    BIT(13), BIT(13), BIT(14), true),
834         [RK3399_PD_VIO]         = DOMAIN_RK3399("vio",       BIT(14), BIT(14), BIT(17), false),
835         [RK3399_PD_GPU]         = DOMAIN_RK3399("gpu",       BIT(15), BIT(15), BIT(0),  false),
836         [RK3399_PD_VCODEC]      = DOMAIN_RK3399("vcodec",    BIT(16), BIT(16), BIT(3),  false),
837         [RK3399_PD_VDU]         = DOMAIN_RK3399("vdu",       BIT(17), BIT(17), BIT(4),  false),
838         [RK3399_PD_RGA]         = DOMAIN_RK3399("rga",       BIT(18), BIT(18), BIT(5),  false),
839         [RK3399_PD_IEP]         = DOMAIN_RK3399("iep",       BIT(19), BIT(19), BIT(6),  false),
840         [RK3399_PD_VO]          = DOMAIN_RK3399("vo",        BIT(20), BIT(20), 0,       false),
841         [RK3399_PD_VOPB]        = DOMAIN_RK3399("vopb",      0,       0,       BIT(7),  false),
842         [RK3399_PD_VOPL]        = DOMAIN_RK3399("vopl",      0,       0,       BIT(8),  false),
843         [RK3399_PD_ISP0]        = DOMAIN_RK3399("isp0",      BIT(22), BIT(22), BIT(9),  false),
844         [RK3399_PD_ISP1]        = DOMAIN_RK3399("isp1",      BIT(23), BIT(23), BIT(10), false),
845         [RK3399_PD_HDCP]        = DOMAIN_RK3399("hdcp",      BIT(24), BIT(24), BIT(11), false),
846         [RK3399_PD_GMAC]        = DOMAIN_RK3399("gmac",      BIT(25), BIT(25), BIT(23), true),
847         [RK3399_PD_EMMC]        = DOMAIN_RK3399("emmc",      BIT(26), BIT(26), BIT(24), true),
848         [RK3399_PD_USB3]        = DOMAIN_RK3399("usb3",      BIT(27), BIT(27), BIT(12), true),
849         [RK3399_PD_EDP]         = DOMAIN_RK3399("edp",       BIT(28), BIT(28), BIT(22), false),
850         [RK3399_PD_GIC]         = DOMAIN_RK3399("gic",       BIT(29), BIT(29), BIT(27), true),
851         [RK3399_PD_SD]          = DOMAIN_RK3399("sd",        BIT(30), BIT(30), BIT(28), true),
852         [RK3399_PD_SDIOAUDIO]   = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true),
853 };
854
855 static const struct rockchip_domain_info rk3568_pm_domains[] = {
856         [RK3568_PD_NPU]         = DOMAIN_RK3568("npu",  BIT(1), BIT(2),  false),
857         [RK3568_PD_GPU]         = DOMAIN_RK3568("gpu",  BIT(0), BIT(1),  false),
858         [RK3568_PD_VI]          = DOMAIN_RK3568("vi",   BIT(6), BIT(3),  false),
859         [RK3568_PD_VO]          = DOMAIN_RK3568("vo",   BIT(7), BIT(4),  false),
860         [RK3568_PD_RGA]         = DOMAIN_RK3568("rga",  BIT(5), BIT(5),  false),
861         [RK3568_PD_VPU]         = DOMAIN_RK3568("vpu",  BIT(2), BIT(6),  false),
862         [RK3568_PD_RKVDEC]      = DOMAIN_RK3568("vdec", BIT(4), BIT(8),  false),
863         [RK3568_PD_RKVENC]      = DOMAIN_RK3568("venc", BIT(3), BIT(7),  false),
864         [RK3568_PD_PIPE]        = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
865 };
866
867 static const struct rockchip_pmu_info px30_pmu = {
868         .pwr_offset = 0x18,
869         .status_offset = 0x20,
870         .req_offset = 0x64,
871         .idle_offset = 0x6c,
872         .ack_offset = 0x6c,
873
874         .num_domains = ARRAY_SIZE(px30_pm_domains),
875         .domain_info = px30_pm_domains,
876 };
877
878 static const struct rockchip_pmu_info rk3036_pmu = {
879         .req_offset = 0x148,
880         .idle_offset = 0x14c,
881         .ack_offset = 0x14c,
882
883         .num_domains = ARRAY_SIZE(rk3036_pm_domains),
884         .domain_info = rk3036_pm_domains,
885 };
886
887 static const struct rockchip_pmu_info rk3066_pmu = {
888         .pwr_offset = 0x08,
889         .status_offset = 0x0c,
890         .req_offset = 0x38, /* PMU_MISC_CON1 */
891         .idle_offset = 0x0c,
892         .ack_offset = 0x0c,
893
894         .num_domains = ARRAY_SIZE(rk3066_pm_domains),
895         .domain_info = rk3066_pm_domains,
896 };
897
898 static const struct rockchip_pmu_info rk3128_pmu = {
899         .pwr_offset = 0x04,
900         .status_offset = 0x08,
901         .req_offset = 0x0c,
902         .idle_offset = 0x10,
903         .ack_offset = 0x10,
904
905         .num_domains = ARRAY_SIZE(rk3128_pm_domains),
906         .domain_info = rk3128_pm_domains,
907 };
908
909 static const struct rockchip_pmu_info rk3188_pmu = {
910         .pwr_offset = 0x08,
911         .status_offset = 0x0c,
912         .req_offset = 0x38, /* PMU_MISC_CON1 */
913         .idle_offset = 0x0c,
914         .ack_offset = 0x0c,
915
916         .num_domains = ARRAY_SIZE(rk3188_pm_domains),
917         .domain_info = rk3188_pm_domains,
918 };
919
920 static const struct rockchip_pmu_info rk3228_pmu = {
921         .req_offset = 0x40c,
922         .idle_offset = 0x488,
923         .ack_offset = 0x488,
924
925         .num_domains = ARRAY_SIZE(rk3228_pm_domains),
926         .domain_info = rk3228_pm_domains,
927 };
928
929 static const struct rockchip_pmu_info rk3288_pmu = {
930         .pwr_offset = 0x08,
931         .status_offset = 0x0c,
932         .req_offset = 0x10,
933         .idle_offset = 0x14,
934         .ack_offset = 0x14,
935
936         .core_pwrcnt_offset = 0x34,
937         .gpu_pwrcnt_offset = 0x3c,
938
939         .core_power_transition_time = 24, /* 1us */
940         .gpu_power_transition_time = 24, /* 1us */
941
942         .num_domains = ARRAY_SIZE(rk3288_pm_domains),
943         .domain_info = rk3288_pm_domains,
944 };
945
946 static const struct rockchip_pmu_info rk3328_pmu = {
947         .req_offset = 0x414,
948         .idle_offset = 0x484,
949         .ack_offset = 0x484,
950
951         .num_domains = ARRAY_SIZE(rk3328_pm_domains),
952         .domain_info = rk3328_pm_domains,
953 };
954
955 static const struct rockchip_pmu_info rk3366_pmu = {
956         .pwr_offset = 0x0c,
957         .status_offset = 0x10,
958         .req_offset = 0x3c,
959         .idle_offset = 0x40,
960         .ack_offset = 0x40,
961
962         .core_pwrcnt_offset = 0x48,
963         .gpu_pwrcnt_offset = 0x50,
964
965         .core_power_transition_time = 24,
966         .gpu_power_transition_time = 24,
967
968         .num_domains = ARRAY_SIZE(rk3366_pm_domains),
969         .domain_info = rk3366_pm_domains,
970 };
971
972 static const struct rockchip_pmu_info rk3368_pmu = {
973         .pwr_offset = 0x0c,
974         .status_offset = 0x10,
975         .req_offset = 0x3c,
976         .idle_offset = 0x40,
977         .ack_offset = 0x40,
978
979         .core_pwrcnt_offset = 0x48,
980         .gpu_pwrcnt_offset = 0x50,
981
982         .core_power_transition_time = 24,
983         .gpu_power_transition_time = 24,
984
985         .num_domains = ARRAY_SIZE(rk3368_pm_domains),
986         .domain_info = rk3368_pm_domains,
987 };
988
989 static const struct rockchip_pmu_info rk3399_pmu = {
990         .pwr_offset = 0x14,
991         .status_offset = 0x18,
992         .req_offset = 0x60,
993         .idle_offset = 0x64,
994         .ack_offset = 0x68,
995
996         /* ARM Trusted Firmware manages power transition times */
997
998         .num_domains = ARRAY_SIZE(rk3399_pm_domains),
999         .domain_info = rk3399_pm_domains,
1000 };
1001
1002 static const struct rockchip_pmu_info rk3568_pmu = {
1003         .pwr_offset = 0xa0,
1004         .status_offset = 0x98,
1005         .req_offset = 0x50,
1006         .idle_offset = 0x68,
1007         .ack_offset = 0x60,
1008
1009         .num_domains = ARRAY_SIZE(rk3568_pm_domains),
1010         .domain_info = rk3568_pm_domains,
1011 };
1012
1013 static const struct of_device_id rockchip_pm_domain_dt_match[] = {
1014         {
1015                 .compatible = "rockchip,px30-power-controller",
1016                 .data = (void *)&px30_pmu,
1017         },
1018         {
1019                 .compatible = "rockchip,rk3036-power-controller",
1020                 .data = (void *)&rk3036_pmu,
1021         },
1022         {
1023                 .compatible = "rockchip,rk3066-power-controller",
1024                 .data = (void *)&rk3066_pmu,
1025         },
1026         {
1027                 .compatible = "rockchip,rk3128-power-controller",
1028                 .data = (void *)&rk3128_pmu,
1029         },
1030         {
1031                 .compatible = "rockchip,rk3188-power-controller",
1032                 .data = (void *)&rk3188_pmu,
1033         },
1034         {
1035                 .compatible = "rockchip,rk3228-power-controller",
1036                 .data = (void *)&rk3228_pmu,
1037         },
1038         {
1039                 .compatible = "rockchip,rk3288-power-controller",
1040                 .data = (void *)&rk3288_pmu,
1041         },
1042         {
1043                 .compatible = "rockchip,rk3328-power-controller",
1044                 .data = (void *)&rk3328_pmu,
1045         },
1046         {
1047                 .compatible = "rockchip,rk3366-power-controller",
1048                 .data = (void *)&rk3366_pmu,
1049         },
1050         {
1051                 .compatible = "rockchip,rk3368-power-controller",
1052                 .data = (void *)&rk3368_pmu,
1053         },
1054         {
1055                 .compatible = "rockchip,rk3399-power-controller",
1056                 .data = (void *)&rk3399_pmu,
1057         },
1058         {
1059                 .compatible = "rockchip,rk3568-power-controller",
1060                 .data = (void *)&rk3568_pmu,
1061         },
1062         { /* sentinel */ },
1063 };
1064
1065 static struct platform_driver rockchip_pm_domain_driver = {
1066         .probe = rockchip_pm_domain_probe,
1067         .driver = {
1068                 .name   = "rockchip-pm-domain",
1069                 .of_match_table = rockchip_pm_domain_dt_match,
1070                 /*
1071                  * We can't forcibly eject devices form power domain,
1072                  * so we can't really remove power domains once they
1073                  * were added.
1074                  */
1075                 .suppress_bind_attrs = true,
1076         },
1077 };
1078
1079 static int __init rockchip_pm_domain_drv_register(void)
1080 {
1081         return platform_driver_register(&rockchip_pm_domain_driver);
1082 }
1083 postcore_initcall(rockchip_pm_domain_drv_register);