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