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