Linux-libre 5.3.12-gnu
[librecmc/linux-libre.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
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; /* mutex lock for pmu */
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         /* 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,
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         /* check idle status for idle-only domains */
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         /* 1'b0: power on, 1'b1: power off */
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                         /* if powering down, idle request to NIU first */
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                         /* if powering up, leave idle mode */
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          * We're in the error cleanup already, so we only complain,
519          * but won't emit another error on top of the original one.
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         /* protect the zeroing of pm->num_clks */
530         mutex_lock(&pd->pmu->mutex);
531         pd->num_clks = 0;
532         mutex_unlock(&pd->pmu->mutex);
533
534         /* devm will free our memory */
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         /* devm will free our memory */
552 }
553
554 static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
555                                       u32 domain_reg_offset,
556                                       unsigned int count)
557 {
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);
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          * Configure power up and down transition delays for CORE
671          * and GPU domains.
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, /* PMU_MISC_CON1 */
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, /* PMU_MISC_CON1 */
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, /* 1us */
917         .gpu_power_transition_time = 24, /* 1us */
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         /* ARM Trusted Firmware manages power transition times */
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         { /* sentinel */ },
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                  * We can't forcibly eject devices form power domain,
1034                  * so we can't really remove power domains once they
1035                  * were added.
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);