Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.12-rc4 731 lines 17 kB view raw
1/* 2 * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13#include <linux/clk.h> 14#include <linux/init.h> 15#include <linux/io.h> 16#include <linux/mfd/syscon.h> 17#include <linux/of_device.h> 18#include <linux/platform_device.h> 19#include <linux/pm_domain.h> 20#include <linux/regulator/consumer.h> 21#include <linux/soc/mediatek/infracfg.h> 22 23#include <dt-bindings/power/mt2701-power.h> 24#include <dt-bindings/power/mt8173-power.h> 25 26#define SPM_VDE_PWR_CON 0x0210 27#define SPM_MFG_PWR_CON 0x0214 28#define SPM_VEN_PWR_CON 0x0230 29#define SPM_ISP_PWR_CON 0x0238 30#define SPM_DIS_PWR_CON 0x023c 31#define SPM_CONN_PWR_CON 0x0280 32#define SPM_VEN2_PWR_CON 0x0298 33#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */ 34#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ 35#define SPM_ETH_PWR_CON 0x02a0 36#define SPM_HIF_PWR_CON 0x02a4 37#define SPM_IFR_MSC_PWR_CON 0x02a8 38#define SPM_MFG_2D_PWR_CON 0x02c0 39#define SPM_MFG_ASYNC_PWR_CON 0x02c4 40#define SPM_USB_PWR_CON 0x02cc 41 42#define SPM_PWR_STATUS 0x060c 43#define SPM_PWR_STATUS_2ND 0x0610 44 45#define PWR_RST_B_BIT BIT(0) 46#define PWR_ISO_BIT BIT(1) 47#define PWR_ON_BIT BIT(2) 48#define PWR_ON_2ND_BIT BIT(3) 49#define PWR_CLK_DIS_BIT BIT(4) 50 51#define PWR_STATUS_CONN BIT(1) 52#define PWR_STATUS_DISP BIT(3) 53#define PWR_STATUS_MFG BIT(4) 54#define PWR_STATUS_ISP BIT(5) 55#define PWR_STATUS_VDEC BIT(7) 56#define PWR_STATUS_BDP BIT(14) 57#define PWR_STATUS_ETH BIT(15) 58#define PWR_STATUS_HIF BIT(16) 59#define PWR_STATUS_IFR_MSC BIT(17) 60#define PWR_STATUS_VENC_LT BIT(20) 61#define PWR_STATUS_VENC BIT(21) 62#define PWR_STATUS_MFG_2D BIT(22) 63#define PWR_STATUS_MFG_ASYNC BIT(23) 64#define PWR_STATUS_AUDIO BIT(24) 65#define PWR_STATUS_USB BIT(25) 66 67enum clk_id { 68 CLK_NONE, 69 CLK_MM, 70 CLK_MFG, 71 CLK_VENC, 72 CLK_VENC_LT, 73 CLK_ETHIF, 74 CLK_MAX, 75}; 76 77static const char * const clk_names[] = { 78 NULL, 79 "mm", 80 "mfg", 81 "venc", 82 "venc_lt", 83 "ethif", 84 NULL, 85}; 86 87#define MAX_CLKS 2 88 89struct scp_domain_data { 90 const char *name; 91 u32 sta_mask; 92 int ctl_offs; 93 u32 sram_pdn_bits; 94 u32 sram_pdn_ack_bits; 95 u32 bus_prot_mask; 96 enum clk_id clk_id[MAX_CLKS]; 97 bool active_wakeup; 98}; 99 100struct scp; 101 102struct scp_domain { 103 struct generic_pm_domain genpd; 104 struct scp *scp; 105 struct clk *clk[MAX_CLKS]; 106 const struct scp_domain_data *data; 107 struct regulator *supply; 108}; 109 110struct scp { 111 struct scp_domain *domains; 112 struct genpd_onecell_data pd_data; 113 struct device *dev; 114 void __iomem *base; 115 struct regmap *infracfg; 116}; 117 118static int scpsys_domain_is_on(struct scp_domain *scpd) 119{ 120 struct scp *scp = scpd->scp; 121 122 u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->data->sta_mask; 123 u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & 124 scpd->data->sta_mask; 125 126 /* 127 * A domain is on when both status bits are set. If only one is set 128 * return an error. This happens while powering up a domain 129 */ 130 131 if (status && status2) 132 return true; 133 if (!status && !status2) 134 return false; 135 136 return -EINVAL; 137} 138 139static int scpsys_power_on(struct generic_pm_domain *genpd) 140{ 141 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 142 struct scp *scp = scpd->scp; 143 unsigned long timeout; 144 bool expired; 145 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 146 u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits; 147 u32 val; 148 int ret; 149 int i; 150 151 if (scpd->supply) { 152 ret = regulator_enable(scpd->supply); 153 if (ret) 154 return ret; 155 } 156 157 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { 158 ret = clk_prepare_enable(scpd->clk[i]); 159 if (ret) { 160 for (--i; i >= 0; i--) 161 clk_disable_unprepare(scpd->clk[i]); 162 163 goto err_clk; 164 } 165 } 166 167 val = readl(ctl_addr); 168 val |= PWR_ON_BIT; 169 writel(val, ctl_addr); 170 val |= PWR_ON_2ND_BIT; 171 writel(val, ctl_addr); 172 173 /* wait until PWR_ACK = 1 */ 174 timeout = jiffies + HZ; 175 expired = false; 176 while (1) { 177 ret = scpsys_domain_is_on(scpd); 178 if (ret > 0) 179 break; 180 181 if (expired) { 182 ret = -ETIMEDOUT; 183 goto err_pwr_ack; 184 } 185 186 cpu_relax(); 187 188 if (time_after(jiffies, timeout)) 189 expired = true; 190 } 191 192 val &= ~PWR_CLK_DIS_BIT; 193 writel(val, ctl_addr); 194 195 val &= ~PWR_ISO_BIT; 196 writel(val, ctl_addr); 197 198 val |= PWR_RST_B_BIT; 199 writel(val, ctl_addr); 200 201 val &= ~scpd->data->sram_pdn_bits; 202 writel(val, ctl_addr); 203 204 /* wait until SRAM_PDN_ACK all 0 */ 205 timeout = jiffies + HZ; 206 expired = false; 207 while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) { 208 209 if (expired) { 210 ret = -ETIMEDOUT; 211 goto err_pwr_ack; 212 } 213 214 cpu_relax(); 215 216 if (time_after(jiffies, timeout)) 217 expired = true; 218 } 219 220 if (scpd->data->bus_prot_mask) { 221 ret = mtk_infracfg_clear_bus_protection(scp->infracfg, 222 scpd->data->bus_prot_mask); 223 if (ret) 224 goto err_pwr_ack; 225 } 226 227 return 0; 228 229err_pwr_ack: 230 for (i = MAX_CLKS - 1; i >= 0; i--) { 231 if (scpd->clk[i]) 232 clk_disable_unprepare(scpd->clk[i]); 233 } 234err_clk: 235 if (scpd->supply) 236 regulator_disable(scpd->supply); 237 238 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 239 240 return ret; 241} 242 243static int scpsys_power_off(struct generic_pm_domain *genpd) 244{ 245 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 246 struct scp *scp = scpd->scp; 247 unsigned long timeout; 248 bool expired; 249 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 250 u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 251 u32 val; 252 int ret; 253 int i; 254 255 if (scpd->data->bus_prot_mask) { 256 ret = mtk_infracfg_set_bus_protection(scp->infracfg, 257 scpd->data->bus_prot_mask); 258 if (ret) 259 goto out; 260 } 261 262 val = readl(ctl_addr); 263 val |= scpd->data->sram_pdn_bits; 264 writel(val, ctl_addr); 265 266 /* wait until SRAM_PDN_ACK all 1 */ 267 timeout = jiffies + HZ; 268 expired = false; 269 while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) { 270 if (expired) { 271 ret = -ETIMEDOUT; 272 goto out; 273 } 274 275 cpu_relax(); 276 277 if (time_after(jiffies, timeout)) 278 expired = true; 279 } 280 281 val |= PWR_ISO_BIT; 282 writel(val, ctl_addr); 283 284 val &= ~PWR_RST_B_BIT; 285 writel(val, ctl_addr); 286 287 val |= PWR_CLK_DIS_BIT; 288 writel(val, ctl_addr); 289 290 val &= ~PWR_ON_BIT; 291 writel(val, ctl_addr); 292 293 val &= ~PWR_ON_2ND_BIT; 294 writel(val, ctl_addr); 295 296 /* wait until PWR_ACK = 0 */ 297 timeout = jiffies + HZ; 298 expired = false; 299 while (1) { 300 ret = scpsys_domain_is_on(scpd); 301 if (ret == 0) 302 break; 303 304 if (expired) { 305 ret = -ETIMEDOUT; 306 goto out; 307 } 308 309 cpu_relax(); 310 311 if (time_after(jiffies, timeout)) 312 expired = true; 313 } 314 315 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) 316 clk_disable_unprepare(scpd->clk[i]); 317 318 if (scpd->supply) 319 regulator_disable(scpd->supply); 320 321 return 0; 322 323out: 324 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); 325 326 return ret; 327} 328 329static bool scpsys_active_wakeup(struct device *dev) 330{ 331 struct generic_pm_domain *genpd; 332 struct scp_domain *scpd; 333 334 genpd = pd_to_genpd(dev->pm_domain); 335 scpd = container_of(genpd, struct scp_domain, genpd); 336 337 return scpd->data->active_wakeup; 338} 339 340static void init_clks(struct platform_device *pdev, struct clk **clk) 341{ 342 int i; 343 344 for (i = CLK_NONE + 1; i < CLK_MAX; i++) 345 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); 346} 347 348static struct scp *init_scp(struct platform_device *pdev, 349 const struct scp_domain_data *scp_domain_data, int num) 350{ 351 struct genpd_onecell_data *pd_data; 352 struct resource *res; 353 int i, j; 354 struct scp *scp; 355 struct clk *clk[CLK_MAX]; 356 357 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); 358 if (!scp) 359 return ERR_PTR(-ENOMEM); 360 361 scp->dev = &pdev->dev; 362 363 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 364 scp->base = devm_ioremap_resource(&pdev->dev, res); 365 if (IS_ERR(scp->base)) 366 return ERR_CAST(scp->base); 367 368 scp->domains = devm_kzalloc(&pdev->dev, 369 sizeof(*scp->domains) * num, GFP_KERNEL); 370 if (!scp->domains) 371 return ERR_PTR(-ENOMEM); 372 373 pd_data = &scp->pd_data; 374 375 pd_data->domains = devm_kzalloc(&pdev->dev, 376 sizeof(*pd_data->domains) * num, GFP_KERNEL); 377 if (!pd_data->domains) 378 return ERR_PTR(-ENOMEM); 379 380 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 381 "infracfg"); 382 if (IS_ERR(scp->infracfg)) { 383 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", 384 PTR_ERR(scp->infracfg)); 385 return ERR_CAST(scp->infracfg); 386 } 387 388 for (i = 0; i < num; i++) { 389 struct scp_domain *scpd = &scp->domains[i]; 390 const struct scp_domain_data *data = &scp_domain_data[i]; 391 392 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); 393 if (IS_ERR(scpd->supply)) { 394 if (PTR_ERR(scpd->supply) == -ENODEV) 395 scpd->supply = NULL; 396 else 397 return ERR_CAST(scpd->supply); 398 } 399 } 400 401 pd_data->num_domains = num; 402 403 init_clks(pdev, clk); 404 405 for (i = 0; i < num; i++) { 406 struct scp_domain *scpd = &scp->domains[i]; 407 struct generic_pm_domain *genpd = &scpd->genpd; 408 const struct scp_domain_data *data = &scp_domain_data[i]; 409 410 pd_data->domains[i] = genpd; 411 scpd->scp = scp; 412 413 scpd->data = data; 414 415 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { 416 struct clk *c = clk[data->clk_id[j]]; 417 418 if (IS_ERR(c)) { 419 dev_err(&pdev->dev, "%s: clk unavailable\n", 420 data->name); 421 return ERR_CAST(c); 422 } 423 424 scpd->clk[j] = c; 425 } 426 427 genpd->name = data->name; 428 genpd->power_off = scpsys_power_off; 429 genpd->power_on = scpsys_power_on; 430 genpd->dev_ops.active_wakeup = scpsys_active_wakeup; 431 } 432 433 return scp; 434} 435 436static void mtk_register_power_domains(struct platform_device *pdev, 437 struct scp *scp, int num) 438{ 439 struct genpd_onecell_data *pd_data; 440 int i, ret; 441 442 for (i = 0; i < num; i++) { 443 struct scp_domain *scpd = &scp->domains[i]; 444 struct generic_pm_domain *genpd = &scpd->genpd; 445 446 /* 447 * Initially turn on all domains to make the domains usable 448 * with !CONFIG_PM and to get the hardware in sync with the 449 * software. The unused domains will be switched off during 450 * late_init time. 451 */ 452 genpd->power_on(genpd); 453 454 pm_genpd_init(genpd, NULL, false); 455 } 456 457 /* 458 * We are not allowed to fail here since there is no way to unregister 459 * a power domain. Once registered above we have to keep the domains 460 * valid. 461 */ 462 463 pd_data = &scp->pd_data; 464 465 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); 466 if (ret) 467 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); 468} 469 470/* 471 * MT2701 power domain support 472 */ 473 474static const struct scp_domain_data scp_domain_data_mt2701[] = { 475 [MT2701_POWER_DOMAIN_CONN] = { 476 .name = "conn", 477 .sta_mask = PWR_STATUS_CONN, 478 .ctl_offs = SPM_CONN_PWR_CON, 479 .bus_prot_mask = 0x0104, 480 .clk_id = {CLK_NONE}, 481 .active_wakeup = true, 482 }, 483 [MT2701_POWER_DOMAIN_DISP] = { 484 .name = "disp", 485 .sta_mask = PWR_STATUS_DISP, 486 .ctl_offs = SPM_DIS_PWR_CON, 487 .sram_pdn_bits = GENMASK(11, 8), 488 .clk_id = {CLK_MM}, 489 .bus_prot_mask = 0x0002, 490 .active_wakeup = true, 491 }, 492 [MT2701_POWER_DOMAIN_MFG] = { 493 .name = "mfg", 494 .sta_mask = PWR_STATUS_MFG, 495 .ctl_offs = SPM_MFG_PWR_CON, 496 .sram_pdn_bits = GENMASK(11, 8), 497 .sram_pdn_ack_bits = GENMASK(12, 12), 498 .clk_id = {CLK_MFG}, 499 .active_wakeup = true, 500 }, 501 [MT2701_POWER_DOMAIN_VDEC] = { 502 .name = "vdec", 503 .sta_mask = PWR_STATUS_VDEC, 504 .ctl_offs = SPM_VDE_PWR_CON, 505 .sram_pdn_bits = GENMASK(11, 8), 506 .sram_pdn_ack_bits = GENMASK(12, 12), 507 .clk_id = {CLK_MM}, 508 .active_wakeup = true, 509 }, 510 [MT2701_POWER_DOMAIN_ISP] = { 511 .name = "isp", 512 .sta_mask = PWR_STATUS_ISP, 513 .ctl_offs = SPM_ISP_PWR_CON, 514 .sram_pdn_bits = GENMASK(11, 8), 515 .sram_pdn_ack_bits = GENMASK(13, 12), 516 .clk_id = {CLK_MM}, 517 .active_wakeup = true, 518 }, 519 [MT2701_POWER_DOMAIN_BDP] = { 520 .name = "bdp", 521 .sta_mask = PWR_STATUS_BDP, 522 .ctl_offs = SPM_BDP_PWR_CON, 523 .sram_pdn_bits = GENMASK(11, 8), 524 .clk_id = {CLK_NONE}, 525 .active_wakeup = true, 526 }, 527 [MT2701_POWER_DOMAIN_ETH] = { 528 .name = "eth", 529 .sta_mask = PWR_STATUS_ETH, 530 .ctl_offs = SPM_ETH_PWR_CON, 531 .sram_pdn_bits = GENMASK(11, 8), 532 .sram_pdn_ack_bits = GENMASK(15, 12), 533 .clk_id = {CLK_ETHIF}, 534 .active_wakeup = true, 535 }, 536 [MT2701_POWER_DOMAIN_HIF] = { 537 .name = "hif", 538 .sta_mask = PWR_STATUS_HIF, 539 .ctl_offs = SPM_HIF_PWR_CON, 540 .sram_pdn_bits = GENMASK(11, 8), 541 .sram_pdn_ack_bits = GENMASK(15, 12), 542 .clk_id = {CLK_ETHIF}, 543 .active_wakeup = true, 544 }, 545 [MT2701_POWER_DOMAIN_IFR_MSC] = { 546 .name = "ifr_msc", 547 .sta_mask = PWR_STATUS_IFR_MSC, 548 .ctl_offs = SPM_IFR_MSC_PWR_CON, 549 .clk_id = {CLK_NONE}, 550 .active_wakeup = true, 551 }, 552}; 553 554#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701) 555 556static int __init scpsys_probe_mt2701(struct platform_device *pdev) 557{ 558 struct scp *scp; 559 560 scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701); 561 if (IS_ERR(scp)) 562 return PTR_ERR(scp); 563 564 mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701); 565 566 return 0; 567} 568 569/* 570 * MT8173 power domain support 571 */ 572 573static const struct scp_domain_data scp_domain_data_mt8173[] = { 574 [MT8173_POWER_DOMAIN_VDEC] = { 575 .name = "vdec", 576 .sta_mask = PWR_STATUS_VDEC, 577 .ctl_offs = SPM_VDE_PWR_CON, 578 .sram_pdn_bits = GENMASK(11, 8), 579 .sram_pdn_ack_bits = GENMASK(12, 12), 580 .clk_id = {CLK_MM}, 581 }, 582 [MT8173_POWER_DOMAIN_VENC] = { 583 .name = "venc", 584 .sta_mask = PWR_STATUS_VENC, 585 .ctl_offs = SPM_VEN_PWR_CON, 586 .sram_pdn_bits = GENMASK(11, 8), 587 .sram_pdn_ack_bits = GENMASK(15, 12), 588 .clk_id = {CLK_MM, CLK_VENC}, 589 }, 590 [MT8173_POWER_DOMAIN_ISP] = { 591 .name = "isp", 592 .sta_mask = PWR_STATUS_ISP, 593 .ctl_offs = SPM_ISP_PWR_CON, 594 .sram_pdn_bits = GENMASK(11, 8), 595 .sram_pdn_ack_bits = GENMASK(13, 12), 596 .clk_id = {CLK_MM}, 597 }, 598 [MT8173_POWER_DOMAIN_MM] = { 599 .name = "mm", 600 .sta_mask = PWR_STATUS_DISP, 601 .ctl_offs = SPM_DIS_PWR_CON, 602 .sram_pdn_bits = GENMASK(11, 8), 603 .sram_pdn_ack_bits = GENMASK(12, 12), 604 .clk_id = {CLK_MM}, 605 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 606 MT8173_TOP_AXI_PROT_EN_MM_M1, 607 }, 608 [MT8173_POWER_DOMAIN_VENC_LT] = { 609 .name = "venc_lt", 610 .sta_mask = PWR_STATUS_VENC_LT, 611 .ctl_offs = SPM_VEN2_PWR_CON, 612 .sram_pdn_bits = GENMASK(11, 8), 613 .sram_pdn_ack_bits = GENMASK(15, 12), 614 .clk_id = {CLK_MM, CLK_VENC_LT}, 615 }, 616 [MT8173_POWER_DOMAIN_AUDIO] = { 617 .name = "audio", 618 .sta_mask = PWR_STATUS_AUDIO, 619 .ctl_offs = SPM_AUDIO_PWR_CON, 620 .sram_pdn_bits = GENMASK(11, 8), 621 .sram_pdn_ack_bits = GENMASK(15, 12), 622 .clk_id = {CLK_NONE}, 623 }, 624 [MT8173_POWER_DOMAIN_USB] = { 625 .name = "usb", 626 .sta_mask = PWR_STATUS_USB, 627 .ctl_offs = SPM_USB_PWR_CON, 628 .sram_pdn_bits = GENMASK(11, 8), 629 .sram_pdn_ack_bits = GENMASK(15, 12), 630 .clk_id = {CLK_NONE}, 631 .active_wakeup = true, 632 }, 633 [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 634 .name = "mfg_async", 635 .sta_mask = PWR_STATUS_MFG_ASYNC, 636 .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 637 .sram_pdn_bits = GENMASK(11, 8), 638 .sram_pdn_ack_bits = 0, 639 .clk_id = {CLK_MFG}, 640 }, 641 [MT8173_POWER_DOMAIN_MFG_2D] = { 642 .name = "mfg_2d", 643 .sta_mask = PWR_STATUS_MFG_2D, 644 .ctl_offs = SPM_MFG_2D_PWR_CON, 645 .sram_pdn_bits = GENMASK(11, 8), 646 .sram_pdn_ack_bits = GENMASK(13, 12), 647 .clk_id = {CLK_NONE}, 648 }, 649 [MT8173_POWER_DOMAIN_MFG] = { 650 .name = "mfg", 651 .sta_mask = PWR_STATUS_MFG, 652 .ctl_offs = SPM_MFG_PWR_CON, 653 .sram_pdn_bits = GENMASK(13, 8), 654 .sram_pdn_ack_bits = GENMASK(21, 16), 655 .clk_id = {CLK_NONE}, 656 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 657 MT8173_TOP_AXI_PROT_EN_MFG_M0 | 658 MT8173_TOP_AXI_PROT_EN_MFG_M1 | 659 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, 660 }, 661}; 662 663#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173) 664 665static int __init scpsys_probe_mt8173(struct platform_device *pdev) 666{ 667 struct scp *scp; 668 struct genpd_onecell_data *pd_data; 669 int ret; 670 671 scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173); 672 if (IS_ERR(scp)) 673 return PTR_ERR(scp); 674 675 mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173); 676 677 pd_data = &scp->pd_data; 678 679 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], 680 pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); 681 if (ret && IS_ENABLED(CONFIG_PM)) 682 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); 683 684 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D], 685 pd_data->domains[MT8173_POWER_DOMAIN_MFG]); 686 if (ret && IS_ENABLED(CONFIG_PM)) 687 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); 688 689 return 0; 690} 691 692/* 693 * scpsys driver init 694 */ 695 696static const struct of_device_id of_scpsys_match_tbl[] = { 697 { 698 .compatible = "mediatek,mt2701-scpsys", 699 .data = scpsys_probe_mt2701, 700 }, { 701 .compatible = "mediatek,mt8173-scpsys", 702 .data = scpsys_probe_mt8173, 703 }, { 704 /* sentinel */ 705 } 706}; 707 708static int scpsys_probe(struct platform_device *pdev) 709{ 710 int (*probe)(struct platform_device *); 711 const struct of_device_id *of_id; 712 713 of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node); 714 if (!of_id || !of_id->data) 715 return -EINVAL; 716 717 probe = of_id->data; 718 719 return probe(pdev); 720} 721 722static struct platform_driver scpsys_drv = { 723 .probe = scpsys_probe, 724 .driver = { 725 .name = "mtk-scpsys", 726 .suppress_bind_attrs = true, 727 .owner = THIS_MODULE, 728 .of_match_table = of_match_ptr(of_scpsys_match_tbl), 729 }, 730}; 731builtin_platform_driver(scpsys_drv);