GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / soc / rockchip / pm_domains.c
1 /*
2  * Rockchip Generic power domain support.
3  *
4  * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/io.h>
12 #include <linux/iopoll.h>
13 #include <linux/err.h>
14 #include <linux/pm_clock.h>
15 #include <linux/pm_domain.h>
16 #include <linux/of_address.h>
17 #include <linux/of_platform.h>
18 #include <linux/clk.h>
19 #include <linux/regmap.h>
20 #include <linux/mfd/syscon.h>
21 #include <dt-bindings/power/rk3288-power.h>
22 #include <dt-bindings/power/rk3328-power.h>
23 #include <dt-bindings/power/rk3366-power.h>
24 #include <dt-bindings/power/rk3368-power.h>
25 #include <dt-bindings/power/rk3399-power.h>
26
27 struct rockchip_domain_info {
28         int pwr_mask;
29         int status_mask;
30         int req_mask;
31         int idle_mask;
32         int ack_mask;
33         bool active_wakeup;
34         int pwr_w_mask;
35         int req_w_mask;
36 };
37
38 struct rockchip_pmu_info {
39         u32 pwr_offset;
40         u32 status_offset;
41         u32 req_offset;
42         u32 idle_offset;
43         u32 ack_offset;
44
45         u32 core_pwrcnt_offset;
46         u32 gpu_pwrcnt_offset;
47
48         unsigned int core_power_transition_time;
49         unsigned int gpu_power_transition_time;
50
51         int num_domains;
52         const struct rockchip_domain_info *domain_info;
53 };
54
55 #define MAX_QOS_REGS_NUM        5
56 #define QOS_PRIORITY            0x08
57 #define QOS_MODE                0x0c
58 #define QOS_BANDWIDTH           0x10
59 #define QOS_SATURATION          0x14
60 #define QOS_EXTCONTROL          0x18
61
62 struct rockchip_pm_domain {
63         struct generic_pm_domain genpd;
64         const struct rockchip_domain_info *info;
65         struct rockchip_pmu *pmu;
66         int num_qos;
67         struct regmap **qos_regmap;
68         u32 *qos_save_regs[MAX_QOS_REGS_NUM];
69         int num_clks;
70         struct clk *clks[];
71 };
72
73 struct rockchip_pmu {
74         struct device *dev;
75         struct regmap *regmap;
76         const struct rockchip_pmu_info *info;
77         struct mutex mutex; /* mutex lock for pmu */
78         struct genpd_onecell_data genpd_data;
79         struct generic_pm_domain *domains[];
80 };
81
82 #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
83
84 #define DOMAIN(pwr, status, req, idle, ack, wakeup)     \
85 {                                               \
86         .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0,          \
87         .status_mask = (status >= 0) ? BIT(status) : 0, \
88         .req_mask = (req >= 0) ? BIT(req) : 0,          \
89         .idle_mask = (idle >= 0) ? BIT(idle) : 0,       \
90         .ack_mask = (ack >= 0) ? BIT(ack) : 0,          \
91         .active_wakeup = wakeup,                        \
92 }
93
94 #define DOMAIN_M(pwr, status, req, idle, ack, wakeup)   \
95 {                                                       \
96         .pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0,   \
97         .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0,          \
98         .status_mask = (status >= 0) ? BIT(status) : 0, \
99         .req_w_mask = (req >= 0) ?  BIT(req + 16) : 0,  \
100         .req_mask = (req >= 0) ?  BIT(req) : 0,         \
101         .idle_mask = (idle >= 0) ? BIT(idle) : 0,       \
102         .ack_mask = (ack >= 0) ? BIT(ack) : 0,          \
103         .active_wakeup = wakeup,                        \
104 }
105
106 #define DOMAIN_RK3288(pwr, status, req, wakeup)         \
107         DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
108
109 #define DOMAIN_RK3328(pwr, status, req, wakeup)         \
110         DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup)
111
112 #define DOMAIN_RK3368(pwr, status, req, wakeup)         \
113         DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
114
115 #define DOMAIN_RK3399(pwr, status, req, wakeup)         \
116         DOMAIN(pwr, status, req, req, req, wakeup)
117
118 static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
119 {
120         struct rockchip_pmu *pmu = pd->pmu;
121         const struct rockchip_domain_info *pd_info = pd->info;
122         unsigned int val;
123
124         regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
125         return (val & pd_info->idle_mask) == pd_info->idle_mask;
126 }
127
128 static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
129 {
130         unsigned int val;
131
132         regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
133         return val;
134 }
135
136 static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
137                                          bool idle)
138 {
139         const struct rockchip_domain_info *pd_info = pd->info;
140         struct generic_pm_domain *genpd = &pd->genpd;
141         struct rockchip_pmu *pmu = pd->pmu;
142         unsigned int target_ack;
143         unsigned int val;
144         bool is_idle;
145         int ret;
146
147         if (pd_info->req_mask == 0)
148                 return 0;
149         else if (pd_info->req_w_mask)
150                 regmap_write(pmu->regmap, pmu->info->req_offset,
151                              idle ? (pd_info->req_mask | pd_info->req_w_mask) :
152                              pd_info->req_w_mask);
153         else
154                 regmap_update_bits(pmu->regmap, pmu->info->req_offset,
155                                    pd_info->req_mask, idle ? -1U : 0);
156
157         dsb(sy);
158
159         /* Wait util idle_ack = 1 */
160         target_ack = idle ? pd_info->ack_mask : 0;
161         ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
162                                         (val & pd_info->ack_mask) == target_ack,
163                                         0, 10000);
164         if (ret) {
165                 dev_err(pmu->dev,
166                         "failed to get ack on domain '%s', val=0x%x\n",
167                         genpd->name, val);
168                 return ret;
169         }
170
171         ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
172                                         is_idle, is_idle == idle, 0, 10000);
173         if (ret) {
174                 dev_err(pmu->dev,
175                         "failed to set idle on domain '%s', val=%d\n",
176                         genpd->name, is_idle);
177                 return ret;
178         }
179
180         return 0;
181 }
182
183 static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
184 {
185         int i;
186
187         for (i = 0; i < pd->num_qos; i++) {
188                 regmap_read(pd->qos_regmap[i],
189                             QOS_PRIORITY,
190                             &pd->qos_save_regs[0][i]);
191                 regmap_read(pd->qos_regmap[i],
192                             QOS_MODE,
193                             &pd->qos_save_regs[1][i]);
194                 regmap_read(pd->qos_regmap[i],
195                             QOS_BANDWIDTH,
196                             &pd->qos_save_regs[2][i]);
197                 regmap_read(pd->qos_regmap[i],
198                             QOS_SATURATION,
199                             &pd->qos_save_regs[3][i]);
200                 regmap_read(pd->qos_regmap[i],
201                             QOS_EXTCONTROL,
202                             &pd->qos_save_regs[4][i]);
203         }
204         return 0;
205 }
206
207 static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
208 {
209         int i;
210
211         for (i = 0; i < pd->num_qos; i++) {
212                 regmap_write(pd->qos_regmap[i],
213                              QOS_PRIORITY,
214                              pd->qos_save_regs[0][i]);
215                 regmap_write(pd->qos_regmap[i],
216                              QOS_MODE,
217                              pd->qos_save_regs[1][i]);
218                 regmap_write(pd->qos_regmap[i],
219                              QOS_BANDWIDTH,
220                              pd->qos_save_regs[2][i]);
221                 regmap_write(pd->qos_regmap[i],
222                              QOS_SATURATION,
223                              pd->qos_save_regs[3][i]);
224                 regmap_write(pd->qos_regmap[i],
225                              QOS_EXTCONTROL,
226                              pd->qos_save_regs[4][i]);
227         }
228
229         return 0;
230 }
231
232 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
233 {
234         struct rockchip_pmu *pmu = pd->pmu;
235         unsigned int val;
236
237         /* check idle status for idle-only domains */
238         if (pd->info->status_mask == 0)
239                 return !rockchip_pmu_domain_is_idle(pd);
240
241         regmap_read(pmu->regmap, pmu->info->status_offset, &val);
242
243         /* 1'b0: power on, 1'b1: power off */
244         return !(val & pd->info->status_mask);
245 }
246
247 static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
248                                              bool on)
249 {
250         struct rockchip_pmu *pmu = pd->pmu;
251         struct generic_pm_domain *genpd = &pd->genpd;
252         bool is_on;
253
254         if (pd->info->pwr_mask == 0)
255                 return;
256         else if (pd->info->pwr_w_mask)
257                 regmap_write(pmu->regmap, pmu->info->pwr_offset,
258                              on ? pd->info->pwr_w_mask :
259                              (pd->info->pwr_mask | pd->info->pwr_w_mask));
260         else
261                 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
262                                    pd->info->pwr_mask, on ? 0 : -1U);
263
264         dsb(sy);
265
266         if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
267                                       is_on == on, 0, 10000)) {
268                 dev_err(pmu->dev,
269                         "failed to set domain '%s', val=%d\n",
270                         genpd->name, is_on);
271                 return;
272         }
273 }
274
275 static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
276 {
277         int i;
278
279         mutex_lock(&pd->pmu->mutex);
280
281         if (rockchip_pmu_domain_is_on(pd) != power_on) {
282                 for (i = 0; i < pd->num_clks; i++)
283                         clk_enable(pd->clks[i]);
284
285                 if (!power_on) {
286                         rockchip_pmu_save_qos(pd);
287
288                         /* if powering down, idle request to NIU first */
289                         rockchip_pmu_set_idle_request(pd, true);
290                 }
291
292                 rockchip_do_pmu_set_power_domain(pd, power_on);
293
294                 if (power_on) {
295                         /* if powering up, leave idle mode */
296                         rockchip_pmu_set_idle_request(pd, false);
297
298                         rockchip_pmu_restore_qos(pd);
299                 }
300
301                 for (i = pd->num_clks - 1; i >= 0; i--)
302                         clk_disable(pd->clks[i]);
303         }
304
305         mutex_unlock(&pd->pmu->mutex);
306         return 0;
307 }
308
309 static int rockchip_pd_power_on(struct generic_pm_domain *domain)
310 {
311         struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
312
313         return rockchip_pd_power(pd, true);
314 }
315
316 static int rockchip_pd_power_off(struct generic_pm_domain *domain)
317 {
318         struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
319
320         return rockchip_pd_power(pd, false);
321 }
322
323 static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
324                                   struct device *dev)
325 {
326         struct clk *clk;
327         int i;
328         int error;
329
330         dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
331
332         error = pm_clk_create(dev);
333         if (error) {
334                 dev_err(dev, "pm_clk_create failed %d\n", error);
335                 return error;
336         }
337
338         i = 0;
339         while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
340                 dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
341                 error = pm_clk_add_clk(dev, clk);
342                 if (error) {
343                         dev_err(dev, "pm_clk_add_clk failed %d\n", error);
344                         clk_put(clk);
345                         pm_clk_destroy(dev);
346                         return error;
347                 }
348         }
349
350         return 0;
351 }
352
353 static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
354                                    struct device *dev)
355 {
356         dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
357
358         pm_clk_destroy(dev);
359 }
360
361 static bool rockchip_active_wakeup(struct device *dev)
362 {
363         struct generic_pm_domain *genpd;
364         struct rockchip_pm_domain *pd;
365
366         genpd = pd_to_genpd(dev->pm_domain);
367         pd = container_of(genpd, struct rockchip_pm_domain, genpd);
368
369         return pd->info->active_wakeup;
370 }
371
372 static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
373                                       struct device_node *node)
374 {
375         const struct rockchip_domain_info *pd_info;
376         struct rockchip_pm_domain *pd;
377         struct device_node *qos_node;
378         struct clk *clk;
379         int clk_cnt;
380         int i, j;
381         u32 id;
382         int error;
383
384         error = of_property_read_u32(node, "reg", &id);
385         if (error) {
386                 dev_err(pmu->dev,
387                         "%s: failed to retrieve domain id (reg): %d\n",
388                         node->name, error);
389                 return -EINVAL;
390         }
391
392         if (id >= pmu->info->num_domains) {
393                 dev_err(pmu->dev, "%s: invalid domain id %d\n",
394                         node->name, id);
395                 return -EINVAL;
396         }
397
398         pd_info = &pmu->info->domain_info[id];
399         if (!pd_info) {
400                 dev_err(pmu->dev, "%s: undefined domain id %d\n",
401                         node->name, id);
402                 return -EINVAL;
403         }
404
405         clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
406         pd = devm_kzalloc(pmu->dev,
407                           sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
408                           GFP_KERNEL);
409         if (!pd)
410                 return -ENOMEM;
411
412         pd->info = pd_info;
413         pd->pmu = pmu;
414
415         for (i = 0; i < clk_cnt; i++) {
416                 clk = of_clk_get(node, i);
417                 if (IS_ERR(clk)) {
418                         error = PTR_ERR(clk);
419                         dev_err(pmu->dev,
420                                 "%s: failed to get clk at index %d: %d\n",
421                                 node->name, i, error);
422                         goto err_out;
423                 }
424
425                 error = clk_prepare(clk);
426                 if (error) {
427                         dev_err(pmu->dev,
428                                 "%s: failed to prepare clk %pC (index %d): %d\n",
429                                 node->name, clk, i, error);
430                         clk_put(clk);
431                         goto err_out;
432                 }
433
434                 pd->clks[pd->num_clks++] = clk;
435
436                 dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n",
437                         clk, node->name);
438         }
439
440         pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
441                                                  NULL);
442
443         if (pd->num_qos > 0) {
444                 pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
445                                               sizeof(*pd->qos_regmap),
446                                               GFP_KERNEL);
447                 if (!pd->qos_regmap) {
448                         error = -ENOMEM;
449                         goto err_out;
450                 }
451
452                 for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
453                         pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
454                                                             pd->num_qos,
455                                                             sizeof(u32),
456                                                             GFP_KERNEL);
457                         if (!pd->qos_save_regs[j]) {
458                                 error = -ENOMEM;
459                                 goto err_out;
460                         }
461                 }
462
463                 for (j = 0; j < pd->num_qos; j++) {
464                         qos_node = of_parse_phandle(node, "pm_qos", j);
465                         if (!qos_node) {
466                                 error = -ENODEV;
467                                 goto err_out;
468                         }
469                         pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
470                         if (IS_ERR(pd->qos_regmap[j])) {
471                                 error = -ENODEV;
472                                 of_node_put(qos_node);
473                                 goto err_out;
474                         }
475                         of_node_put(qos_node);
476                 }
477         }
478
479         error = rockchip_pd_power(pd, true);
480         if (error) {
481                 dev_err(pmu->dev,
482                         "failed to power on domain '%s': %d\n",
483                         node->name, error);
484                 goto err_out;
485         }
486
487         pd->genpd.name = node->name;
488         pd->genpd.power_off = rockchip_pd_power_off;
489         pd->genpd.power_on = rockchip_pd_power_on;
490         pd->genpd.attach_dev = rockchip_pd_attach_dev;
491         pd->genpd.detach_dev = rockchip_pd_detach_dev;
492         pd->genpd.dev_ops.active_wakeup = rockchip_active_wakeup;
493         pd->genpd.flags = GENPD_FLAG_PM_CLK;
494         pm_genpd_init(&pd->genpd, NULL, false);
495
496         pmu->genpd_data.domains[id] = &pd->genpd;
497         return 0;
498
499 err_out:
500         while (--i >= 0) {
501                 clk_unprepare(pd->clks[i]);
502                 clk_put(pd->clks[i]);
503         }
504         return error;
505 }
506
507 static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
508 {
509         int i, ret;
510
511         /*
512          * We're in the error cleanup already, so we only complain,
513          * but won't emit another error on top of the original one.
514          */
515         ret = pm_genpd_remove(&pd->genpd);
516         if (ret < 0)
517                 dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
518                         pd->genpd.name, ret);
519
520         for (i = 0; i < pd->num_clks; i++) {
521                 clk_unprepare(pd->clks[i]);
522                 clk_put(pd->clks[i]);
523         }
524
525         /* protect the zeroing of pm->num_clks */
526         mutex_lock(&pd->pmu->mutex);
527         pd->num_clks = 0;
528         mutex_unlock(&pd->pmu->mutex);
529
530         /* devm will free our memory */
531 }
532
533 static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
534 {
535         struct generic_pm_domain *genpd;
536         struct rockchip_pm_domain *pd;
537         int i;
538
539         for (i = 0; i < pmu->genpd_data.num_domains; i++) {
540                 genpd = pmu->genpd_data.domains[i];
541                 if (genpd) {
542                         pd = to_rockchip_pd(genpd);
543                         rockchip_pm_remove_one_domain(pd);
544                 }
545         }
546
547         /* devm will free our memory */
548 }
549
550 static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
551                                       u32 domain_reg_offset,
552                                       unsigned int count)
553 {
554         /* First configure domain power down transition count ... */
555         regmap_write(pmu->regmap, domain_reg_offset, count);
556         /* ... and then power up count. */
557         regmap_write(pmu->regmap, domain_reg_offset + 4, count);
558 }
559
560 static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
561                                      struct device_node *parent)
562 {
563         struct device_node *np;
564         struct generic_pm_domain *child_domain, *parent_domain;
565         int error;
566
567         for_each_child_of_node(parent, np) {
568                 u32 idx;
569
570                 error = of_property_read_u32(parent, "reg", &idx);
571                 if (error) {
572                         dev_err(pmu->dev,
573                                 "%s: failed to retrieve domain id (reg): %d\n",
574                                 parent->name, error);
575                         goto err_out;
576                 }
577                 parent_domain = pmu->genpd_data.domains[idx];
578
579                 error = rockchip_pm_add_one_domain(pmu, np);
580                 if (error) {
581                         dev_err(pmu->dev, "failed to handle node %s: %d\n",
582                                 np->name, error);
583                         goto err_out;
584                 }
585
586                 error = of_property_read_u32(np, "reg", &idx);
587                 if (error) {
588                         dev_err(pmu->dev,
589                                 "%s: failed to retrieve domain id (reg): %d\n",
590                                 np->name, error);
591                         goto err_out;
592                 }
593                 child_domain = pmu->genpd_data.domains[idx];
594
595                 error = pm_genpd_add_subdomain(parent_domain, child_domain);
596                 if (error) {
597                         dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
598                                 parent_domain->name, child_domain->name, error);
599                         goto err_out;
600                 } else {
601                         dev_dbg(pmu->dev, "%s add subdomain: %s\n",
602                                 parent_domain->name, child_domain->name);
603                 }
604
605                 rockchip_pm_add_subdomain(pmu, np);
606         }
607
608         return 0;
609
610 err_out:
611         of_node_put(np);
612         return error;
613 }
614
615 static int rockchip_pm_domain_probe(struct platform_device *pdev)
616 {
617         struct device *dev = &pdev->dev;
618         struct device_node *np = dev->of_node;
619         struct device_node *node;
620         struct device *parent;
621         struct rockchip_pmu *pmu;
622         const struct of_device_id *match;
623         const struct rockchip_pmu_info *pmu_info;
624         int error;
625
626         if (!np) {
627                 dev_err(dev, "device tree node not found\n");
628                 return -ENODEV;
629         }
630
631         match = of_match_device(dev->driver->of_match_table, dev);
632         if (!match || !match->data) {
633                 dev_err(dev, "missing pmu data\n");
634                 return -EINVAL;
635         }
636
637         pmu_info = match->data;
638
639         pmu = devm_kzalloc(dev,
640                            sizeof(*pmu) +
641                                 pmu_info->num_domains * sizeof(pmu->domains[0]),
642                            GFP_KERNEL);
643         if (!pmu)
644                 return -ENOMEM;
645
646         pmu->dev = &pdev->dev;
647         mutex_init(&pmu->mutex);
648
649         pmu->info = pmu_info;
650
651         pmu->genpd_data.domains = pmu->domains;
652         pmu->genpd_data.num_domains = pmu_info->num_domains;
653
654         parent = dev->parent;
655         if (!parent) {
656                 dev_err(dev, "no parent for syscon devices\n");
657                 return -ENODEV;
658         }
659
660         pmu->regmap = syscon_node_to_regmap(parent->of_node);
661         if (IS_ERR(pmu->regmap)) {
662                 dev_err(dev, "no regmap available\n");
663                 return PTR_ERR(pmu->regmap);
664         }
665
666         /*
667          * Configure power up and down transition delays for CORE
668          * and GPU domains.
669          */
670         if (pmu_info->core_power_transition_time)
671                 rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
672                                         pmu_info->core_power_transition_time);
673         if (pmu_info->gpu_pwrcnt_offset)
674                 rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
675                                         pmu_info->gpu_power_transition_time);
676
677         error = -ENODEV;
678
679         for_each_available_child_of_node(np, node) {
680                 error = rockchip_pm_add_one_domain(pmu, node);
681                 if (error) {
682                         dev_err(dev, "failed to handle node %s: %d\n",
683                                 node->name, error);
684                         of_node_put(node);
685                         goto err_out;
686                 }
687
688                 error = rockchip_pm_add_subdomain(pmu, node);
689                 if (error < 0) {
690                         dev_err(dev, "failed to handle subdomain node %s: %d\n",
691                                 node->name, error);
692                         of_node_put(node);
693                         goto err_out;
694                 }
695         }
696
697         if (error) {
698                 dev_dbg(dev, "no power domains defined\n");
699                 goto err_out;
700         }
701
702         error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
703         if (error) {
704                 dev_err(dev, "failed to add provider: %d\n", error);
705                 goto err_out;
706         }
707
708         return 0;
709
710 err_out:
711         rockchip_pm_domain_cleanup(pmu);
712         return error;
713 }
714
715 static const struct rockchip_domain_info rk3288_pm_domains[] = {
716         [RK3288_PD_VIO]         = DOMAIN_RK3288(7, 7, 4, false),
717         [RK3288_PD_HEVC]        = DOMAIN_RK3288(14, 10, 9, false),
718         [RK3288_PD_VIDEO]       = DOMAIN_RK3288(8, 8, 3, false),
719         [RK3288_PD_GPU]         = DOMAIN_RK3288(9, 9, 2, false),
720 };
721
722 static const struct rockchip_domain_info rk3328_pm_domains[] = {
723         [RK3328_PD_CORE]        = DOMAIN_RK3328(-1, 0, 0, false),
724         [RK3328_PD_GPU]         = DOMAIN_RK3328(-1, 1, 1, false),
725         [RK3328_PD_BUS]         = DOMAIN_RK3328(-1, 2, 2, true),
726         [RK3328_PD_MSCH]        = DOMAIN_RK3328(-1, 3, 3, true),
727         [RK3328_PD_PERI]        = DOMAIN_RK3328(-1, 4, 4, true),
728         [RK3328_PD_VIDEO]       = DOMAIN_RK3328(-1, 5, 5, false),
729         [RK3328_PD_HEVC]        = DOMAIN_RK3328(-1, 6, 6, false),
730         [RK3328_PD_VIO]         = DOMAIN_RK3328(-1, 8, 8, false),
731         [RK3328_PD_VPU]         = DOMAIN_RK3328(-1, 9, 9, false),
732 };
733
734 static const struct rockchip_domain_info rk3366_pm_domains[] = {
735         [RK3366_PD_PERI]        = DOMAIN_RK3368(10, 10, 6, true),
736         [RK3366_PD_VIO]         = DOMAIN_RK3368(14, 14, 8, false),
737         [RK3366_PD_VIDEO]       = DOMAIN_RK3368(13, 13, 7, false),
738         [RK3366_PD_RKVDEC]      = DOMAIN_RK3368(11, 11, 7, false),
739         [RK3366_PD_WIFIBT]      = DOMAIN_RK3368(8, 8, 9, false),
740         [RK3366_PD_VPU]         = DOMAIN_RK3368(12, 12, 7, false),
741         [RK3366_PD_GPU]         = DOMAIN_RK3368(15, 15, 2, false),
742 };
743
744 static const struct rockchip_domain_info rk3368_pm_domains[] = {
745         [RK3368_PD_PERI]        = DOMAIN_RK3368(13, 12, 6, true),
746         [RK3368_PD_VIO]         = DOMAIN_RK3368(15, 14, 8, false),
747         [RK3368_PD_VIDEO]       = DOMAIN_RK3368(14, 13, 7, false),
748         [RK3368_PD_GPU_0]       = DOMAIN_RK3368(16, 15, 2, false),
749         [RK3368_PD_GPU_1]       = DOMAIN_RK3368(17, 16, 2, false),
750 };
751
752 static const struct rockchip_domain_info rk3399_pm_domains[] = {
753         [RK3399_PD_TCPD0]       = DOMAIN_RK3399(8, 8, -1, false),
754         [RK3399_PD_TCPD1]       = DOMAIN_RK3399(9, 9, -1, false),
755         [RK3399_PD_CCI]         = DOMAIN_RK3399(10, 10, -1, true),
756         [RK3399_PD_CCI0]        = DOMAIN_RK3399(-1, -1, 15, true),
757         [RK3399_PD_CCI1]        = DOMAIN_RK3399(-1, -1, 16, true),
758         [RK3399_PD_PERILP]      = DOMAIN_RK3399(11, 11, 1, true),
759         [RK3399_PD_PERIHP]      = DOMAIN_RK3399(12, 12, 2, true),
760         [RK3399_PD_CENTER]      = DOMAIN_RK3399(13, 13, 14, true),
761         [RK3399_PD_VIO]         = DOMAIN_RK3399(14, 14, 17, false),
762         [RK3399_PD_GPU]         = DOMAIN_RK3399(15, 15, 0, false),
763         [RK3399_PD_VCODEC]      = DOMAIN_RK3399(16, 16, 3, false),
764         [RK3399_PD_VDU]         = DOMAIN_RK3399(17, 17, 4, false),
765         [RK3399_PD_RGA]         = DOMAIN_RK3399(18, 18, 5, false),
766         [RK3399_PD_IEP]         = DOMAIN_RK3399(19, 19, 6, false),
767         [RK3399_PD_VO]          = DOMAIN_RK3399(20, 20, -1, false),
768         [RK3399_PD_VOPB]        = DOMAIN_RK3399(-1, -1, 7, false),
769         [RK3399_PD_VOPL]        = DOMAIN_RK3399(-1, -1, 8, false),
770         [RK3399_PD_ISP0]        = DOMAIN_RK3399(22, 22, 9, false),
771         [RK3399_PD_ISP1]        = DOMAIN_RK3399(23, 23, 10, false),
772         [RK3399_PD_HDCP]        = DOMAIN_RK3399(24, 24, 11, false),
773         [RK3399_PD_GMAC]        = DOMAIN_RK3399(25, 25, 23, true),
774         [RK3399_PD_EMMC]        = DOMAIN_RK3399(26, 26, 24, true),
775         [RK3399_PD_USB3]        = DOMAIN_RK3399(27, 27, 12, true),
776         [RK3399_PD_EDP]         = DOMAIN_RK3399(28, 28, 22, false),
777         [RK3399_PD_GIC]         = DOMAIN_RK3399(29, 29, 27, true),
778         [RK3399_PD_SD]          = DOMAIN_RK3399(30, 30, 28, true),
779         [RK3399_PD_SDIOAUDIO]   = DOMAIN_RK3399(31, 31, 29, true),
780 };
781
782 static const struct rockchip_pmu_info rk3288_pmu = {
783         .pwr_offset = 0x08,
784         .status_offset = 0x0c,
785         .req_offset = 0x10,
786         .idle_offset = 0x14,
787         .ack_offset = 0x14,
788
789         .core_pwrcnt_offset = 0x34,
790         .gpu_pwrcnt_offset = 0x3c,
791
792         .core_power_transition_time = 24, /* 1us */
793         .gpu_power_transition_time = 24, /* 1us */
794
795         .num_domains = ARRAY_SIZE(rk3288_pm_domains),
796         .domain_info = rk3288_pm_domains,
797 };
798
799 static const struct rockchip_pmu_info rk3328_pmu = {
800         .req_offset = 0x414,
801         .idle_offset = 0x484,
802         .ack_offset = 0x484,
803
804         .num_domains = ARRAY_SIZE(rk3328_pm_domains),
805         .domain_info = rk3328_pm_domains,
806 };
807
808 static const struct rockchip_pmu_info rk3366_pmu = {
809         .pwr_offset = 0x0c,
810         .status_offset = 0x10,
811         .req_offset = 0x3c,
812         .idle_offset = 0x40,
813         .ack_offset = 0x40,
814
815         .core_pwrcnt_offset = 0x48,
816         .gpu_pwrcnt_offset = 0x50,
817
818         .core_power_transition_time = 24,
819         .gpu_power_transition_time = 24,
820
821         .num_domains = ARRAY_SIZE(rk3366_pm_domains),
822         .domain_info = rk3366_pm_domains,
823 };
824
825 static const struct rockchip_pmu_info rk3368_pmu = {
826         .pwr_offset = 0x0c,
827         .status_offset = 0x10,
828         .req_offset = 0x3c,
829         .idle_offset = 0x40,
830         .ack_offset = 0x40,
831
832         .core_pwrcnt_offset = 0x48,
833         .gpu_pwrcnt_offset = 0x50,
834
835         .core_power_transition_time = 24,
836         .gpu_power_transition_time = 24,
837
838         .num_domains = ARRAY_SIZE(rk3368_pm_domains),
839         .domain_info = rk3368_pm_domains,
840 };
841
842 static const struct rockchip_pmu_info rk3399_pmu = {
843         .pwr_offset = 0x14,
844         .status_offset = 0x18,
845         .req_offset = 0x60,
846         .idle_offset = 0x64,
847         .ack_offset = 0x68,
848
849         /* ARM Trusted Firmware manages power transition times */
850
851         .num_domains = ARRAY_SIZE(rk3399_pm_domains),
852         .domain_info = rk3399_pm_domains,
853 };
854
855 static const struct of_device_id rockchip_pm_domain_dt_match[] = {
856         {
857                 .compatible = "rockchip,rk3288-power-controller",
858                 .data = (void *)&rk3288_pmu,
859         },
860         {
861                 .compatible = "rockchip,rk3328-power-controller",
862                 .data = (void *)&rk3328_pmu,
863         },
864         {
865                 .compatible = "rockchip,rk3366-power-controller",
866                 .data = (void *)&rk3366_pmu,
867         },
868         {
869                 .compatible = "rockchip,rk3368-power-controller",
870                 .data = (void *)&rk3368_pmu,
871         },
872         {
873                 .compatible = "rockchip,rk3399-power-controller",
874                 .data = (void *)&rk3399_pmu,
875         },
876         { /* sentinel */ },
877 };
878
879 static struct platform_driver rockchip_pm_domain_driver = {
880         .probe = rockchip_pm_domain_probe,
881         .driver = {
882                 .name   = "rockchip-pm-domain",
883                 .of_match_table = rockchip_pm_domain_dt_match,
884                 /*
885                  * We can't forcibly eject devices form power domain,
886                  * so we can't really remove power domains once they
887                  * were added.
888                  */
889                 .suppress_bind_attrs = true,
890         },
891 };
892
893 static int __init rockchip_pm_domain_drv_register(void)
894 {
895         return platform_driver_register(&rockchip_pm_domain_driver);
896 }
897 postcore_initcall(rockchip_pm_domain_drv_register);