1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2020 Collabora Ltd. 4 */ 5 #include <linux/clk.h> 6 #include <linux/clk-provider.h> 7 #include <linux/init.h> 8 #include <linux/io.h> 9 #include <linux/iopoll.h> 10 #include <linux/mfd/syscon.h> 11 #include <linux/of.h> 12 #include <linux/of_clk.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_domain.h> 15 #include <linux/regmap.h> 16 #include <linux/regulator/consumer.h> 17 #include <linux/soc/mediatek/infracfg.h> 18 19 #include "mt6795-pm-domains.h" 20 #include "mt8167-pm-domains.h" 21 #include "mt8173-pm-domains.h" 22 #include "mt8183-pm-domains.h" 23 #include "mt8186-pm-domains.h" 24 #include "mt8188-pm-domains.h" 25 #include "mt8192-pm-domains.h" 26 #include "mt8195-pm-domains.h" 27 #include "mt8365-pm-domains.h" 28 29 #define MTK_POLL_DELAY_US 10 30 #define MTK_POLL_TIMEOUT USEC_PER_SEC 31 32 #define PWR_RST_B_BIT BIT(0) 33 #define PWR_ISO_BIT BIT(1) 34 #define PWR_ON_BIT BIT(2) 35 #define PWR_ON_2ND_BIT BIT(3) 36 #define PWR_CLK_DIS_BIT BIT(4) 37 #define PWR_SRAM_CLKISO_BIT BIT(5) 38 #define PWR_SRAM_ISOINT_B_BIT BIT(6) 39 40 struct scpsys_domain { 41 struct generic_pm_domain genpd; 42 const struct scpsys_domain_data *data; 43 struct scpsys *scpsys; 44 int num_clks; 45 struct clk_bulk_data *clks; 46 int num_subsys_clks; 47 struct clk_bulk_data *subsys_clks; 48 struct regmap *infracfg_nao; 49 struct regmap *infracfg; 50 struct regmap *smi; 51 struct regulator *supply; 52 }; 53 54 struct scpsys { 55 struct device *dev; 56 struct regmap *base; 57 const struct scpsys_soc_data *soc_data; 58 struct genpd_onecell_data pd_data; 59 struct generic_pm_domain *domains[]; 60 }; 61 62 #define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd) 63 64 static bool scpsys_domain_is_on(struct scpsys_domain *pd) 65 { 66 struct scpsys *scpsys = pd->scpsys; 67 u32 status, status2; 68 69 regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status); 70 status &= pd->data->sta_mask; 71 72 regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2); 73 status2 &= pd->data->sta_mask; 74 75 /* A domain is on when both status bits are set. */ 76 return status && status2; 77 } 78 79 static int scpsys_sram_enable(struct scpsys_domain *pd) 80 { 81 u32 pdn_ack = pd->data->sram_pdn_ack_bits; 82 struct scpsys *scpsys = pd->scpsys; 83 unsigned int tmp; 84 int ret; 85 86 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); 87 88 /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 89 ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, 90 (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 91 if (ret < 0) 92 return ret; 93 94 if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) { 95 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); 96 udelay(1); 97 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); 98 } 99 100 return 0; 101 } 102 103 static int scpsys_sram_disable(struct scpsys_domain *pd) 104 { 105 u32 pdn_ack = pd->data->sram_pdn_ack_bits; 106 struct scpsys *scpsys = pd->scpsys; 107 unsigned int tmp; 108 109 if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) { 110 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); 111 udelay(1); 112 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); 113 } 114 115 regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); 116 117 /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 118 return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, 119 (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US, 120 MTK_POLL_TIMEOUT); 121 } 122 123 static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd, 124 const struct scpsys_bus_prot_data *bpd) 125 { 126 if (bpd->flags & BUS_PROT_COMPONENT_SMI) 127 return pd->smi; 128 else 129 return pd->infracfg; 130 } 131 132 static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd, 133 const struct scpsys_bus_prot_data *bpd) 134 { 135 if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO) 136 return pd->infracfg_nao; 137 else 138 return scpsys_bus_protect_get_regmap(pd, bpd); 139 } 140 141 static int scpsys_bus_protect_clear(struct scpsys_domain *pd, 142 const struct scpsys_bus_prot_data *bpd) 143 { 144 struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd); 145 struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd); 146 u32 sta_mask = bpd->bus_prot_sta_mask; 147 u32 expected_ack; 148 u32 val; 149 150 expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0); 151 152 if (bpd->flags & BUS_PROT_REG_UPDATE) 153 regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask); 154 else 155 regmap_write(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask); 156 157 if (bpd->flags & BUS_PROT_IGNORE_CLR_ACK) 158 return 0; 159 160 return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta, 161 val, (val & sta_mask) == expected_ack, 162 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 163 } 164 165 static int scpsys_bus_protect_set(struct scpsys_domain *pd, 166 const struct scpsys_bus_prot_data *bpd) 167 { 168 struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd); 169 struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd); 170 u32 sta_mask = bpd->bus_prot_sta_mask; 171 u32 val; 172 173 if (bpd->flags & BUS_PROT_REG_UPDATE) 174 regmap_set_bits(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask); 175 else 176 regmap_write(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask); 177 178 return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta, 179 val, (val & sta_mask) == sta_mask, 180 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 181 } 182 183 static int scpsys_bus_protect_enable(struct scpsys_domain *pd) 184 { 185 for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) { 186 const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i]; 187 int ret; 188 189 if (!bpd->bus_prot_set_clr_mask) 190 break; 191 192 if (bpd->flags & BUS_PROT_INVERTED) 193 ret = scpsys_bus_protect_clear(pd, bpd); 194 else 195 ret = scpsys_bus_protect_set(pd, bpd); 196 if (ret) 197 return ret; 198 } 199 200 return 0; 201 } 202 203 static int scpsys_bus_protect_disable(struct scpsys_domain *pd) 204 { 205 for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) { 206 const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i]; 207 int ret; 208 209 if (!bpd->bus_prot_set_clr_mask) 210 continue; 211 212 if (bpd->flags & BUS_PROT_INVERTED) 213 ret = scpsys_bus_protect_set(pd, bpd); 214 else 215 ret = scpsys_bus_protect_clear(pd, bpd); 216 if (ret) 217 return ret; 218 } 219 220 return 0; 221 } 222 223 static int scpsys_regulator_enable(struct regulator *supply) 224 { 225 return supply ? regulator_enable(supply) : 0; 226 } 227 228 static int scpsys_regulator_disable(struct regulator *supply) 229 { 230 return supply ? regulator_disable(supply) : 0; 231 } 232 233 static int scpsys_power_on(struct generic_pm_domain *genpd) 234 { 235 struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); 236 struct scpsys *scpsys = pd->scpsys; 237 bool tmp; 238 int ret; 239 240 ret = scpsys_regulator_enable(pd->supply); 241 if (ret) 242 return ret; 243 244 ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); 245 if (ret) 246 goto err_reg; 247 248 if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) 249 regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs, 250 pd->data->ext_buck_iso_mask); 251 252 /* subsys power on */ 253 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); 254 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); 255 256 /* wait until PWR_ACK = 1 */ 257 ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US, 258 MTK_POLL_TIMEOUT); 259 if (ret < 0) 260 goto err_pwr_ack; 261 262 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); 263 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); 264 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); 265 266 /* 267 * In few Mediatek platforms(e.g. MT6779), the bus protect policy is 268 * stricter, which leads to bus protect release must be prior to bus 269 * access. 270 */ 271 if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) { 272 ret = clk_bulk_prepare_enable(pd->num_subsys_clks, 273 pd->subsys_clks); 274 if (ret) 275 goto err_pwr_ack; 276 } 277 278 ret = scpsys_sram_enable(pd); 279 if (ret < 0) 280 goto err_disable_subsys_clks; 281 282 ret = scpsys_bus_protect_disable(pd); 283 if (ret < 0) 284 goto err_disable_sram; 285 286 if (MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) { 287 ret = clk_bulk_prepare_enable(pd->num_subsys_clks, 288 pd->subsys_clks); 289 if (ret) 290 goto err_enable_bus_protect; 291 } 292 293 return 0; 294 295 err_enable_bus_protect: 296 scpsys_bus_protect_enable(pd); 297 err_disable_sram: 298 scpsys_sram_disable(pd); 299 err_disable_subsys_clks: 300 if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) 301 clk_bulk_disable_unprepare(pd->num_subsys_clks, 302 pd->subsys_clks); 303 err_pwr_ack: 304 clk_bulk_disable_unprepare(pd->num_clks, pd->clks); 305 err_reg: 306 scpsys_regulator_disable(pd->supply); 307 return ret; 308 } 309 310 static int scpsys_power_off(struct generic_pm_domain *genpd) 311 { 312 struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); 313 struct scpsys *scpsys = pd->scpsys; 314 bool tmp; 315 int ret; 316 317 ret = scpsys_bus_protect_enable(pd); 318 if (ret < 0) 319 return ret; 320 321 ret = scpsys_sram_disable(pd); 322 if (ret < 0) 323 return ret; 324 325 if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) 326 regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs, 327 pd->data->ext_buck_iso_mask); 328 329 clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); 330 331 /* subsys power off */ 332 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); 333 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); 334 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); 335 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); 336 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); 337 338 /* wait until PWR_ACK = 0 */ 339 ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US, 340 MTK_POLL_TIMEOUT); 341 if (ret < 0) 342 return ret; 343 344 clk_bulk_disable_unprepare(pd->num_clks, pd->clks); 345 346 scpsys_regulator_disable(pd->supply); 347 348 return 0; 349 } 350 351 static struct 352 generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node) 353 { 354 const struct scpsys_domain_data *domain_data; 355 struct scpsys_domain *pd; 356 struct device_node *root_node = scpsys->dev->of_node; 357 struct device_node *smi_node; 358 struct property *prop; 359 const char *clk_name; 360 int i, ret, num_clks; 361 struct clk *clk; 362 int clk_ind = 0; 363 u32 id; 364 365 ret = of_property_read_u32(node, "reg", &id); 366 if (ret) { 367 dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n", 368 node, ret); 369 return ERR_PTR(-EINVAL); 370 } 371 372 if (id >= scpsys->soc_data->num_domains) { 373 dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id); 374 return ERR_PTR(-EINVAL); 375 } 376 377 domain_data = &scpsys->soc_data->domains_data[id]; 378 if (domain_data->sta_mask == 0) { 379 dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id); 380 return ERR_PTR(-EINVAL); 381 } 382 383 pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL); 384 if (!pd) 385 return ERR_PTR(-ENOMEM); 386 387 pd->data = domain_data; 388 pd->scpsys = scpsys; 389 390 if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) { 391 /* 392 * Find regulator in current power domain node. 393 * devm_regulator_get() finds regulator in a node and its child 394 * node, so set of_node to current power domain node then change 395 * back to original node after regulator is found for current 396 * power domain node. 397 */ 398 scpsys->dev->of_node = node; 399 pd->supply = devm_regulator_get(scpsys->dev, "domain"); 400 scpsys->dev->of_node = root_node; 401 if (IS_ERR(pd->supply)) { 402 dev_err_probe(scpsys->dev, PTR_ERR(pd->supply), 403 "%pOF: failed to get power supply.\n", 404 node); 405 return ERR_CAST(pd->supply); 406 } 407 } 408 409 pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); 410 if (IS_ERR(pd->infracfg)) 411 return ERR_CAST(pd->infracfg); 412 413 smi_node = of_parse_phandle(node, "mediatek,smi", 0); 414 if (smi_node) { 415 pd->smi = device_node_to_regmap(smi_node); 416 of_node_put(smi_node); 417 if (IS_ERR(pd->smi)) 418 return ERR_CAST(pd->smi); 419 } 420 421 if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) { 422 pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao"); 423 if (IS_ERR(pd->infracfg_nao)) 424 return ERR_CAST(pd->infracfg_nao); 425 } else { 426 pd->infracfg_nao = NULL; 427 } 428 429 num_clks = of_clk_get_parent_count(node); 430 if (num_clks > 0) { 431 /* Calculate number of subsys_clks */ 432 of_property_for_each_string(node, "clock-names", prop, clk_name) { 433 char *subsys; 434 435 subsys = strchr(clk_name, '-'); 436 if (subsys) 437 pd->num_subsys_clks++; 438 else 439 pd->num_clks++; 440 } 441 442 pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL); 443 if (!pd->clks) 444 return ERR_PTR(-ENOMEM); 445 446 pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks, 447 sizeof(*pd->subsys_clks), GFP_KERNEL); 448 if (!pd->subsys_clks) 449 return ERR_PTR(-ENOMEM); 450 451 } 452 453 for (i = 0; i < pd->num_clks; i++) { 454 clk = of_clk_get(node, i); 455 if (IS_ERR(clk)) { 456 ret = PTR_ERR(clk); 457 dev_err_probe(scpsys->dev, ret, 458 "%pOF: failed to get clk at index %d\n", node, i); 459 goto err_put_clocks; 460 } 461 462 pd->clks[clk_ind++].clk = clk; 463 } 464 465 for (i = 0; i < pd->num_subsys_clks; i++) { 466 clk = of_clk_get(node, i + clk_ind); 467 if (IS_ERR(clk)) { 468 ret = PTR_ERR(clk); 469 dev_err_probe(scpsys->dev, ret, 470 "%pOF: failed to get clk at index %d\n", node, 471 i + clk_ind); 472 goto err_put_subsys_clocks; 473 } 474 475 pd->subsys_clks[i].clk = clk; 476 } 477 478 /* 479 * Initially turn on all domains to make the domains usable 480 * with !CONFIG_PM and to get the hardware in sync with the 481 * software. The unused domains will be switched off during 482 * late_init time. 483 */ 484 if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) { 485 if (scpsys_domain_is_on(pd)) 486 dev_warn(scpsys->dev, 487 "%pOF: A default off power domain has been ON\n", node); 488 } else { 489 ret = scpsys_power_on(&pd->genpd); 490 if (ret < 0) { 491 dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret); 492 goto err_put_subsys_clocks; 493 } 494 495 if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON)) 496 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; 497 } 498 499 if (scpsys->domains[id]) { 500 ret = -EINVAL; 501 dev_err(scpsys->dev, 502 "power domain with id %d already exists, check your device-tree\n", id); 503 goto err_put_subsys_clocks; 504 } 505 506 if (!pd->data->name) 507 pd->genpd.name = node->name; 508 else 509 pd->genpd.name = pd->data->name; 510 511 pd->genpd.power_off = scpsys_power_off; 512 pd->genpd.power_on = scpsys_power_on; 513 514 if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP)) 515 pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; 516 517 if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) 518 pm_genpd_init(&pd->genpd, NULL, true); 519 else 520 pm_genpd_init(&pd->genpd, NULL, false); 521 522 scpsys->domains[id] = &pd->genpd; 523 524 return scpsys->pd_data.domains[id]; 525 526 err_put_subsys_clocks: 527 clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); 528 err_put_clocks: 529 clk_bulk_put(pd->num_clks, pd->clks); 530 return ERR_PTR(ret); 531 } 532 533 static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent) 534 { 535 struct generic_pm_domain *child_pd, *parent_pd; 536 struct device_node *child; 537 int ret; 538 539 for_each_child_of_node(parent, child) { 540 u32 id; 541 542 ret = of_property_read_u32(parent, "reg", &id); 543 if (ret) { 544 dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child); 545 goto err_put_node; 546 } 547 548 if (!scpsys->pd_data.domains[id]) { 549 ret = -EINVAL; 550 dev_err(scpsys->dev, "power domain with id %d does not exist\n", id); 551 goto err_put_node; 552 } 553 554 parent_pd = scpsys->pd_data.domains[id]; 555 556 child_pd = scpsys_add_one_domain(scpsys, child); 557 if (IS_ERR(child_pd)) { 558 ret = PTR_ERR(child_pd); 559 dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n", 560 child); 561 goto err_put_node; 562 } 563 564 ret = pm_genpd_add_subdomain(parent_pd, child_pd); 565 if (ret) { 566 dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n", 567 child_pd->name, parent_pd->name); 568 goto err_put_node; 569 } else { 570 dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name, 571 child_pd->name); 572 } 573 574 /* recursive call to add all subdomains */ 575 ret = scpsys_add_subdomain(scpsys, child); 576 if (ret) 577 goto err_put_node; 578 } 579 580 return 0; 581 582 err_put_node: 583 of_node_put(child); 584 return ret; 585 } 586 587 static void scpsys_remove_one_domain(struct scpsys_domain *pd) 588 { 589 int ret; 590 591 if (scpsys_domain_is_on(pd)) 592 scpsys_power_off(&pd->genpd); 593 594 /* 595 * We're in the error cleanup already, so we only complain, 596 * but won't emit another error on top of the original one. 597 */ 598 ret = pm_genpd_remove(&pd->genpd); 599 if (ret < 0) 600 dev_err(pd->scpsys->dev, 601 "failed to remove domain '%s' : %d - state may be inconsistent\n", 602 pd->genpd.name, ret); 603 604 clk_bulk_put(pd->num_clks, pd->clks); 605 clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); 606 } 607 608 static void scpsys_domain_cleanup(struct scpsys *scpsys) 609 { 610 struct generic_pm_domain *genpd; 611 struct scpsys_domain *pd; 612 int i; 613 614 for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) { 615 genpd = scpsys->pd_data.domains[i]; 616 if (genpd) { 617 pd = to_scpsys_domain(genpd); 618 scpsys_remove_one_domain(pd); 619 } 620 } 621 } 622 623 static const struct of_device_id scpsys_of_match[] = { 624 { 625 .compatible = "mediatek,mt6795-power-controller", 626 .data = &mt6795_scpsys_data, 627 }, 628 { 629 .compatible = "mediatek,mt8167-power-controller", 630 .data = &mt8167_scpsys_data, 631 }, 632 { 633 .compatible = "mediatek,mt8173-power-controller", 634 .data = &mt8173_scpsys_data, 635 }, 636 { 637 .compatible = "mediatek,mt8183-power-controller", 638 .data = &mt8183_scpsys_data, 639 }, 640 { 641 .compatible = "mediatek,mt8186-power-controller", 642 .data = &mt8186_scpsys_data, 643 }, 644 { 645 .compatible = "mediatek,mt8188-power-controller", 646 .data = &mt8188_scpsys_data, 647 }, 648 { 649 .compatible = "mediatek,mt8192-power-controller", 650 .data = &mt8192_scpsys_data, 651 }, 652 { 653 .compatible = "mediatek,mt8195-power-controller", 654 .data = &mt8195_scpsys_data, 655 }, 656 { 657 .compatible = "mediatek,mt8365-power-controller", 658 .data = &mt8365_scpsys_data, 659 }, 660 { } 661 }; 662 663 static int scpsys_probe(struct platform_device *pdev) 664 { 665 struct device *dev = &pdev->dev; 666 struct device_node *np = dev->of_node; 667 const struct scpsys_soc_data *soc; 668 struct device_node *node; 669 struct device *parent; 670 struct scpsys *scpsys; 671 int ret; 672 673 soc = of_device_get_match_data(&pdev->dev); 674 if (!soc) { 675 dev_err(&pdev->dev, "no power controller data\n"); 676 return -EINVAL; 677 } 678 679 scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL); 680 if (!scpsys) 681 return -ENOMEM; 682 683 scpsys->dev = dev; 684 scpsys->soc_data = soc; 685 686 scpsys->pd_data.domains = scpsys->domains; 687 scpsys->pd_data.num_domains = soc->num_domains; 688 689 parent = dev->parent; 690 if (!parent) { 691 dev_err(dev, "no parent for syscon devices\n"); 692 return -ENODEV; 693 } 694 695 scpsys->base = syscon_node_to_regmap(parent->of_node); 696 if (IS_ERR(scpsys->base)) { 697 dev_err(dev, "no regmap available\n"); 698 return PTR_ERR(scpsys->base); 699 } 700 701 ret = -ENODEV; 702 for_each_available_child_of_node(np, node) { 703 struct generic_pm_domain *domain; 704 705 domain = scpsys_add_one_domain(scpsys, node); 706 if (IS_ERR(domain)) { 707 ret = PTR_ERR(domain); 708 of_node_put(node); 709 goto err_cleanup_domains; 710 } 711 712 ret = scpsys_add_subdomain(scpsys, node); 713 if (ret) { 714 of_node_put(node); 715 goto err_cleanup_domains; 716 } 717 } 718 719 if (ret) { 720 dev_dbg(dev, "no power domains present\n"); 721 return ret; 722 } 723 724 ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data); 725 if (ret) { 726 dev_err(dev, "failed to add provider: %d\n", ret); 727 goto err_cleanup_domains; 728 } 729 730 return 0; 731 732 err_cleanup_domains: 733 scpsys_domain_cleanup(scpsys); 734 return ret; 735 } 736 737 static struct platform_driver scpsys_pm_domain_driver = { 738 .probe = scpsys_probe, 739 .driver = { 740 .name = "mtk-power-controller", 741 .suppress_bind_attrs = true, 742 .of_match_table = scpsys_of_match, 743 }, 744 }; 745 builtin_platform_driver(scpsys_pm_domain_driver); 746