0001
0002
0003
0004
0005
0006
0007 #include <linux/of_address.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/pm_domain.h>
0010 #include <linux/bitfield.h>
0011 #include <linux/regmap.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/of_device.h>
0014 #include <linux/reset-controller.h>
0015 #include <linux/reset.h>
0016 #include <linux/clk.h>
0017 #include <linux/module.h>
0018 #include <dt-bindings/power/meson8-power.h>
0019 #include <dt-bindings/power/meson-axg-power.h>
0020 #include <dt-bindings/power/meson-g12a-power.h>
0021 #include <dt-bindings/power/meson-gxbb-power.h>
0022 #include <dt-bindings/power/meson-sm1-power.h>
0023
0024
0025
0026 #define GX_AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2)
0027 #define GX_AO_RTI_GEN_PWR_ISO0 (0x3b << 2)
0028
0029
0030
0031
0032
0033
0034 #define MESON8_AO_RTI_GEN_PWR_SLEEP0 (0x02 << 2)
0035 #define MESON8_AO_RTI_GEN_PWR_ISO0 (0x03 << 2)
0036
0037
0038
0039 #define HHI_MEM_PD_REG0 (0x40 << 2)
0040 #define HHI_VPU_MEM_PD_REG0 (0x41 << 2)
0041 #define HHI_VPU_MEM_PD_REG1 (0x42 << 2)
0042 #define HHI_VPU_MEM_PD_REG3 (0x43 << 2)
0043 #define HHI_VPU_MEM_PD_REG4 (0x44 << 2)
0044 #define HHI_AUDIO_MEM_PD_REG0 (0x45 << 2)
0045 #define HHI_NANOQ_MEM_PD_REG0 (0x46 << 2)
0046 #define HHI_NANOQ_MEM_PD_REG1 (0x47 << 2)
0047 #define HHI_VPU_MEM_PD_REG2 (0x4d << 2)
0048
0049 struct meson_ee_pwrc;
0050 struct meson_ee_pwrc_domain;
0051
0052 struct meson_ee_pwrc_mem_domain {
0053 unsigned int reg;
0054 unsigned int mask;
0055 };
0056
0057 struct meson_ee_pwrc_top_domain {
0058 unsigned int sleep_reg;
0059 unsigned int sleep_mask;
0060 unsigned int iso_reg;
0061 unsigned int iso_mask;
0062 };
0063
0064 struct meson_ee_pwrc_domain_desc {
0065 char *name;
0066 unsigned int reset_names_count;
0067 unsigned int clk_names_count;
0068 struct meson_ee_pwrc_top_domain *top_pd;
0069 unsigned int mem_pd_count;
0070 struct meson_ee_pwrc_mem_domain *mem_pd;
0071 bool (*is_powered_off)(struct meson_ee_pwrc_domain *pwrc_domain);
0072 };
0073
0074 struct meson_ee_pwrc_domain_data {
0075 unsigned int count;
0076 struct meson_ee_pwrc_domain_desc *domains;
0077 };
0078
0079
0080
0081 static struct meson_ee_pwrc_top_domain gx_pwrc_vpu = {
0082 .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
0083 .sleep_mask = BIT(8),
0084 .iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
0085 .iso_mask = BIT(9),
0086 };
0087
0088 static struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = {
0089 .sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
0090 .sleep_mask = BIT(8),
0091 .iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
0092 .iso_mask = BIT(9),
0093 };
0094
0095 #define SM1_EE_PD(__bit) \
0096 { \
0097 .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, \
0098 .sleep_mask = BIT(__bit), \
0099 .iso_reg = GX_AO_RTI_GEN_PWR_ISO0, \
0100 .iso_mask = BIT(__bit), \
0101 }
0102
0103 static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
0104 static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
0105 static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
0106 static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
0107 static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
0108
0109
0110
0111 #define VPU_MEMPD(__reg) \
0112 { __reg, GENMASK(1, 0) }, \
0113 { __reg, GENMASK(3, 2) }, \
0114 { __reg, GENMASK(5, 4) }, \
0115 { __reg, GENMASK(7, 6) }, \
0116 { __reg, GENMASK(9, 8) }, \
0117 { __reg, GENMASK(11, 10) }, \
0118 { __reg, GENMASK(13, 12) }, \
0119 { __reg, GENMASK(15, 14) }, \
0120 { __reg, GENMASK(17, 16) }, \
0121 { __reg, GENMASK(19, 18) }, \
0122 { __reg, GENMASK(21, 20) }, \
0123 { __reg, GENMASK(23, 22) }, \
0124 { __reg, GENMASK(25, 24) }, \
0125 { __reg, GENMASK(27, 26) }, \
0126 { __reg, GENMASK(29, 28) }, \
0127 { __reg, GENMASK(31, 30) }
0128
0129 #define VPU_HHI_MEMPD(__reg) \
0130 { __reg, BIT(8) }, \
0131 { __reg, BIT(9) }, \
0132 { __reg, BIT(10) }, \
0133 { __reg, BIT(11) }, \
0134 { __reg, BIT(12) }, \
0135 { __reg, BIT(13) }, \
0136 { __reg, BIT(14) }, \
0137 { __reg, BIT(15) }
0138
0139 static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = {
0140 VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
0141 VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
0142 };
0143
0144 static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
0145 VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
0146 VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
0147 VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
0148 VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
0149 };
0150
0151 static struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = {
0152 VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
0153 VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
0154 VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
0155 };
0156
0157 static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
0158 { HHI_MEM_PD_REG0, GENMASK(3, 2) },
0159 };
0160
0161 static struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = {
0162 { HHI_MEM_PD_REG0, GENMASK(1, 0) },
0163 };
0164
0165 static struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = {
0166 VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
0167 VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
0168 VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
0169 };
0170
0171 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
0172 VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
0173 VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
0174 VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
0175 VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
0176 { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
0177 { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
0178 { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
0179 { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
0180 VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
0181 };
0182
0183 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
0184 { HHI_NANOQ_MEM_PD_REG0, 0xff },
0185 { HHI_NANOQ_MEM_PD_REG1, 0xff },
0186 };
0187
0188 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
0189 { HHI_MEM_PD_REG0, GENMASK(31, 30) },
0190 };
0191
0192 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
0193 { HHI_MEM_PD_REG0, GENMASK(29, 26) },
0194 };
0195
0196 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
0197 { HHI_MEM_PD_REG0, GENMASK(25, 18) },
0198 };
0199
0200 static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = {
0201 { HHI_MEM_PD_REG0, GENMASK(5, 4) },
0202 };
0203
0204 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
0205 { HHI_MEM_PD_REG0, GENMASK(5, 4) },
0206 { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
0207 { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
0208 { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
0209 { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
0210 { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
0211 { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
0212 { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
0213 { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
0214 { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
0215 { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
0216 { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
0217 { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
0218 };
0219
0220 #define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks) \
0221 { \
0222 .name = __name, \
0223 .reset_names_count = __resets, \
0224 .clk_names_count = __clks, \
0225 .top_pd = __top_pd, \
0226 .mem_pd_count = ARRAY_SIZE(__mem), \
0227 .mem_pd = __mem, \
0228 .is_powered_off = __is_pwr_off, \
0229 }
0230
0231 #define TOP_PD(__name, __top_pd, __mem, __is_pwr_off) \
0232 { \
0233 .name = __name, \
0234 .top_pd = __top_pd, \
0235 .mem_pd_count = ARRAY_SIZE(__mem), \
0236 .mem_pd = __mem, \
0237 .is_powered_off = __is_pwr_off, \
0238 }
0239
0240 #define MEM_PD(__name, __mem) \
0241 TOP_PD(__name, NULL, __mem, NULL)
0242
0243 static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain);
0244
0245 static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = {
0246 [PWRC_AXG_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu,
0247 pwrc_ee_is_powered_off, 5, 2),
0248 [PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
0249 [PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio),
0250 };
0251
0252 static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
0253 [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
0254 pwrc_ee_is_powered_off, 11, 2),
0255 [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
0256 };
0257
0258 static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
0259 [PWRC_GXBB_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu,
0260 pwrc_ee_is_powered_off, 12, 2),
0261 [PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
0262 };
0263
0264 static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
0265 [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu,
0266 meson8_pwrc_mem_vpu,
0267 pwrc_ee_is_powered_off, 0, 1),
0268 [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
0269 meson_pwrc_mem_eth),
0270 [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
0271 meson8_pwrc_audio_dsp_mem),
0272 };
0273
0274 static struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = {
0275 [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu,
0276 meson8_pwrc_mem_vpu,
0277 pwrc_ee_is_powered_off, 11, 1),
0278 [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
0279 meson_pwrc_mem_eth),
0280 [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
0281 meson8_pwrc_audio_dsp_mem),
0282 };
0283
0284 static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
0285 [PWRC_SM1_VPU_ID] = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
0286 pwrc_ee_is_powered_off, 11, 2),
0287 [PWRC_SM1_NNA_ID] = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
0288 pwrc_ee_is_powered_off),
0289 [PWRC_SM1_USB_ID] = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
0290 pwrc_ee_is_powered_off),
0291 [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
0292 pwrc_ee_is_powered_off),
0293 [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
0294 pwrc_ee_is_powered_off),
0295 [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
0296 [PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
0297 };
0298
0299 struct meson_ee_pwrc_domain {
0300 struct generic_pm_domain base;
0301 bool enabled;
0302 struct meson_ee_pwrc *pwrc;
0303 struct meson_ee_pwrc_domain_desc desc;
0304 struct clk_bulk_data *clks;
0305 int num_clks;
0306 struct reset_control *rstc;
0307 int num_rstc;
0308 };
0309
0310 struct meson_ee_pwrc {
0311 struct regmap *regmap_ao;
0312 struct regmap *regmap_hhi;
0313 struct meson_ee_pwrc_domain *domains;
0314 struct genpd_onecell_data xlate;
0315 };
0316
0317 static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain)
0318 {
0319 u32 reg;
0320
0321 regmap_read(pwrc_domain->pwrc->regmap_ao,
0322 pwrc_domain->desc.top_pd->sleep_reg, ®);
0323
0324 return (reg & pwrc_domain->desc.top_pd->sleep_mask);
0325 }
0326
0327 static int meson_ee_pwrc_off(struct generic_pm_domain *domain)
0328 {
0329 struct meson_ee_pwrc_domain *pwrc_domain =
0330 container_of(domain, struct meson_ee_pwrc_domain, base);
0331 int i;
0332
0333 if (pwrc_domain->desc.top_pd)
0334 regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
0335 pwrc_domain->desc.top_pd->sleep_reg,
0336 pwrc_domain->desc.top_pd->sleep_mask,
0337 pwrc_domain->desc.top_pd->sleep_mask);
0338 udelay(20);
0339
0340 for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
0341 regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
0342 pwrc_domain->desc.mem_pd[i].reg,
0343 pwrc_domain->desc.mem_pd[i].mask,
0344 pwrc_domain->desc.mem_pd[i].mask);
0345
0346 udelay(20);
0347
0348 if (pwrc_domain->desc.top_pd)
0349 regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
0350 pwrc_domain->desc.top_pd->iso_reg,
0351 pwrc_domain->desc.top_pd->iso_mask,
0352 pwrc_domain->desc.top_pd->iso_mask);
0353
0354 if (pwrc_domain->num_clks) {
0355 msleep(20);
0356 clk_bulk_disable_unprepare(pwrc_domain->num_clks,
0357 pwrc_domain->clks);
0358 }
0359
0360 return 0;
0361 }
0362
0363 static int meson_ee_pwrc_on(struct generic_pm_domain *domain)
0364 {
0365 struct meson_ee_pwrc_domain *pwrc_domain =
0366 container_of(domain, struct meson_ee_pwrc_domain, base);
0367 int i, ret;
0368
0369 if (pwrc_domain->desc.top_pd)
0370 regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
0371 pwrc_domain->desc.top_pd->sleep_reg,
0372 pwrc_domain->desc.top_pd->sleep_mask, 0);
0373 udelay(20);
0374
0375 for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
0376 regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
0377 pwrc_domain->desc.mem_pd[i].reg,
0378 pwrc_domain->desc.mem_pd[i].mask, 0);
0379
0380 udelay(20);
0381
0382 ret = reset_control_assert(pwrc_domain->rstc);
0383 if (ret)
0384 return ret;
0385
0386 if (pwrc_domain->desc.top_pd)
0387 regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
0388 pwrc_domain->desc.top_pd->iso_reg,
0389 pwrc_domain->desc.top_pd->iso_mask, 0);
0390
0391 ret = reset_control_deassert(pwrc_domain->rstc);
0392 if (ret)
0393 return ret;
0394
0395 return clk_bulk_prepare_enable(pwrc_domain->num_clks,
0396 pwrc_domain->clks);
0397 }
0398
0399 static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
0400 struct meson_ee_pwrc *pwrc,
0401 struct meson_ee_pwrc_domain *dom)
0402 {
0403 int ret;
0404
0405 dom->pwrc = pwrc;
0406 dom->num_rstc = dom->desc.reset_names_count;
0407 dom->num_clks = dom->desc.clk_names_count;
0408
0409 if (dom->num_rstc) {
0410 int count = reset_control_get_count(&pdev->dev);
0411
0412 if (count != dom->num_rstc)
0413 dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n",
0414 count, dom->desc.name);
0415
0416 dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
0417 if (IS_ERR(dom->rstc))
0418 return PTR_ERR(dom->rstc);
0419 }
0420
0421 if (dom->num_clks) {
0422 int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks);
0423 if (ret < 0)
0424 return ret;
0425
0426 if (dom->num_clks != ret) {
0427 dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n",
0428 ret, dom->desc.name);
0429 dom->num_clks = ret;
0430 }
0431 }
0432
0433 dom->base.name = dom->desc.name;
0434 dom->base.power_on = meson_ee_pwrc_on;
0435 dom->base.power_off = meson_ee_pwrc_off;
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 if (dom->num_clks && dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) {
0449 ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
0450 if (ret)
0451 return ret;
0452
0453 dom->base.flags = GENPD_FLAG_ALWAYS_ON;
0454 ret = pm_genpd_init(&dom->base, NULL, false);
0455 if (ret)
0456 return ret;
0457 } else {
0458 ret = pm_genpd_init(&dom->base, NULL,
0459 (dom->desc.is_powered_off ?
0460 dom->desc.is_powered_off(dom) : true));
0461 if (ret)
0462 return ret;
0463 }
0464
0465 return 0;
0466 }
0467
0468 static int meson_ee_pwrc_probe(struct platform_device *pdev)
0469 {
0470 const struct meson_ee_pwrc_domain_data *match;
0471 struct regmap *regmap_ao, *regmap_hhi;
0472 struct meson_ee_pwrc *pwrc;
0473 int i, ret;
0474
0475 match = of_device_get_match_data(&pdev->dev);
0476 if (!match) {
0477 dev_err(&pdev->dev, "failed to get match data\n");
0478 return -ENODEV;
0479 }
0480
0481 pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
0482 if (!pwrc)
0483 return -ENOMEM;
0484
0485 pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
0486 sizeof(*pwrc->xlate.domains),
0487 GFP_KERNEL);
0488 if (!pwrc->xlate.domains)
0489 return -ENOMEM;
0490
0491 pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
0492 sizeof(*pwrc->domains), GFP_KERNEL);
0493 if (!pwrc->domains)
0494 return -ENOMEM;
0495
0496 pwrc->xlate.num_domains = match->count;
0497
0498 regmap_hhi = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
0499 if (IS_ERR(regmap_hhi)) {
0500 dev_err(&pdev->dev, "failed to get HHI regmap\n");
0501 return PTR_ERR(regmap_hhi);
0502 }
0503
0504 regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
0505 "amlogic,ao-sysctrl");
0506 if (IS_ERR(regmap_ao)) {
0507 dev_err(&pdev->dev, "failed to get AO regmap\n");
0508 return PTR_ERR(regmap_ao);
0509 }
0510
0511 pwrc->regmap_ao = regmap_ao;
0512 pwrc->regmap_hhi = regmap_hhi;
0513
0514 platform_set_drvdata(pdev, pwrc);
0515
0516 for (i = 0 ; i < match->count ; ++i) {
0517 struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
0518
0519 memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc));
0520
0521 ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom);
0522 if (ret)
0523 return ret;
0524
0525 pwrc->xlate.domains[i] = &dom->base;
0526 }
0527
0528 return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
0529 }
0530
0531 static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
0532 {
0533 struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev);
0534 int i;
0535
0536 for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
0537 struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
0538
0539 if (dom->desc.is_powered_off && !dom->desc.is_powered_off(dom))
0540 meson_ee_pwrc_off(&dom->base);
0541 }
0542 }
0543
0544 static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
0545 .count = ARRAY_SIZE(g12a_pwrc_domains),
0546 .domains = g12a_pwrc_domains,
0547 };
0548
0549 static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = {
0550 .count = ARRAY_SIZE(axg_pwrc_domains),
0551 .domains = axg_pwrc_domains,
0552 };
0553
0554 static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
0555 .count = ARRAY_SIZE(gxbb_pwrc_domains),
0556 .domains = gxbb_pwrc_domains,
0557 };
0558
0559 static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
0560 .count = ARRAY_SIZE(meson8_pwrc_domains),
0561 .domains = meson8_pwrc_domains,
0562 };
0563
0564 static struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = {
0565 .count = ARRAY_SIZE(meson8b_pwrc_domains),
0566 .domains = meson8b_pwrc_domains,
0567 };
0568
0569 static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
0570 .count = ARRAY_SIZE(sm1_pwrc_domains),
0571 .domains = sm1_pwrc_domains,
0572 };
0573
0574 static const struct of_device_id meson_ee_pwrc_match_table[] = {
0575 {
0576 .compatible = "amlogic,meson8-pwrc",
0577 .data = &meson_ee_m8_pwrc_data,
0578 },
0579 {
0580 .compatible = "amlogic,meson8b-pwrc",
0581 .data = &meson_ee_m8b_pwrc_data,
0582 },
0583 {
0584 .compatible = "amlogic,meson8m2-pwrc",
0585 .data = &meson_ee_m8b_pwrc_data,
0586 },
0587 {
0588 .compatible = "amlogic,meson-axg-pwrc",
0589 .data = &meson_ee_axg_pwrc_data,
0590 },
0591 {
0592 .compatible = "amlogic,meson-gxbb-pwrc",
0593 .data = &meson_ee_gxbb_pwrc_data,
0594 },
0595 {
0596 .compatible = "amlogic,meson-g12a-pwrc",
0597 .data = &meson_ee_g12a_pwrc_data,
0598 },
0599 {
0600 .compatible = "amlogic,meson-sm1-pwrc",
0601 .data = &meson_ee_sm1_pwrc_data,
0602 },
0603 { }
0604 };
0605 MODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table);
0606
0607 static struct platform_driver meson_ee_pwrc_driver = {
0608 .probe = meson_ee_pwrc_probe,
0609 .shutdown = meson_ee_pwrc_shutdown,
0610 .driver = {
0611 .name = "meson_ee_pwrc",
0612 .of_match_table = meson_ee_pwrc_match_table,
0613 },
0614 };
0615 module_platform_driver(meson_ee_pwrc_driver);
0616 MODULE_LICENSE("GPL v2");