Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Rockchip Generic power domain support.
0004  *
0005  * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
0006  */
0007 
0008 #include <linux/io.h>
0009 #include <linux/iopoll.h>
0010 #include <linux/err.h>
0011 #include <linux/mutex.h>
0012 #include <linux/pm_clock.h>
0013 #include <linux/pm_domain.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_clk.h>
0016 #include <linux/of_platform.h>
0017 #include <linux/clk.h>
0018 #include <linux/regmap.h>
0019 #include <linux/mfd/syscon.h>
0020 #include <soc/rockchip/pm_domains.h>
0021 #include <dt-bindings/power/px30-power.h>
0022 #include <dt-bindings/power/rk3036-power.h>
0023 #include <dt-bindings/power/rk3066-power.h>
0024 #include <dt-bindings/power/rk3128-power.h>
0025 #include <dt-bindings/power/rk3188-power.h>
0026 #include <dt-bindings/power/rk3228-power.h>
0027 #include <dt-bindings/power/rk3288-power.h>
0028 #include <dt-bindings/power/rk3328-power.h>
0029 #include <dt-bindings/power/rk3366-power.h>
0030 #include <dt-bindings/power/rk3368-power.h>
0031 #include <dt-bindings/power/rk3399-power.h>
0032 #include <dt-bindings/power/rk3568-power.h>
0033 
0034 struct rockchip_domain_info {
0035     const char *name;
0036     int pwr_mask;
0037     int status_mask;
0038     int req_mask;
0039     int idle_mask;
0040     int ack_mask;
0041     bool active_wakeup;
0042     int pwr_w_mask;
0043     int req_w_mask;
0044 };
0045 
0046 struct rockchip_pmu_info {
0047     u32 pwr_offset;
0048     u32 status_offset;
0049     u32 req_offset;
0050     u32 idle_offset;
0051     u32 ack_offset;
0052 
0053     u32 core_pwrcnt_offset;
0054     u32 gpu_pwrcnt_offset;
0055 
0056     unsigned int core_power_transition_time;
0057     unsigned int gpu_power_transition_time;
0058 
0059     int num_domains;
0060     const struct rockchip_domain_info *domain_info;
0061 };
0062 
0063 #define MAX_QOS_REGS_NUM    5
0064 #define QOS_PRIORITY        0x08
0065 #define QOS_MODE        0x0c
0066 #define QOS_BANDWIDTH       0x10
0067 #define QOS_SATURATION      0x14
0068 #define QOS_EXTCONTROL      0x18
0069 
0070 struct rockchip_pm_domain {
0071     struct generic_pm_domain genpd;
0072     const struct rockchip_domain_info *info;
0073     struct rockchip_pmu *pmu;
0074     int num_qos;
0075     struct regmap **qos_regmap;
0076     u32 *qos_save_regs[MAX_QOS_REGS_NUM];
0077     int num_clks;
0078     struct clk_bulk_data *clks;
0079 };
0080 
0081 struct rockchip_pmu {
0082     struct device *dev;
0083     struct regmap *regmap;
0084     const struct rockchip_pmu_info *info;
0085     struct mutex mutex; /* mutex lock for pmu */
0086     struct genpd_onecell_data genpd_data;
0087     struct generic_pm_domain *domains[];
0088 };
0089 
0090 #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
0091 
0092 #define DOMAIN(_name, pwr, status, req, idle, ack, wakeup)  \
0093 {                           \
0094     .name = _name,              \
0095     .pwr_mask = (pwr),              \
0096     .status_mask = (status),            \
0097     .req_mask = (req),              \
0098     .idle_mask = (idle),                \
0099     .ack_mask = (ack),              \
0100     .active_wakeup = (wakeup),          \
0101 }
0102 
0103 #define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup)    \
0104 {                           \
0105     .name = _name,              \
0106     .pwr_w_mask = (pwr) << 16,          \
0107     .pwr_mask = (pwr),              \
0108     .status_mask = (status),            \
0109     .req_w_mask = (req) << 16,          \
0110     .req_mask = (req),              \
0111     .idle_mask = (idle),                \
0112     .ack_mask = (ack),              \
0113     .active_wakeup = wakeup,            \
0114 }
0115 
0116 #define DOMAIN_RK3036(_name, req, ack, idle, wakeup)        \
0117 {                           \
0118     .name = _name,              \
0119     .req_mask = (req),              \
0120     .req_w_mask = (req) << 16,          \
0121     .ack_mask = (ack),              \
0122     .idle_mask = (idle),                \
0123     .active_wakeup = wakeup,            \
0124 }
0125 
0126 #define DOMAIN_PX30(name, pwr, status, req, wakeup)     \
0127     DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
0128 
0129 #define DOMAIN_RK3288(name, pwr, status, req, wakeup)       \
0130     DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
0131 
0132 #define DOMAIN_RK3328(name, pwr, status, req, wakeup)       \
0133     DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup)
0134 
0135 #define DOMAIN_RK3368(name, pwr, status, req, wakeup)       \
0136     DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup)
0137 
0138 #define DOMAIN_RK3399(name, pwr, status, req, wakeup)       \
0139     DOMAIN(name, pwr, status, req, req, req, wakeup)
0140 
0141 #define DOMAIN_RK3568(name, pwr, req, wakeup)       \
0142     DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
0143 
0144 /*
0145  * Dynamic Memory Controller may need to coordinate with us -- see
0146  * rockchip_pmu_block().
0147  *
0148  * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to
0149  * block() while we're initializing the PMU.
0150  */
0151 static DEFINE_MUTEX(dmc_pmu_mutex);
0152 static struct rockchip_pmu *dmc_pmu;
0153 
0154 /*
0155  * Block PMU transitions and make sure they don't interfere with ARM Trusted
0156  * Firmware operations. There are two conflicts, noted in the comments below.
0157  *
0158  * Caller must unblock PMU transitions via rockchip_pmu_unblock().
0159  */
0160 int rockchip_pmu_block(void)
0161 {
0162     struct rockchip_pmu *pmu;
0163     struct generic_pm_domain *genpd;
0164     struct rockchip_pm_domain *pd;
0165     int i, ret;
0166 
0167     mutex_lock(&dmc_pmu_mutex);
0168 
0169     /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */
0170     if (!dmc_pmu)
0171         return 0;
0172     pmu = dmc_pmu;
0173 
0174     /*
0175      * mutex blocks all idle transitions: we can't touch the
0176      * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted
0177      * Firmware might be using it.
0178      */
0179     mutex_lock(&pmu->mutex);
0180 
0181     /*
0182      * Power domain clocks: Per Rockchip, we *must* keep certain clocks
0183      * enabled for the duration of power-domain transitions. Most
0184      * transitions are handled by this driver, but some cases (in
0185      * particular, DRAM DVFS / memory-controller idle) must be handled by
0186      * firmware. Firmware can handle most clock management via a special
0187      * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this
0188      * doesn't handle PLLs. We can assist this transition by doing the
0189      * clock management on behalf of firmware.
0190      */
0191     for (i = 0; i < pmu->genpd_data.num_domains; i++) {
0192         genpd = pmu->genpd_data.domains[i];
0193         if (genpd) {
0194             pd = to_rockchip_pd(genpd);
0195             ret = clk_bulk_enable(pd->num_clks, pd->clks);
0196             if (ret < 0) {
0197                 dev_err(pmu->dev,
0198                     "failed to enable clks for domain '%s': %d\n",
0199                     genpd->name, ret);
0200                 goto err;
0201             }
0202         }
0203     }
0204 
0205     return 0;
0206 
0207 err:
0208     for (i = i - 1; i >= 0; i--) {
0209         genpd = pmu->genpd_data.domains[i];
0210         if (genpd) {
0211             pd = to_rockchip_pd(genpd);
0212             clk_bulk_disable(pd->num_clks, pd->clks);
0213         }
0214     }
0215     mutex_unlock(&pmu->mutex);
0216     mutex_unlock(&dmc_pmu_mutex);
0217 
0218     return ret;
0219 }
0220 EXPORT_SYMBOL_GPL(rockchip_pmu_block);
0221 
0222 /* Unblock PMU transitions. */
0223 void rockchip_pmu_unblock(void)
0224 {
0225     struct rockchip_pmu *pmu;
0226     struct generic_pm_domain *genpd;
0227     struct rockchip_pm_domain *pd;
0228     int i;
0229 
0230     if (dmc_pmu) {
0231         pmu = dmc_pmu;
0232         for (i = 0; i < pmu->genpd_data.num_domains; i++) {
0233             genpd = pmu->genpd_data.domains[i];
0234             if (genpd) {
0235                 pd = to_rockchip_pd(genpd);
0236                 clk_bulk_disable(pd->num_clks, pd->clks);
0237             }
0238         }
0239 
0240         mutex_unlock(&pmu->mutex);
0241     }
0242 
0243     mutex_unlock(&dmc_pmu_mutex);
0244 }
0245 EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
0246 
0247 static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
0248 {
0249     struct rockchip_pmu *pmu = pd->pmu;
0250     const struct rockchip_domain_info *pd_info = pd->info;
0251     unsigned int val;
0252 
0253     regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
0254     return (val & pd_info->idle_mask) == pd_info->idle_mask;
0255 }
0256 
0257 static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
0258 {
0259     unsigned int val;
0260 
0261     regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
0262     return val;
0263 }
0264 
0265 static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
0266                      bool idle)
0267 {
0268     const struct rockchip_domain_info *pd_info = pd->info;
0269     struct generic_pm_domain *genpd = &pd->genpd;
0270     struct rockchip_pmu *pmu = pd->pmu;
0271     unsigned int target_ack;
0272     unsigned int val;
0273     bool is_idle;
0274     int ret;
0275 
0276     if (pd_info->req_mask == 0)
0277         return 0;
0278     else if (pd_info->req_w_mask)
0279         regmap_write(pmu->regmap, pmu->info->req_offset,
0280                  idle ? (pd_info->req_mask | pd_info->req_w_mask) :
0281                  pd_info->req_w_mask);
0282     else
0283         regmap_update_bits(pmu->regmap, pmu->info->req_offset,
0284                    pd_info->req_mask, idle ? -1U : 0);
0285 
0286     wmb();
0287 
0288     /* Wait util idle_ack = 1 */
0289     target_ack = idle ? pd_info->ack_mask : 0;
0290     ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
0291                     (val & pd_info->ack_mask) == target_ack,
0292                     0, 10000);
0293     if (ret) {
0294         dev_err(pmu->dev,
0295             "failed to get ack on domain '%s', val=0x%x\n",
0296             genpd->name, val);
0297         return ret;
0298     }
0299 
0300     ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
0301                     is_idle, is_idle == idle, 0, 10000);
0302     if (ret) {
0303         dev_err(pmu->dev,
0304             "failed to set idle on domain '%s', val=%d\n",
0305             genpd->name, is_idle);
0306         return ret;
0307     }
0308 
0309     return 0;
0310 }
0311 
0312 static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
0313 {
0314     int i;
0315 
0316     for (i = 0; i < pd->num_qos; i++) {
0317         regmap_read(pd->qos_regmap[i],
0318                 QOS_PRIORITY,
0319                 &pd->qos_save_regs[0][i]);
0320         regmap_read(pd->qos_regmap[i],
0321                 QOS_MODE,
0322                 &pd->qos_save_regs[1][i]);
0323         regmap_read(pd->qos_regmap[i],
0324                 QOS_BANDWIDTH,
0325                 &pd->qos_save_regs[2][i]);
0326         regmap_read(pd->qos_regmap[i],
0327                 QOS_SATURATION,
0328                 &pd->qos_save_regs[3][i]);
0329         regmap_read(pd->qos_regmap[i],
0330                 QOS_EXTCONTROL,
0331                 &pd->qos_save_regs[4][i]);
0332     }
0333     return 0;
0334 }
0335 
0336 static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
0337 {
0338     int i;
0339 
0340     for (i = 0; i < pd->num_qos; i++) {
0341         regmap_write(pd->qos_regmap[i],
0342                  QOS_PRIORITY,
0343                  pd->qos_save_regs[0][i]);
0344         regmap_write(pd->qos_regmap[i],
0345                  QOS_MODE,
0346                  pd->qos_save_regs[1][i]);
0347         regmap_write(pd->qos_regmap[i],
0348                  QOS_BANDWIDTH,
0349                  pd->qos_save_regs[2][i]);
0350         regmap_write(pd->qos_regmap[i],
0351                  QOS_SATURATION,
0352                  pd->qos_save_regs[3][i]);
0353         regmap_write(pd->qos_regmap[i],
0354                  QOS_EXTCONTROL,
0355                  pd->qos_save_regs[4][i]);
0356     }
0357 
0358     return 0;
0359 }
0360 
0361 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
0362 {
0363     struct rockchip_pmu *pmu = pd->pmu;
0364     unsigned int val;
0365 
0366     /* check idle status for idle-only domains */
0367     if (pd->info->status_mask == 0)
0368         return !rockchip_pmu_domain_is_idle(pd);
0369 
0370     regmap_read(pmu->regmap, pmu->info->status_offset, &val);
0371 
0372     /* 1'b0: power on, 1'b1: power off */
0373     return !(val & pd->info->status_mask);
0374 }
0375 
0376 static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
0377                          bool on)
0378 {
0379     struct rockchip_pmu *pmu = pd->pmu;
0380     struct generic_pm_domain *genpd = &pd->genpd;
0381     bool is_on;
0382 
0383     if (pd->info->pwr_mask == 0)
0384         return;
0385     else if (pd->info->pwr_w_mask)
0386         regmap_write(pmu->regmap, pmu->info->pwr_offset,
0387                  on ? pd->info->pwr_w_mask :
0388                  (pd->info->pwr_mask | pd->info->pwr_w_mask));
0389     else
0390         regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
0391                    pd->info->pwr_mask, on ? 0 : -1U);
0392 
0393     wmb();
0394 
0395     if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
0396                       is_on == on, 0, 10000)) {
0397         dev_err(pmu->dev,
0398             "failed to set domain '%s', val=%d\n",
0399             genpd->name, is_on);
0400         return;
0401     }
0402 }
0403 
0404 static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
0405 {
0406     struct rockchip_pmu *pmu = pd->pmu;
0407     int ret;
0408 
0409     mutex_lock(&pmu->mutex);
0410 
0411     if (rockchip_pmu_domain_is_on(pd) != power_on) {
0412         ret = clk_bulk_enable(pd->num_clks, pd->clks);
0413         if (ret < 0) {
0414             dev_err(pmu->dev, "failed to enable clocks\n");
0415             mutex_unlock(&pmu->mutex);
0416             return ret;
0417         }
0418 
0419         if (!power_on) {
0420             rockchip_pmu_save_qos(pd);
0421 
0422             /* if powering down, idle request to NIU first */
0423             rockchip_pmu_set_idle_request(pd, true);
0424         }
0425 
0426         rockchip_do_pmu_set_power_domain(pd, power_on);
0427 
0428         if (power_on) {
0429             /* if powering up, leave idle mode */
0430             rockchip_pmu_set_idle_request(pd, false);
0431 
0432             rockchip_pmu_restore_qos(pd);
0433         }
0434 
0435         clk_bulk_disable(pd->num_clks, pd->clks);
0436     }
0437 
0438     mutex_unlock(&pmu->mutex);
0439     return 0;
0440 }
0441 
0442 static int rockchip_pd_power_on(struct generic_pm_domain *domain)
0443 {
0444     struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
0445 
0446     return rockchip_pd_power(pd, true);
0447 }
0448 
0449 static int rockchip_pd_power_off(struct generic_pm_domain *domain)
0450 {
0451     struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
0452 
0453     return rockchip_pd_power(pd, false);
0454 }
0455 
0456 static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
0457                   struct device *dev)
0458 {
0459     struct clk *clk;
0460     int i;
0461     int error;
0462 
0463     dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
0464 
0465     error = pm_clk_create(dev);
0466     if (error) {
0467         dev_err(dev, "pm_clk_create failed %d\n", error);
0468         return error;
0469     }
0470 
0471     i = 0;
0472     while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
0473         dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
0474         error = pm_clk_add_clk(dev, clk);
0475         if (error) {
0476             dev_err(dev, "pm_clk_add_clk failed %d\n", error);
0477             clk_put(clk);
0478             pm_clk_destroy(dev);
0479             return error;
0480         }
0481     }
0482 
0483     return 0;
0484 }
0485 
0486 static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
0487                    struct device *dev)
0488 {
0489     dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
0490 
0491     pm_clk_destroy(dev);
0492 }
0493 
0494 static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
0495                       struct device_node *node)
0496 {
0497     const struct rockchip_domain_info *pd_info;
0498     struct rockchip_pm_domain *pd;
0499     struct device_node *qos_node;
0500     int i, j;
0501     u32 id;
0502     int error;
0503 
0504     error = of_property_read_u32(node, "reg", &id);
0505     if (error) {
0506         dev_err(pmu->dev,
0507             "%pOFn: failed to retrieve domain id (reg): %d\n",
0508             node, error);
0509         return -EINVAL;
0510     }
0511 
0512     if (id >= pmu->info->num_domains) {
0513         dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
0514             node, id);
0515         return -EINVAL;
0516     }
0517 
0518     pd_info = &pmu->info->domain_info[id];
0519     if (!pd_info) {
0520         dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
0521             node, id);
0522         return -EINVAL;
0523     }
0524 
0525     pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
0526     if (!pd)
0527         return -ENOMEM;
0528 
0529     pd->info = pd_info;
0530     pd->pmu = pmu;
0531 
0532     pd->num_clks = of_clk_get_parent_count(node);
0533     if (pd->num_clks > 0) {
0534         pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
0535                     sizeof(*pd->clks), GFP_KERNEL);
0536         if (!pd->clks)
0537             return -ENOMEM;
0538     } else {
0539         dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
0540             node, pd->num_clks);
0541         pd->num_clks = 0;
0542     }
0543 
0544     for (i = 0; i < pd->num_clks; i++) {
0545         pd->clks[i].clk = of_clk_get(node, i);
0546         if (IS_ERR(pd->clks[i].clk)) {
0547             error = PTR_ERR(pd->clks[i].clk);
0548             dev_err(pmu->dev,
0549                 "%pOFn: failed to get clk at index %d: %d\n",
0550                 node, i, error);
0551             return error;
0552         }
0553     }
0554 
0555     error = clk_bulk_prepare(pd->num_clks, pd->clks);
0556     if (error)
0557         goto err_put_clocks;
0558 
0559     pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
0560                          NULL);
0561 
0562     if (pd->num_qos > 0) {
0563         pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
0564                           sizeof(*pd->qos_regmap),
0565                           GFP_KERNEL);
0566         if (!pd->qos_regmap) {
0567             error = -ENOMEM;
0568             goto err_unprepare_clocks;
0569         }
0570 
0571         for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
0572             pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
0573                                 pd->num_qos,
0574                                 sizeof(u32),
0575                                 GFP_KERNEL);
0576             if (!pd->qos_save_regs[j]) {
0577                 error = -ENOMEM;
0578                 goto err_unprepare_clocks;
0579             }
0580         }
0581 
0582         for (j = 0; j < pd->num_qos; j++) {
0583             qos_node = of_parse_phandle(node, "pm_qos", j);
0584             if (!qos_node) {
0585                 error = -ENODEV;
0586                 goto err_unprepare_clocks;
0587             }
0588             pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
0589             if (IS_ERR(pd->qos_regmap[j])) {
0590                 error = -ENODEV;
0591                 of_node_put(qos_node);
0592                 goto err_unprepare_clocks;
0593             }
0594             of_node_put(qos_node);
0595         }
0596     }
0597 
0598     error = rockchip_pd_power(pd, true);
0599     if (error) {
0600         dev_err(pmu->dev,
0601             "failed to power on domain '%pOFn': %d\n",
0602             node, error);
0603         goto err_unprepare_clocks;
0604     }
0605 
0606     if (pd->info->name)
0607         pd->genpd.name = pd->info->name;
0608     else
0609         pd->genpd.name = kbasename(node->full_name);
0610     pd->genpd.power_off = rockchip_pd_power_off;
0611     pd->genpd.power_on = rockchip_pd_power_on;
0612     pd->genpd.attach_dev = rockchip_pd_attach_dev;
0613     pd->genpd.detach_dev = rockchip_pd_detach_dev;
0614     pd->genpd.flags = GENPD_FLAG_PM_CLK;
0615     if (pd_info->active_wakeup)
0616         pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
0617     pm_genpd_init(&pd->genpd, NULL, false);
0618 
0619     pmu->genpd_data.domains[id] = &pd->genpd;
0620     return 0;
0621 
0622 err_unprepare_clocks:
0623     clk_bulk_unprepare(pd->num_clks, pd->clks);
0624 err_put_clocks:
0625     clk_bulk_put(pd->num_clks, pd->clks);
0626     return error;
0627 }
0628 
0629 static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
0630 {
0631     int ret;
0632 
0633     /*
0634      * We're in the error cleanup already, so we only complain,
0635      * but won't emit another error on top of the original one.
0636      */
0637     ret = pm_genpd_remove(&pd->genpd);
0638     if (ret < 0)
0639         dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
0640             pd->genpd.name, ret);
0641 
0642     clk_bulk_unprepare(pd->num_clks, pd->clks);
0643     clk_bulk_put(pd->num_clks, pd->clks);
0644 
0645     /* protect the zeroing of pm->num_clks */
0646     mutex_lock(&pd->pmu->mutex);
0647     pd->num_clks = 0;
0648     mutex_unlock(&pd->pmu->mutex);
0649 
0650     /* devm will free our memory */
0651 }
0652 
0653 static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
0654 {
0655     struct generic_pm_domain *genpd;
0656     struct rockchip_pm_domain *pd;
0657     int i;
0658 
0659     for (i = 0; i < pmu->genpd_data.num_domains; i++) {
0660         genpd = pmu->genpd_data.domains[i];
0661         if (genpd) {
0662             pd = to_rockchip_pd(genpd);
0663             rockchip_pm_remove_one_domain(pd);
0664         }
0665     }
0666 
0667     /* devm will free our memory */
0668 }
0669 
0670 static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
0671                       u32 domain_reg_offset,
0672                       unsigned int count)
0673 {
0674     /* First configure domain power down transition count ... */
0675     regmap_write(pmu->regmap, domain_reg_offset, count);
0676     /* ... and then power up count. */
0677     regmap_write(pmu->regmap, domain_reg_offset + 4, count);
0678 }
0679 
0680 static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
0681                      struct device_node *parent)
0682 {
0683     struct device_node *np;
0684     struct generic_pm_domain *child_domain, *parent_domain;
0685     int error;
0686 
0687     for_each_child_of_node(parent, np) {
0688         u32 idx;
0689 
0690         error = of_property_read_u32(parent, "reg", &idx);
0691         if (error) {
0692             dev_err(pmu->dev,
0693                 "%pOFn: failed to retrieve domain id (reg): %d\n",
0694                 parent, error);
0695             goto err_out;
0696         }
0697         parent_domain = pmu->genpd_data.domains[idx];
0698 
0699         error = rockchip_pm_add_one_domain(pmu, np);
0700         if (error) {
0701             dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
0702                 np, error);
0703             goto err_out;
0704         }
0705 
0706         error = of_property_read_u32(np, "reg", &idx);
0707         if (error) {
0708             dev_err(pmu->dev,
0709                 "%pOFn: failed to retrieve domain id (reg): %d\n",
0710                 np, error);
0711             goto err_out;
0712         }
0713         child_domain = pmu->genpd_data.domains[idx];
0714 
0715         error = pm_genpd_add_subdomain(parent_domain, child_domain);
0716         if (error) {
0717             dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
0718                 parent_domain->name, child_domain->name, error);
0719             goto err_out;
0720         } else {
0721             dev_dbg(pmu->dev, "%s add subdomain: %s\n",
0722                 parent_domain->name, child_domain->name);
0723         }
0724 
0725         rockchip_pm_add_subdomain(pmu, np);
0726     }
0727 
0728     return 0;
0729 
0730 err_out:
0731     of_node_put(np);
0732     return error;
0733 }
0734 
0735 static int rockchip_pm_domain_probe(struct platform_device *pdev)
0736 {
0737     struct device *dev = &pdev->dev;
0738     struct device_node *np = dev->of_node;
0739     struct device_node *node;
0740     struct device *parent;
0741     struct rockchip_pmu *pmu;
0742     const struct of_device_id *match;
0743     const struct rockchip_pmu_info *pmu_info;
0744     int error;
0745 
0746     if (!np) {
0747         dev_err(dev, "device tree node not found\n");
0748         return -ENODEV;
0749     }
0750 
0751     match = of_match_device(dev->driver->of_match_table, dev);
0752     if (!match || !match->data) {
0753         dev_err(dev, "missing pmu data\n");
0754         return -EINVAL;
0755     }
0756 
0757     pmu_info = match->data;
0758 
0759     pmu = devm_kzalloc(dev,
0760                struct_size(pmu, domains, pmu_info->num_domains),
0761                GFP_KERNEL);
0762     if (!pmu)
0763         return -ENOMEM;
0764 
0765     pmu->dev = &pdev->dev;
0766     mutex_init(&pmu->mutex);
0767 
0768     pmu->info = pmu_info;
0769 
0770     pmu->genpd_data.domains = pmu->domains;
0771     pmu->genpd_data.num_domains = pmu_info->num_domains;
0772 
0773     parent = dev->parent;
0774     if (!parent) {
0775         dev_err(dev, "no parent for syscon devices\n");
0776         return -ENODEV;
0777     }
0778 
0779     pmu->regmap = syscon_node_to_regmap(parent->of_node);
0780     if (IS_ERR(pmu->regmap)) {
0781         dev_err(dev, "no regmap available\n");
0782         return PTR_ERR(pmu->regmap);
0783     }
0784 
0785     /*
0786      * Configure power up and down transition delays for CORE
0787      * and GPU domains.
0788      */
0789     if (pmu_info->core_power_transition_time)
0790         rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
0791                     pmu_info->core_power_transition_time);
0792     if (pmu_info->gpu_pwrcnt_offset)
0793         rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
0794                     pmu_info->gpu_power_transition_time);
0795 
0796     error = -ENODEV;
0797 
0798     /*
0799      * Prevent any rockchip_pmu_block() from racing with the remainder of
0800      * setup (clocks, register initialization).
0801      */
0802     mutex_lock(&dmc_pmu_mutex);
0803 
0804     for_each_available_child_of_node(np, node) {
0805         error = rockchip_pm_add_one_domain(pmu, node);
0806         if (error) {
0807             dev_err(dev, "failed to handle node %pOFn: %d\n",
0808                 node, error);
0809             of_node_put(node);
0810             goto err_out;
0811         }
0812 
0813         error = rockchip_pm_add_subdomain(pmu, node);
0814         if (error < 0) {
0815             dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
0816                 node, error);
0817             of_node_put(node);
0818             goto err_out;
0819         }
0820     }
0821 
0822     if (error) {
0823         dev_dbg(dev, "no power domains defined\n");
0824         goto err_out;
0825     }
0826 
0827     error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
0828     if (error) {
0829         dev_err(dev, "failed to add provider: %d\n", error);
0830         goto err_out;
0831     }
0832 
0833     /* We only expect one PMU. */
0834     if (!WARN_ON_ONCE(dmc_pmu))
0835         dmc_pmu = pmu;
0836 
0837     mutex_unlock(&dmc_pmu_mutex);
0838 
0839     return 0;
0840 
0841 err_out:
0842     rockchip_pm_domain_cleanup(pmu);
0843     mutex_unlock(&dmc_pmu_mutex);
0844     return error;
0845 }
0846 
0847 static const struct rockchip_domain_info px30_pm_domains[] = {
0848     [PX30_PD_USB]       = DOMAIN_PX30("usb",      BIT(5),  BIT(5),  BIT(10), false),
0849     [PX30_PD_SDCARD]    = DOMAIN_PX30("sdcard",   BIT(8),  BIT(8),  BIT(9),  false),
0850     [PX30_PD_GMAC]      = DOMAIN_PX30("gmac",     BIT(10), BIT(10), BIT(6),  false),
0851     [PX30_PD_MMC_NAND]  = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5),  false),
0852     [PX30_PD_VPU]       = DOMAIN_PX30("vpu",      BIT(12), BIT(12), BIT(14), false),
0853     [PX30_PD_VO]        = DOMAIN_PX30("vo",       BIT(13), BIT(13), BIT(7),  false),
0854     [PX30_PD_VI]        = DOMAIN_PX30("vi",       BIT(14), BIT(14), BIT(8),  false),
0855     [PX30_PD_GPU]       = DOMAIN_PX30("gpu",      BIT(15), BIT(15), BIT(2),  false),
0856 };
0857 
0858 static const struct rockchip_domain_info rk3036_pm_domains[] = {
0859     [RK3036_PD_MSCH]    = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
0860     [RK3036_PD_CORE]    = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
0861     [RK3036_PD_PERI]    = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false),
0862     [RK3036_PD_VIO]     = DOMAIN_RK3036("vio",  BIT(11), BIT(19), BIT(26), false),
0863     [RK3036_PD_VPU]     = DOMAIN_RK3036("vpu",  BIT(10), BIT(20), BIT(27), false),
0864     [RK3036_PD_GPU]     = DOMAIN_RK3036("gpu",  BIT(9),  BIT(21), BIT(28), false),
0865     [RK3036_PD_SYS]     = DOMAIN_RK3036("sys",  BIT(8),  BIT(22), BIT(29), false),
0866 };
0867 
0868 static const struct rockchip_domain_info rk3066_pm_domains[] = {
0869     [RK3066_PD_GPU]     = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
0870     [RK3066_PD_VIDEO]   = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
0871     [RK3066_PD_VIO]     = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
0872     [RK3066_PD_PERI]    = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
0873     [RK3066_PD_CPU]     = DOMAIN("cpu",   0,      BIT(5), BIT(1), BIT(26), BIT(31), false),
0874 };
0875 
0876 static const struct rockchip_domain_info rk3128_pm_domains[] = {
0877     [RK3128_PD_CORE]    = DOMAIN_RK3288("core",  BIT(0), BIT(0), BIT(4), false),
0878     [RK3128_PD_MSCH]    = DOMAIN_RK3288("msch",  0,      0,      BIT(6), true),
0879     [RK3128_PD_VIO]     = DOMAIN_RK3288("vio",   BIT(3), BIT(3), BIT(2), false),
0880     [RK3128_PD_VIDEO]   = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false),
0881     [RK3128_PD_GPU]     = DOMAIN_RK3288("gpu",   BIT(1), BIT(1), BIT(3), false),
0882 };
0883 
0884 static const struct rockchip_domain_info rk3188_pm_domains[] = {
0885     [RK3188_PD_GPU]     = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
0886     [RK3188_PD_VIDEO]   = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
0887     [RK3188_PD_VIO]     = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
0888     [RK3188_PD_PERI]    = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
0889     [RK3188_PD_CPU]     = DOMAIN("cpu",   BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
0890 };
0891 
0892 static const struct rockchip_domain_info rk3228_pm_domains[] = {
0893     [RK3228_PD_CORE]    = DOMAIN_RK3036("core", BIT(0),  BIT(0),  BIT(16), true),
0894     [RK3228_PD_MSCH]    = DOMAIN_RK3036("msch", BIT(1),  BIT(1),  BIT(17), true),
0895     [RK3228_PD_BUS]     = DOMAIN_RK3036("bus",  BIT(2),  BIT(2),  BIT(18), true),
0896     [RK3228_PD_SYS]     = DOMAIN_RK3036("sys",  BIT(3),  BIT(3),  BIT(19), true),
0897     [RK3228_PD_VIO]     = DOMAIN_RK3036("vio",  BIT(4),  BIT(4),  BIT(20), false),
0898     [RK3228_PD_VOP]     = DOMAIN_RK3036("vop",  BIT(5),  BIT(5),  BIT(21), false),
0899     [RK3228_PD_VPU]     = DOMAIN_RK3036("vpu",  BIT(6),  BIT(6),  BIT(22), false),
0900     [RK3228_PD_RKVDEC]  = DOMAIN_RK3036("vdec", BIT(7),  BIT(7),  BIT(23), false),
0901     [RK3228_PD_GPU]     = DOMAIN_RK3036("gpu",  BIT(8),  BIT(8),  BIT(24), false),
0902     [RK3228_PD_PERI]    = DOMAIN_RK3036("peri", BIT(9),  BIT(9),  BIT(25), true),
0903     [RK3228_PD_GMAC]    = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false),
0904 };
0905 
0906 static const struct rockchip_domain_info rk3288_pm_domains[] = {
0907     [RK3288_PD_VIO]     = DOMAIN_RK3288("vio",   BIT(7),  BIT(7),  BIT(4), false),
0908     [RK3288_PD_HEVC]    = DOMAIN_RK3288("hevc",  BIT(14), BIT(10), BIT(9), false),
0909     [RK3288_PD_VIDEO]   = DOMAIN_RK3288("video", BIT(8),  BIT(8),  BIT(3), false),
0910     [RK3288_PD_GPU]     = DOMAIN_RK3288("gpu",   BIT(9),  BIT(9),  BIT(2), false),
0911 };
0912 
0913 static const struct rockchip_domain_info rk3328_pm_domains[] = {
0914     [RK3328_PD_CORE]    = DOMAIN_RK3328("core",  0, BIT(0), BIT(0), false),
0915     [RK3328_PD_GPU]     = DOMAIN_RK3328("gpu",   0, BIT(1), BIT(1), false),
0916     [RK3328_PD_BUS]     = DOMAIN_RK3328("bus",   0, BIT(2), BIT(2), true),
0917     [RK3328_PD_MSCH]    = DOMAIN_RK3328("msch",  0, BIT(3), BIT(3), true),
0918     [RK3328_PD_PERI]    = DOMAIN_RK3328("peri",  0, BIT(4), BIT(4), true),
0919     [RK3328_PD_VIDEO]   = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false),
0920     [RK3328_PD_HEVC]    = DOMAIN_RK3328("hevc",  0, BIT(6), BIT(6), false),
0921     [RK3328_PD_VIO]     = DOMAIN_RK3328("vio",   0, BIT(8), BIT(8), false),
0922     [RK3328_PD_VPU]     = DOMAIN_RK3328("vpu",   0, BIT(9), BIT(9), false),
0923 };
0924 
0925 static const struct rockchip_domain_info rk3366_pm_domains[] = {
0926     [RK3366_PD_PERI]    = DOMAIN_RK3368("peri",   BIT(10), BIT(10), BIT(6), true),
0927     [RK3366_PD_VIO]     = DOMAIN_RK3368("vio",    BIT(14), BIT(14), BIT(8), false),
0928     [RK3366_PD_VIDEO]   = DOMAIN_RK3368("video",  BIT(13), BIT(13), BIT(7), false),
0929     [RK3366_PD_RKVDEC]  = DOMAIN_RK3368("vdec",   BIT(11), BIT(11), BIT(7), false),
0930     [RK3366_PD_WIFIBT]  = DOMAIN_RK3368("wifibt", BIT(8),  BIT(8),  BIT(9), false),
0931     [RK3366_PD_VPU]     = DOMAIN_RK3368("vpu",    BIT(12), BIT(12), BIT(7), false),
0932     [RK3366_PD_GPU]     = DOMAIN_RK3368("gpu",    BIT(15), BIT(15), BIT(2), false),
0933 };
0934 
0935 static const struct rockchip_domain_info rk3368_pm_domains[] = {
0936     [RK3368_PD_PERI]    = DOMAIN_RK3368("peri",  BIT(13), BIT(12), BIT(6), true),
0937     [RK3368_PD_VIO]     = DOMAIN_RK3368("vio",   BIT(15), BIT(14), BIT(8), false),
0938     [RK3368_PD_VIDEO]   = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false),
0939     [RK3368_PD_GPU_0]   = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false),
0940     [RK3368_PD_GPU_1]   = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false),
0941 };
0942 
0943 static const struct rockchip_domain_info rk3399_pm_domains[] = {
0944     [RK3399_PD_TCPD0]   = DOMAIN_RK3399("tcpd0",     BIT(8),  BIT(8),  0,       false),
0945     [RK3399_PD_TCPD1]   = DOMAIN_RK3399("tcpd1",     BIT(9),  BIT(9),  0,       false),
0946     [RK3399_PD_CCI]     = DOMAIN_RK3399("cci",       BIT(10), BIT(10), 0,       true),
0947     [RK3399_PD_CCI0]    = DOMAIN_RK3399("cci0",      0,       0,       BIT(15), true),
0948     [RK3399_PD_CCI1]    = DOMAIN_RK3399("cci1",      0,       0,       BIT(16), true),
0949     [RK3399_PD_PERILP]  = DOMAIN_RK3399("perilp",    BIT(11), BIT(11), BIT(1),  true),
0950     [RK3399_PD_PERIHP]  = DOMAIN_RK3399("perihp",    BIT(12), BIT(12), BIT(2),  true),
0951     [RK3399_PD_CENTER]  = DOMAIN_RK3399("center",    BIT(13), BIT(13), BIT(14), true),
0952     [RK3399_PD_VIO]     = DOMAIN_RK3399("vio",       BIT(14), BIT(14), BIT(17), false),
0953     [RK3399_PD_GPU]     = DOMAIN_RK3399("gpu",       BIT(15), BIT(15), BIT(0),  false),
0954     [RK3399_PD_VCODEC]  = DOMAIN_RK3399("vcodec",    BIT(16), BIT(16), BIT(3),  false),
0955     [RK3399_PD_VDU]     = DOMAIN_RK3399("vdu",       BIT(17), BIT(17), BIT(4),  false),
0956     [RK3399_PD_RGA]     = DOMAIN_RK3399("rga",       BIT(18), BIT(18), BIT(5),  false),
0957     [RK3399_PD_IEP]     = DOMAIN_RK3399("iep",       BIT(19), BIT(19), BIT(6),  false),
0958     [RK3399_PD_VO]      = DOMAIN_RK3399("vo",        BIT(20), BIT(20), 0,       false),
0959     [RK3399_PD_VOPB]    = DOMAIN_RK3399("vopb",      0,       0,       BIT(7),  false),
0960     [RK3399_PD_VOPL]    = DOMAIN_RK3399("vopl",      0,       0,       BIT(8),  false),
0961     [RK3399_PD_ISP0]    = DOMAIN_RK3399("isp0",      BIT(22), BIT(22), BIT(9),  false),
0962     [RK3399_PD_ISP1]    = DOMAIN_RK3399("isp1",      BIT(23), BIT(23), BIT(10), false),
0963     [RK3399_PD_HDCP]    = DOMAIN_RK3399("hdcp",      BIT(24), BIT(24), BIT(11), false),
0964     [RK3399_PD_GMAC]    = DOMAIN_RK3399("gmac",      BIT(25), BIT(25), BIT(23), true),
0965     [RK3399_PD_EMMC]    = DOMAIN_RK3399("emmc",      BIT(26), BIT(26), BIT(24), true),
0966     [RK3399_PD_USB3]    = DOMAIN_RK3399("usb3",      BIT(27), BIT(27), BIT(12), true),
0967     [RK3399_PD_EDP]     = DOMAIN_RK3399("edp",       BIT(28), BIT(28), BIT(22), false),
0968     [RK3399_PD_GIC]     = DOMAIN_RK3399("gic",       BIT(29), BIT(29), BIT(27), true),
0969     [RK3399_PD_SD]      = DOMAIN_RK3399("sd",        BIT(30), BIT(30), BIT(28), true),
0970     [RK3399_PD_SDIOAUDIO]   = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true),
0971 };
0972 
0973 static const struct rockchip_domain_info rk3568_pm_domains[] = {
0974     [RK3568_PD_NPU]     = DOMAIN_RK3568("npu",  BIT(1), BIT(2),  false),
0975     [RK3568_PD_GPU]     = DOMAIN_RK3568("gpu",  BIT(0), BIT(1),  false),
0976     [RK3568_PD_VI]      = DOMAIN_RK3568("vi",   BIT(6), BIT(3),  false),
0977     [RK3568_PD_VO]      = DOMAIN_RK3568("vo",   BIT(7), BIT(4),  false),
0978     [RK3568_PD_RGA]     = DOMAIN_RK3568("rga",  BIT(5), BIT(5),  false),
0979     [RK3568_PD_VPU]     = DOMAIN_RK3568("vpu",  BIT(2), BIT(6),  false),
0980     [RK3568_PD_RKVDEC]  = DOMAIN_RK3568("vdec", BIT(4), BIT(8),  false),
0981     [RK3568_PD_RKVENC]  = DOMAIN_RK3568("venc", BIT(3), BIT(7),  false),
0982     [RK3568_PD_PIPE]    = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
0983 };
0984 
0985 static const struct rockchip_pmu_info px30_pmu = {
0986     .pwr_offset = 0x18,
0987     .status_offset = 0x20,
0988     .req_offset = 0x64,
0989     .idle_offset = 0x6c,
0990     .ack_offset = 0x6c,
0991 
0992     .num_domains = ARRAY_SIZE(px30_pm_domains),
0993     .domain_info = px30_pm_domains,
0994 };
0995 
0996 static const struct rockchip_pmu_info rk3036_pmu = {
0997     .req_offset = 0x148,
0998     .idle_offset = 0x14c,
0999     .ack_offset = 0x14c,
1000 
1001     .num_domains = ARRAY_SIZE(rk3036_pm_domains),
1002     .domain_info = rk3036_pm_domains,
1003 };
1004 
1005 static const struct rockchip_pmu_info rk3066_pmu = {
1006     .pwr_offset = 0x08,
1007     .status_offset = 0x0c,
1008     .req_offset = 0x38, /* PMU_MISC_CON1 */
1009     .idle_offset = 0x0c,
1010     .ack_offset = 0x0c,
1011 
1012     .num_domains = ARRAY_SIZE(rk3066_pm_domains),
1013     .domain_info = rk3066_pm_domains,
1014 };
1015 
1016 static const struct rockchip_pmu_info rk3128_pmu = {
1017     .pwr_offset = 0x04,
1018     .status_offset = 0x08,
1019     .req_offset = 0x0c,
1020     .idle_offset = 0x10,
1021     .ack_offset = 0x10,
1022 
1023     .num_domains = ARRAY_SIZE(rk3128_pm_domains),
1024     .domain_info = rk3128_pm_domains,
1025 };
1026 
1027 static const struct rockchip_pmu_info rk3188_pmu = {
1028     .pwr_offset = 0x08,
1029     .status_offset = 0x0c,
1030     .req_offset = 0x38, /* PMU_MISC_CON1 */
1031     .idle_offset = 0x0c,
1032     .ack_offset = 0x0c,
1033 
1034     .num_domains = ARRAY_SIZE(rk3188_pm_domains),
1035     .domain_info = rk3188_pm_domains,
1036 };
1037 
1038 static const struct rockchip_pmu_info rk3228_pmu = {
1039     .req_offset = 0x40c,
1040     .idle_offset = 0x488,
1041     .ack_offset = 0x488,
1042 
1043     .num_domains = ARRAY_SIZE(rk3228_pm_domains),
1044     .domain_info = rk3228_pm_domains,
1045 };
1046 
1047 static const struct rockchip_pmu_info rk3288_pmu = {
1048     .pwr_offset = 0x08,
1049     .status_offset = 0x0c,
1050     .req_offset = 0x10,
1051     .idle_offset = 0x14,
1052     .ack_offset = 0x14,
1053 
1054     .core_pwrcnt_offset = 0x34,
1055     .gpu_pwrcnt_offset = 0x3c,
1056 
1057     .core_power_transition_time = 24, /* 1us */
1058     .gpu_power_transition_time = 24, /* 1us */
1059 
1060     .num_domains = ARRAY_SIZE(rk3288_pm_domains),
1061     .domain_info = rk3288_pm_domains,
1062 };
1063 
1064 static const struct rockchip_pmu_info rk3328_pmu = {
1065     .req_offset = 0x414,
1066     .idle_offset = 0x484,
1067     .ack_offset = 0x484,
1068 
1069     .num_domains = ARRAY_SIZE(rk3328_pm_domains),
1070     .domain_info = rk3328_pm_domains,
1071 };
1072 
1073 static const struct rockchip_pmu_info rk3366_pmu = {
1074     .pwr_offset = 0x0c,
1075     .status_offset = 0x10,
1076     .req_offset = 0x3c,
1077     .idle_offset = 0x40,
1078     .ack_offset = 0x40,
1079 
1080     .core_pwrcnt_offset = 0x48,
1081     .gpu_pwrcnt_offset = 0x50,
1082 
1083     .core_power_transition_time = 24,
1084     .gpu_power_transition_time = 24,
1085 
1086     .num_domains = ARRAY_SIZE(rk3366_pm_domains),
1087     .domain_info = rk3366_pm_domains,
1088 };
1089 
1090 static const struct rockchip_pmu_info rk3368_pmu = {
1091     .pwr_offset = 0x0c,
1092     .status_offset = 0x10,
1093     .req_offset = 0x3c,
1094     .idle_offset = 0x40,
1095     .ack_offset = 0x40,
1096 
1097     .core_pwrcnt_offset = 0x48,
1098     .gpu_pwrcnt_offset = 0x50,
1099 
1100     .core_power_transition_time = 24,
1101     .gpu_power_transition_time = 24,
1102 
1103     .num_domains = ARRAY_SIZE(rk3368_pm_domains),
1104     .domain_info = rk3368_pm_domains,
1105 };
1106 
1107 static const struct rockchip_pmu_info rk3399_pmu = {
1108     .pwr_offset = 0x14,
1109     .status_offset = 0x18,
1110     .req_offset = 0x60,
1111     .idle_offset = 0x64,
1112     .ack_offset = 0x68,
1113 
1114     /* ARM Trusted Firmware manages power transition times */
1115 
1116     .num_domains = ARRAY_SIZE(rk3399_pm_domains),
1117     .domain_info = rk3399_pm_domains,
1118 };
1119 
1120 static const struct rockchip_pmu_info rk3568_pmu = {
1121     .pwr_offset = 0xa0,
1122     .status_offset = 0x98,
1123     .req_offset = 0x50,
1124     .idle_offset = 0x68,
1125     .ack_offset = 0x60,
1126 
1127     .num_domains = ARRAY_SIZE(rk3568_pm_domains),
1128     .domain_info = rk3568_pm_domains,
1129 };
1130 
1131 static const struct of_device_id rockchip_pm_domain_dt_match[] = {
1132     {
1133         .compatible = "rockchip,px30-power-controller",
1134         .data = (void *)&px30_pmu,
1135     },
1136     {
1137         .compatible = "rockchip,rk3036-power-controller",
1138         .data = (void *)&rk3036_pmu,
1139     },
1140     {
1141         .compatible = "rockchip,rk3066-power-controller",
1142         .data = (void *)&rk3066_pmu,
1143     },
1144     {
1145         .compatible = "rockchip,rk3128-power-controller",
1146         .data = (void *)&rk3128_pmu,
1147     },
1148     {
1149         .compatible = "rockchip,rk3188-power-controller",
1150         .data = (void *)&rk3188_pmu,
1151     },
1152     {
1153         .compatible = "rockchip,rk3228-power-controller",
1154         .data = (void *)&rk3228_pmu,
1155     },
1156     {
1157         .compatible = "rockchip,rk3288-power-controller",
1158         .data = (void *)&rk3288_pmu,
1159     },
1160     {
1161         .compatible = "rockchip,rk3328-power-controller",
1162         .data = (void *)&rk3328_pmu,
1163     },
1164     {
1165         .compatible = "rockchip,rk3366-power-controller",
1166         .data = (void *)&rk3366_pmu,
1167     },
1168     {
1169         .compatible = "rockchip,rk3368-power-controller",
1170         .data = (void *)&rk3368_pmu,
1171     },
1172     {
1173         .compatible = "rockchip,rk3399-power-controller",
1174         .data = (void *)&rk3399_pmu,
1175     },
1176     {
1177         .compatible = "rockchip,rk3568-power-controller",
1178         .data = (void *)&rk3568_pmu,
1179     },
1180     { /* sentinel */ },
1181 };
1182 
1183 static struct platform_driver rockchip_pm_domain_driver = {
1184     .probe = rockchip_pm_domain_probe,
1185     .driver = {
1186         .name   = "rockchip-pm-domain",
1187         .of_match_table = rockchip_pm_domain_dt_match,
1188         /*
1189          * We can't forcibly eject devices from the power
1190          * domain, so we can't really remove power domains
1191          * once they were added.
1192          */
1193         .suppress_bind_attrs = true,
1194     },
1195 };
1196 
1197 static int __init rockchip_pm_domain_drv_register(void)
1198 {
1199     return platform_driver_register(&rockchip_pm_domain_driver);
1200 }
1201 postcore_initcall(rockchip_pm_domain_drv_register);