mtk-scpsys.c (28958B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> 4 */ 5#include <linux/clk.h> 6#include <linux/init.h> 7#include <linux/io.h> 8#include <linux/iopoll.h> 9#include <linux/mfd/syscon.h> 10#include <linux/of_device.h> 11#include <linux/platform_device.h> 12#include <linux/pm_domain.h> 13#include <linux/regulator/consumer.h> 14#include <linux/soc/mediatek/infracfg.h> 15 16#include <dt-bindings/power/mt2701-power.h> 17#include <dt-bindings/power/mt2712-power.h> 18#include <dt-bindings/power/mt6797-power.h> 19#include <dt-bindings/power/mt7622-power.h> 20#include <dt-bindings/power/mt7623a-power.h> 21#include <dt-bindings/power/mt8173-power.h> 22 23#define MTK_POLL_DELAY_US 10 24#define MTK_POLL_TIMEOUT USEC_PER_SEC 25 26#define MTK_SCPD_ACTIVE_WAKEUP BIT(0) 27#define MTK_SCPD_FWAIT_SRAM BIT(1) 28#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) 29 30#define SPM_VDE_PWR_CON 0x0210 31#define SPM_MFG_PWR_CON 0x0214 32#define SPM_VEN_PWR_CON 0x0230 33#define SPM_ISP_PWR_CON 0x0238 34#define SPM_DIS_PWR_CON 0x023c 35#define SPM_CONN_PWR_CON 0x0280 36#define SPM_VEN2_PWR_CON 0x0298 37#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */ 38#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ 39#define SPM_ETH_PWR_CON 0x02a0 40#define SPM_HIF_PWR_CON 0x02a4 41#define SPM_IFR_MSC_PWR_CON 0x02a8 42#define SPM_MFG_2D_PWR_CON 0x02c0 43#define SPM_MFG_ASYNC_PWR_CON 0x02c4 44#define SPM_USB_PWR_CON 0x02cc 45#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */ 46#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */ 47#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */ 48#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */ 49#define SPM_WB_PWR_CON 0x02ec /* MT7622 */ 50 51#define SPM_PWR_STATUS 0x060c 52#define SPM_PWR_STATUS_2ND 0x0610 53 54#define PWR_RST_B_BIT BIT(0) 55#define PWR_ISO_BIT BIT(1) 56#define PWR_ON_BIT BIT(2) 57#define PWR_ON_2ND_BIT BIT(3) 58#define PWR_CLK_DIS_BIT BIT(4) 59 60#define PWR_STATUS_CONN BIT(1) 61#define PWR_STATUS_DISP BIT(3) 62#define PWR_STATUS_MFG BIT(4) 63#define PWR_STATUS_ISP BIT(5) 64#define PWR_STATUS_VDEC BIT(7) 65#define PWR_STATUS_BDP BIT(14) 66#define PWR_STATUS_ETH BIT(15) 67#define PWR_STATUS_HIF BIT(16) 68#define PWR_STATUS_IFR_MSC BIT(17) 69#define PWR_STATUS_USB2 BIT(19) /* MT2712 */ 70#define PWR_STATUS_VENC_LT BIT(20) 71#define PWR_STATUS_VENC BIT(21) 72#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */ 73#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */ 74#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */ 75#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */ 76#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */ 77#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */ 78#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ 79#define PWR_STATUS_WB BIT(27) /* MT7622 */ 80 81enum clk_id { 82 CLK_NONE, 83 CLK_MM, 84 CLK_MFG, 85 CLK_VENC, 86 CLK_VENC_LT, 87 CLK_ETHIF, 88 CLK_VDEC, 89 CLK_HIFSEL, 90 CLK_JPGDEC, 91 CLK_AUDIO, 92 CLK_MAX, 93}; 94 95static const char * const clk_names[] = { 96 NULL, 97 "mm", 98 "mfg", 99 "venc", 100 "venc_lt", 101 "ethif", 102 "vdec", 103 "hif_sel", 104 "jpgdec", 105 "audio", 106 NULL, 107}; 108 109#define MAX_CLKS 3 110 111/** 112 * struct scp_domain_data - scp domain data for power on/off flow 113 * @name: The domain name. 114 * @sta_mask: The mask for power on/off status bit. 115 * @ctl_offs: The offset for main power control register. 116 * @sram_pdn_bits: The mask for sram power control bits. 117 * @sram_pdn_ack_bits: The mask for sram power control acked bits. 118 * @bus_prot_mask: The mask for single step bus protection. 119 * @clk_id: The basic clocks required by this power domain. 120 * @caps: The flag for active wake-up action. 121 */ 122struct scp_domain_data { 123 const char *name; 124 u32 sta_mask; 125 int ctl_offs; 126 u32 sram_pdn_bits; 127 u32 sram_pdn_ack_bits; 128 u32 bus_prot_mask; 129 enum clk_id clk_id[MAX_CLKS]; 130 u8 caps; 131}; 132 133struct scp; 134 135struct scp_domain { 136 struct generic_pm_domain genpd; 137 struct scp *scp; 138 struct clk *clk[MAX_CLKS]; 139 const struct scp_domain_data *data; 140 struct regulator *supply; 141}; 142 143struct scp_ctrl_reg { 144 int pwr_sta_offs; 145 int pwr_sta2nd_offs; 146}; 147 148struct scp { 149 struct scp_domain *domains; 150 struct genpd_onecell_data pd_data; 151 struct device *dev; 152 void __iomem *base; 153 struct regmap *infracfg; 154 struct scp_ctrl_reg ctrl_reg; 155 bool bus_prot_reg_update; 156}; 157 158struct scp_subdomain { 159 int origin; 160 int subdomain; 161}; 162 163struct scp_soc_data { 164 const struct scp_domain_data *domains; 165 int num_domains; 166 const struct scp_subdomain *subdomains; 167 int num_subdomains; 168 const struct scp_ctrl_reg regs; 169 bool bus_prot_reg_update; 170}; 171 172static int scpsys_domain_is_on(struct scp_domain *scpd) 173{ 174 struct scp *scp = scpd->scp; 175 176 u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) & 177 scpd->data->sta_mask; 178 u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) & 179 scpd->data->sta_mask; 180 181 /* 182 * A domain is on when both status bits are set. If only one is set 183 * return an error. This happens while powering up a domain 184 */ 185 186 if (status && status2) 187 return true; 188 if (!status && !status2) 189 return false; 190 191 return -EINVAL; 192} 193 194static int scpsys_regulator_enable(struct scp_domain *scpd) 195{ 196 if (!scpd->supply) 197 return 0; 198 199 return regulator_enable(scpd->supply); 200} 201 202static int scpsys_regulator_disable(struct scp_domain *scpd) 203{ 204 if (!scpd->supply) 205 return 0; 206 207 return regulator_disable(scpd->supply); 208} 209 210static void scpsys_clk_disable(struct clk *clk[], int max_num) 211{ 212 int i; 213 214 for (i = max_num - 1; i >= 0; i--) 215 clk_disable_unprepare(clk[i]); 216} 217 218static int scpsys_clk_enable(struct clk *clk[], int max_num) 219{ 220 int i, ret = 0; 221 222 for (i = 0; i < max_num && clk[i]; i++) { 223 ret = clk_prepare_enable(clk[i]); 224 if (ret) { 225 scpsys_clk_disable(clk, i); 226 break; 227 } 228 } 229 230 return ret; 231} 232 233static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr) 234{ 235 u32 val; 236 u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 237 int tmp; 238 239 val = readl(ctl_addr); 240 val &= ~scpd->data->sram_pdn_bits; 241 writel(val, ctl_addr); 242 243 /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */ 244 if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) { 245 /* 246 * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for 247 * MT7622_POWER_DOMAIN_WB and thus just a trivial setup 248 * is applied here. 249 */ 250 usleep_range(12000, 12100); 251 } else { 252 /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 253 int ret = readl_poll_timeout(ctl_addr, tmp, 254 (tmp & pdn_ack) == 0, 255 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 256 if (ret < 0) 257 return ret; 258 } 259 260 return 0; 261} 262 263static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) 264{ 265 u32 val; 266 u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 267 int tmp; 268 269 val = readl(ctl_addr); 270 val |= scpd->data->sram_pdn_bits; 271 writel(val, ctl_addr); 272 273 /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 274 return readl_poll_timeout(ctl_addr, tmp, 275 (tmp & pdn_ack) == pdn_ack, 276 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 277} 278 279static int scpsys_bus_protect_enable(struct scp_domain *scpd) 280{ 281 struct scp *scp = scpd->scp; 282 283 if (!scpd->data->bus_prot_mask) 284 return 0; 285 286 return mtk_infracfg_set_bus_protection(scp->infracfg, 287 scpd->data->bus_prot_mask, 288 scp->bus_prot_reg_update); 289} 290 291static int scpsys_bus_protect_disable(struct scp_domain *scpd) 292{ 293 struct scp *scp = scpd->scp; 294 295 if (!scpd->data->bus_prot_mask) 296 return 0; 297 298 return mtk_infracfg_clear_bus_protection(scp->infracfg, 299 scpd->data->bus_prot_mask, 300 scp->bus_prot_reg_update); 301} 302 303static int scpsys_power_on(struct generic_pm_domain *genpd) 304{ 305 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 306 struct scp *scp = scpd->scp; 307 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 308 u32 val; 309 int ret, tmp; 310 311 ret = scpsys_regulator_enable(scpd); 312 if (ret < 0) 313 return ret; 314 315 ret = scpsys_clk_enable(scpd->clk, MAX_CLKS); 316 if (ret) 317 goto err_clk; 318 319 /* subsys power on */ 320 val = readl(ctl_addr); 321 val |= PWR_ON_BIT; 322 writel(val, ctl_addr); 323 val |= PWR_ON_2ND_BIT; 324 writel(val, ctl_addr); 325 326 /* wait until PWR_ACK = 1 */ 327 ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0, 328 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 329 if (ret < 0) 330 goto err_pwr_ack; 331 332 val &= ~PWR_CLK_DIS_BIT; 333 writel(val, ctl_addr); 334 335 val &= ~PWR_ISO_BIT; 336 writel(val, ctl_addr); 337 338 val |= PWR_RST_B_BIT; 339 writel(val, ctl_addr); 340 341 ret = scpsys_sram_enable(scpd, ctl_addr); 342 if (ret < 0) 343 goto err_pwr_ack; 344 345 ret = scpsys_bus_protect_disable(scpd); 346 if (ret < 0) 347 goto err_pwr_ack; 348 349 return 0; 350 351err_pwr_ack: 352 scpsys_clk_disable(scpd->clk, MAX_CLKS); 353err_clk: 354 scpsys_regulator_disable(scpd); 355 356 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 357 358 return ret; 359} 360 361static int scpsys_power_off(struct generic_pm_domain *genpd) 362{ 363 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 364 struct scp *scp = scpd->scp; 365 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 366 u32 val; 367 int ret, tmp; 368 369 ret = scpsys_bus_protect_enable(scpd); 370 if (ret < 0) 371 goto out; 372 373 ret = scpsys_sram_disable(scpd, ctl_addr); 374 if (ret < 0) 375 goto out; 376 377 /* subsys power off */ 378 val = readl(ctl_addr); 379 val |= PWR_ISO_BIT; 380 writel(val, ctl_addr); 381 382 val &= ~PWR_RST_B_BIT; 383 writel(val, ctl_addr); 384 385 val |= PWR_CLK_DIS_BIT; 386 writel(val, ctl_addr); 387 388 val &= ~PWR_ON_BIT; 389 writel(val, ctl_addr); 390 391 val &= ~PWR_ON_2ND_BIT; 392 writel(val, ctl_addr); 393 394 /* wait until PWR_ACK = 0 */ 395 ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0, 396 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 397 if (ret < 0) 398 goto out; 399 400 scpsys_clk_disable(scpd->clk, MAX_CLKS); 401 402 ret = scpsys_regulator_disable(scpd); 403 if (ret < 0) 404 goto out; 405 406 return 0; 407 408out: 409 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); 410 411 return ret; 412} 413 414static void init_clks(struct platform_device *pdev, struct clk **clk) 415{ 416 int i; 417 418 for (i = CLK_NONE + 1; i < CLK_MAX; i++) 419 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); 420} 421 422static struct scp *init_scp(struct platform_device *pdev, 423 const struct scp_domain_data *scp_domain_data, int num, 424 const struct scp_ctrl_reg *scp_ctrl_reg, 425 bool bus_prot_reg_update) 426{ 427 struct genpd_onecell_data *pd_data; 428 struct resource *res; 429 int i, j; 430 struct scp *scp; 431 struct clk *clk[CLK_MAX]; 432 433 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); 434 if (!scp) 435 return ERR_PTR(-ENOMEM); 436 437 scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; 438 scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; 439 440 scp->bus_prot_reg_update = bus_prot_reg_update; 441 442 scp->dev = &pdev->dev; 443 444 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 445 scp->base = devm_ioremap_resource(&pdev->dev, res); 446 if (IS_ERR(scp->base)) 447 return ERR_CAST(scp->base); 448 449 scp->domains = devm_kcalloc(&pdev->dev, 450 num, sizeof(*scp->domains), GFP_KERNEL); 451 if (!scp->domains) 452 return ERR_PTR(-ENOMEM); 453 454 pd_data = &scp->pd_data; 455 456 pd_data->domains = devm_kcalloc(&pdev->dev, 457 num, sizeof(*pd_data->domains), GFP_KERNEL); 458 if (!pd_data->domains) 459 return ERR_PTR(-ENOMEM); 460 461 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 462 "infracfg"); 463 if (IS_ERR(scp->infracfg)) { 464 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", 465 PTR_ERR(scp->infracfg)); 466 return ERR_CAST(scp->infracfg); 467 } 468 469 for (i = 0; i < num; i++) { 470 struct scp_domain *scpd = &scp->domains[i]; 471 const struct scp_domain_data *data = &scp_domain_data[i]; 472 473 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); 474 if (IS_ERR(scpd->supply)) { 475 if (PTR_ERR(scpd->supply) == -ENODEV) 476 scpd->supply = NULL; 477 else 478 return ERR_CAST(scpd->supply); 479 } 480 } 481 482 pd_data->num_domains = num; 483 484 init_clks(pdev, clk); 485 486 for (i = 0; i < num; i++) { 487 struct scp_domain *scpd = &scp->domains[i]; 488 struct generic_pm_domain *genpd = &scpd->genpd; 489 const struct scp_domain_data *data = &scp_domain_data[i]; 490 491 pd_data->domains[i] = genpd; 492 scpd->scp = scp; 493 494 scpd->data = data; 495 496 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { 497 struct clk *c = clk[data->clk_id[j]]; 498 499 if (IS_ERR(c)) { 500 dev_err(&pdev->dev, "%s: clk unavailable\n", 501 data->name); 502 return ERR_CAST(c); 503 } 504 505 scpd->clk[j] = c; 506 } 507 508 genpd->name = data->name; 509 genpd->power_off = scpsys_power_off; 510 genpd->power_on = scpsys_power_on; 511 if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP)) 512 genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP; 513 } 514 515 return scp; 516} 517 518static void mtk_register_power_domains(struct platform_device *pdev, 519 struct scp *scp, int num) 520{ 521 struct genpd_onecell_data *pd_data; 522 int i, ret; 523 524 for (i = 0; i < num; i++) { 525 struct scp_domain *scpd = &scp->domains[i]; 526 struct generic_pm_domain *genpd = &scpd->genpd; 527 bool on; 528 529 /* 530 * Initially turn on all domains to make the domains usable 531 * with !CONFIG_PM and to get the hardware in sync with the 532 * software. The unused domains will be switched off during 533 * late_init time. 534 */ 535 on = !WARN_ON(genpd->power_on(genpd) < 0); 536 537 pm_genpd_init(genpd, NULL, !on); 538 } 539 540 /* 541 * We are not allowed to fail here since there is no way to unregister 542 * a power domain. Once registered above we have to keep the domains 543 * valid. 544 */ 545 546 pd_data = &scp->pd_data; 547 548 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); 549 if (ret) 550 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); 551} 552 553/* 554 * MT2701 power domain support 555 */ 556 557static const struct scp_domain_data scp_domain_data_mt2701[] = { 558 [MT2701_POWER_DOMAIN_CONN] = { 559 .name = "conn", 560 .sta_mask = PWR_STATUS_CONN, 561 .ctl_offs = SPM_CONN_PWR_CON, 562 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | 563 MT2701_TOP_AXI_PROT_EN_CONN_S, 564 .clk_id = {CLK_NONE}, 565 .caps = MTK_SCPD_ACTIVE_WAKEUP, 566 }, 567 [MT2701_POWER_DOMAIN_DISP] = { 568 .name = "disp", 569 .sta_mask = PWR_STATUS_DISP, 570 .ctl_offs = SPM_DIS_PWR_CON, 571 .sram_pdn_bits = GENMASK(11, 8), 572 .clk_id = {CLK_MM}, 573 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0, 574 .caps = MTK_SCPD_ACTIVE_WAKEUP, 575 }, 576 [MT2701_POWER_DOMAIN_MFG] = { 577 .name = "mfg", 578 .sta_mask = PWR_STATUS_MFG, 579 .ctl_offs = SPM_MFG_PWR_CON, 580 .sram_pdn_bits = GENMASK(11, 8), 581 .sram_pdn_ack_bits = GENMASK(12, 12), 582 .clk_id = {CLK_MFG}, 583 .caps = MTK_SCPD_ACTIVE_WAKEUP, 584 }, 585 [MT2701_POWER_DOMAIN_VDEC] = { 586 .name = "vdec", 587 .sta_mask = PWR_STATUS_VDEC, 588 .ctl_offs = SPM_VDE_PWR_CON, 589 .sram_pdn_bits = GENMASK(11, 8), 590 .sram_pdn_ack_bits = GENMASK(12, 12), 591 .clk_id = {CLK_MM}, 592 .caps = MTK_SCPD_ACTIVE_WAKEUP, 593 }, 594 [MT2701_POWER_DOMAIN_ISP] = { 595 .name = "isp", 596 .sta_mask = PWR_STATUS_ISP, 597 .ctl_offs = SPM_ISP_PWR_CON, 598 .sram_pdn_bits = GENMASK(11, 8), 599 .sram_pdn_ack_bits = GENMASK(13, 12), 600 .clk_id = {CLK_MM}, 601 .caps = MTK_SCPD_ACTIVE_WAKEUP, 602 }, 603 [MT2701_POWER_DOMAIN_BDP] = { 604 .name = "bdp", 605 .sta_mask = PWR_STATUS_BDP, 606 .ctl_offs = SPM_BDP_PWR_CON, 607 .sram_pdn_bits = GENMASK(11, 8), 608 .clk_id = {CLK_NONE}, 609 .caps = MTK_SCPD_ACTIVE_WAKEUP, 610 }, 611 [MT2701_POWER_DOMAIN_ETH] = { 612 .name = "eth", 613 .sta_mask = PWR_STATUS_ETH, 614 .ctl_offs = SPM_ETH_PWR_CON, 615 .sram_pdn_bits = GENMASK(11, 8), 616 .sram_pdn_ack_bits = GENMASK(15, 12), 617 .clk_id = {CLK_ETHIF}, 618 .caps = MTK_SCPD_ACTIVE_WAKEUP, 619 }, 620 [MT2701_POWER_DOMAIN_HIF] = { 621 .name = "hif", 622 .sta_mask = PWR_STATUS_HIF, 623 .ctl_offs = SPM_HIF_PWR_CON, 624 .sram_pdn_bits = GENMASK(11, 8), 625 .sram_pdn_ack_bits = GENMASK(15, 12), 626 .clk_id = {CLK_ETHIF}, 627 .caps = MTK_SCPD_ACTIVE_WAKEUP, 628 }, 629 [MT2701_POWER_DOMAIN_IFR_MSC] = { 630 .name = "ifr_msc", 631 .sta_mask = PWR_STATUS_IFR_MSC, 632 .ctl_offs = SPM_IFR_MSC_PWR_CON, 633 .clk_id = {CLK_NONE}, 634 .caps = MTK_SCPD_ACTIVE_WAKEUP, 635 }, 636}; 637 638/* 639 * MT2712 power domain support 640 */ 641static const struct scp_domain_data scp_domain_data_mt2712[] = { 642 [MT2712_POWER_DOMAIN_MM] = { 643 .name = "mm", 644 .sta_mask = PWR_STATUS_DISP, 645 .ctl_offs = SPM_DIS_PWR_CON, 646 .sram_pdn_bits = GENMASK(8, 8), 647 .sram_pdn_ack_bits = GENMASK(12, 12), 648 .clk_id = {CLK_MM}, 649 .caps = MTK_SCPD_ACTIVE_WAKEUP, 650 }, 651 [MT2712_POWER_DOMAIN_VDEC] = { 652 .name = "vdec", 653 .sta_mask = PWR_STATUS_VDEC, 654 .ctl_offs = SPM_VDE_PWR_CON, 655 .sram_pdn_bits = GENMASK(8, 8), 656 .sram_pdn_ack_bits = GENMASK(12, 12), 657 .clk_id = {CLK_MM, CLK_VDEC}, 658 .caps = MTK_SCPD_ACTIVE_WAKEUP, 659 }, 660 [MT2712_POWER_DOMAIN_VENC] = { 661 .name = "venc", 662 .sta_mask = PWR_STATUS_VENC, 663 .ctl_offs = SPM_VEN_PWR_CON, 664 .sram_pdn_bits = GENMASK(11, 8), 665 .sram_pdn_ack_bits = GENMASK(15, 12), 666 .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC}, 667 .caps = MTK_SCPD_ACTIVE_WAKEUP, 668 }, 669 [MT2712_POWER_DOMAIN_ISP] = { 670 .name = "isp", 671 .sta_mask = PWR_STATUS_ISP, 672 .ctl_offs = SPM_ISP_PWR_CON, 673 .sram_pdn_bits = GENMASK(11, 8), 674 .sram_pdn_ack_bits = GENMASK(13, 12), 675 .clk_id = {CLK_MM}, 676 .caps = MTK_SCPD_ACTIVE_WAKEUP, 677 }, 678 [MT2712_POWER_DOMAIN_AUDIO] = { 679 .name = "audio", 680 .sta_mask = PWR_STATUS_AUDIO, 681 .ctl_offs = SPM_AUDIO_PWR_CON, 682 .sram_pdn_bits = GENMASK(11, 8), 683 .sram_pdn_ack_bits = GENMASK(15, 12), 684 .clk_id = {CLK_AUDIO}, 685 .caps = MTK_SCPD_ACTIVE_WAKEUP, 686 }, 687 [MT2712_POWER_DOMAIN_USB] = { 688 .name = "usb", 689 .sta_mask = PWR_STATUS_USB, 690 .ctl_offs = SPM_USB_PWR_CON, 691 .sram_pdn_bits = GENMASK(10, 8), 692 .sram_pdn_ack_bits = GENMASK(14, 12), 693 .clk_id = {CLK_NONE}, 694 .caps = MTK_SCPD_ACTIVE_WAKEUP, 695 }, 696 [MT2712_POWER_DOMAIN_USB2] = { 697 .name = "usb2", 698 .sta_mask = PWR_STATUS_USB2, 699 .ctl_offs = SPM_USB2_PWR_CON, 700 .sram_pdn_bits = GENMASK(10, 8), 701 .sram_pdn_ack_bits = GENMASK(14, 12), 702 .clk_id = {CLK_NONE}, 703 .caps = MTK_SCPD_ACTIVE_WAKEUP, 704 }, 705 [MT2712_POWER_DOMAIN_MFG] = { 706 .name = "mfg", 707 .sta_mask = PWR_STATUS_MFG, 708 .ctl_offs = SPM_MFG_PWR_CON, 709 .sram_pdn_bits = GENMASK(8, 8), 710 .sram_pdn_ack_bits = GENMASK(16, 16), 711 .clk_id = {CLK_MFG}, 712 .bus_prot_mask = BIT(14) | BIT(21) | BIT(23), 713 .caps = MTK_SCPD_ACTIVE_WAKEUP, 714 }, 715 [MT2712_POWER_DOMAIN_MFG_SC1] = { 716 .name = "mfg_sc1", 717 .sta_mask = BIT(22), 718 .ctl_offs = 0x02c0, 719 .sram_pdn_bits = GENMASK(8, 8), 720 .sram_pdn_ack_bits = GENMASK(16, 16), 721 .clk_id = {CLK_NONE}, 722 .caps = MTK_SCPD_ACTIVE_WAKEUP, 723 }, 724 [MT2712_POWER_DOMAIN_MFG_SC2] = { 725 .name = "mfg_sc2", 726 .sta_mask = BIT(23), 727 .ctl_offs = 0x02c4, 728 .sram_pdn_bits = GENMASK(8, 8), 729 .sram_pdn_ack_bits = GENMASK(16, 16), 730 .clk_id = {CLK_NONE}, 731 .caps = MTK_SCPD_ACTIVE_WAKEUP, 732 }, 733 [MT2712_POWER_DOMAIN_MFG_SC3] = { 734 .name = "mfg_sc3", 735 .sta_mask = BIT(30), 736 .ctl_offs = 0x01f8, 737 .sram_pdn_bits = GENMASK(8, 8), 738 .sram_pdn_ack_bits = GENMASK(16, 16), 739 .clk_id = {CLK_NONE}, 740 .caps = MTK_SCPD_ACTIVE_WAKEUP, 741 }, 742}; 743 744static const struct scp_subdomain scp_subdomain_mt2712[] = { 745 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC}, 746 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC}, 747 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP}, 748 {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1}, 749 {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2}, 750 {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3}, 751}; 752 753/* 754 * MT6797 power domain support 755 */ 756 757static const struct scp_domain_data scp_domain_data_mt6797[] = { 758 [MT6797_POWER_DOMAIN_VDEC] = { 759 .name = "vdec", 760 .sta_mask = BIT(7), 761 .ctl_offs = 0x300, 762 .sram_pdn_bits = GENMASK(8, 8), 763 .sram_pdn_ack_bits = GENMASK(12, 12), 764 .clk_id = {CLK_VDEC}, 765 }, 766 [MT6797_POWER_DOMAIN_VENC] = { 767 .name = "venc", 768 .sta_mask = BIT(21), 769 .ctl_offs = 0x304, 770 .sram_pdn_bits = GENMASK(11, 8), 771 .sram_pdn_ack_bits = GENMASK(15, 12), 772 .clk_id = {CLK_NONE}, 773 }, 774 [MT6797_POWER_DOMAIN_ISP] = { 775 .name = "isp", 776 .sta_mask = BIT(5), 777 .ctl_offs = 0x308, 778 .sram_pdn_bits = GENMASK(9, 8), 779 .sram_pdn_ack_bits = GENMASK(13, 12), 780 .clk_id = {CLK_NONE}, 781 }, 782 [MT6797_POWER_DOMAIN_MM] = { 783 .name = "mm", 784 .sta_mask = BIT(3), 785 .ctl_offs = 0x30C, 786 .sram_pdn_bits = GENMASK(8, 8), 787 .sram_pdn_ack_bits = GENMASK(12, 12), 788 .clk_id = {CLK_MM}, 789 .bus_prot_mask = (BIT(1) | BIT(2)), 790 }, 791 [MT6797_POWER_DOMAIN_AUDIO] = { 792 .name = "audio", 793 .sta_mask = BIT(24), 794 .ctl_offs = 0x314, 795 .sram_pdn_bits = GENMASK(11, 8), 796 .sram_pdn_ack_bits = GENMASK(15, 12), 797 .clk_id = {CLK_NONE}, 798 }, 799 [MT6797_POWER_DOMAIN_MFG_ASYNC] = { 800 .name = "mfg_async", 801 .sta_mask = BIT(13), 802 .ctl_offs = 0x334, 803 .sram_pdn_bits = 0, 804 .sram_pdn_ack_bits = 0, 805 .clk_id = {CLK_MFG}, 806 }, 807 [MT6797_POWER_DOMAIN_MJC] = { 808 .name = "mjc", 809 .sta_mask = BIT(20), 810 .ctl_offs = 0x310, 811 .sram_pdn_bits = GENMASK(8, 8), 812 .sram_pdn_ack_bits = GENMASK(12, 12), 813 .clk_id = {CLK_NONE}, 814 }, 815}; 816 817#define SPM_PWR_STATUS_MT6797 0x0180 818#define SPM_PWR_STATUS_2ND_MT6797 0x0184 819 820static const struct scp_subdomain scp_subdomain_mt6797[] = { 821 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC}, 822 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP}, 823 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC}, 824 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC}, 825}; 826 827/* 828 * MT7622 power domain support 829 */ 830 831static const struct scp_domain_data scp_domain_data_mt7622[] = { 832 [MT7622_POWER_DOMAIN_ETHSYS] = { 833 .name = "ethsys", 834 .sta_mask = PWR_STATUS_ETHSYS, 835 .ctl_offs = SPM_ETHSYS_PWR_CON, 836 .sram_pdn_bits = GENMASK(11, 8), 837 .sram_pdn_ack_bits = GENMASK(15, 12), 838 .clk_id = {CLK_NONE}, 839 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS, 840 .caps = MTK_SCPD_ACTIVE_WAKEUP, 841 }, 842 [MT7622_POWER_DOMAIN_HIF0] = { 843 .name = "hif0", 844 .sta_mask = PWR_STATUS_HIF0, 845 .ctl_offs = SPM_HIF0_PWR_CON, 846 .sram_pdn_bits = GENMASK(11, 8), 847 .sram_pdn_ack_bits = GENMASK(15, 12), 848 .clk_id = {CLK_HIFSEL}, 849 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0, 850 .caps = MTK_SCPD_ACTIVE_WAKEUP, 851 }, 852 [MT7622_POWER_DOMAIN_HIF1] = { 853 .name = "hif1", 854 .sta_mask = PWR_STATUS_HIF1, 855 .ctl_offs = SPM_HIF1_PWR_CON, 856 .sram_pdn_bits = GENMASK(11, 8), 857 .sram_pdn_ack_bits = GENMASK(15, 12), 858 .clk_id = {CLK_HIFSEL}, 859 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1, 860 .caps = MTK_SCPD_ACTIVE_WAKEUP, 861 }, 862 [MT7622_POWER_DOMAIN_WB] = { 863 .name = "wb", 864 .sta_mask = PWR_STATUS_WB, 865 .ctl_offs = SPM_WB_PWR_CON, 866 .sram_pdn_bits = 0, 867 .sram_pdn_ack_bits = 0, 868 .clk_id = {CLK_NONE}, 869 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB, 870 .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM, 871 }, 872}; 873 874/* 875 * MT7623A power domain support 876 */ 877 878static const struct scp_domain_data scp_domain_data_mt7623a[] = { 879 [MT7623A_POWER_DOMAIN_CONN] = { 880 .name = "conn", 881 .sta_mask = PWR_STATUS_CONN, 882 .ctl_offs = SPM_CONN_PWR_CON, 883 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | 884 MT2701_TOP_AXI_PROT_EN_CONN_S, 885 .clk_id = {CLK_NONE}, 886 .caps = MTK_SCPD_ACTIVE_WAKEUP, 887 }, 888 [MT7623A_POWER_DOMAIN_ETH] = { 889 .name = "eth", 890 .sta_mask = PWR_STATUS_ETH, 891 .ctl_offs = SPM_ETH_PWR_CON, 892 .sram_pdn_bits = GENMASK(11, 8), 893 .sram_pdn_ack_bits = GENMASK(15, 12), 894 .clk_id = {CLK_ETHIF}, 895 .caps = MTK_SCPD_ACTIVE_WAKEUP, 896 }, 897 [MT7623A_POWER_DOMAIN_HIF] = { 898 .name = "hif", 899 .sta_mask = PWR_STATUS_HIF, 900 .ctl_offs = SPM_HIF_PWR_CON, 901 .sram_pdn_bits = GENMASK(11, 8), 902 .sram_pdn_ack_bits = GENMASK(15, 12), 903 .clk_id = {CLK_ETHIF}, 904 .caps = MTK_SCPD_ACTIVE_WAKEUP, 905 }, 906 [MT7623A_POWER_DOMAIN_IFR_MSC] = { 907 .name = "ifr_msc", 908 .sta_mask = PWR_STATUS_IFR_MSC, 909 .ctl_offs = SPM_IFR_MSC_PWR_CON, 910 .clk_id = {CLK_NONE}, 911 .caps = MTK_SCPD_ACTIVE_WAKEUP, 912 }, 913}; 914 915/* 916 * MT8173 power domain support 917 */ 918 919static const struct scp_domain_data scp_domain_data_mt8173[] = { 920 [MT8173_POWER_DOMAIN_VDEC] = { 921 .name = "vdec", 922 .sta_mask = PWR_STATUS_VDEC, 923 .ctl_offs = SPM_VDE_PWR_CON, 924 .sram_pdn_bits = GENMASK(11, 8), 925 .sram_pdn_ack_bits = GENMASK(12, 12), 926 .clk_id = {CLK_MM}, 927 }, 928 [MT8173_POWER_DOMAIN_VENC] = { 929 .name = "venc", 930 .sta_mask = PWR_STATUS_VENC, 931 .ctl_offs = SPM_VEN_PWR_CON, 932 .sram_pdn_bits = GENMASK(11, 8), 933 .sram_pdn_ack_bits = GENMASK(15, 12), 934 .clk_id = {CLK_MM, CLK_VENC}, 935 }, 936 [MT8173_POWER_DOMAIN_ISP] = { 937 .name = "isp", 938 .sta_mask = PWR_STATUS_ISP, 939 .ctl_offs = SPM_ISP_PWR_CON, 940 .sram_pdn_bits = GENMASK(11, 8), 941 .sram_pdn_ack_bits = GENMASK(13, 12), 942 .clk_id = {CLK_MM}, 943 }, 944 [MT8173_POWER_DOMAIN_MM] = { 945 .name = "mm", 946 .sta_mask = PWR_STATUS_DISP, 947 .ctl_offs = SPM_DIS_PWR_CON, 948 .sram_pdn_bits = GENMASK(11, 8), 949 .sram_pdn_ack_bits = GENMASK(12, 12), 950 .clk_id = {CLK_MM}, 951 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 952 MT8173_TOP_AXI_PROT_EN_MM_M1, 953 }, 954 [MT8173_POWER_DOMAIN_VENC_LT] = { 955 .name = "venc_lt", 956 .sta_mask = PWR_STATUS_VENC_LT, 957 .ctl_offs = SPM_VEN2_PWR_CON, 958 .sram_pdn_bits = GENMASK(11, 8), 959 .sram_pdn_ack_bits = GENMASK(15, 12), 960 .clk_id = {CLK_MM, CLK_VENC_LT}, 961 }, 962 [MT8173_POWER_DOMAIN_AUDIO] = { 963 .name = "audio", 964 .sta_mask = PWR_STATUS_AUDIO, 965 .ctl_offs = SPM_AUDIO_PWR_CON, 966 .sram_pdn_bits = GENMASK(11, 8), 967 .sram_pdn_ack_bits = GENMASK(15, 12), 968 .clk_id = {CLK_NONE}, 969 }, 970 [MT8173_POWER_DOMAIN_USB] = { 971 .name = "usb", 972 .sta_mask = PWR_STATUS_USB, 973 .ctl_offs = SPM_USB_PWR_CON, 974 .sram_pdn_bits = GENMASK(11, 8), 975 .sram_pdn_ack_bits = GENMASK(15, 12), 976 .clk_id = {CLK_NONE}, 977 .caps = MTK_SCPD_ACTIVE_WAKEUP, 978 }, 979 [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 980 .name = "mfg_async", 981 .sta_mask = PWR_STATUS_MFG_ASYNC, 982 .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 983 .sram_pdn_bits = GENMASK(11, 8), 984 .sram_pdn_ack_bits = 0, 985 .clk_id = {CLK_MFG}, 986 }, 987 [MT8173_POWER_DOMAIN_MFG_2D] = { 988 .name = "mfg_2d", 989 .sta_mask = PWR_STATUS_MFG_2D, 990 .ctl_offs = SPM_MFG_2D_PWR_CON, 991 .sram_pdn_bits = GENMASK(11, 8), 992 .sram_pdn_ack_bits = GENMASK(13, 12), 993 .clk_id = {CLK_NONE}, 994 }, 995 [MT8173_POWER_DOMAIN_MFG] = { 996 .name = "mfg", 997 .sta_mask = PWR_STATUS_MFG, 998 .ctl_offs = SPM_MFG_PWR_CON, 999 .sram_pdn_bits = GENMASK(13, 8), 1000 .sram_pdn_ack_bits = GENMASK(21, 16), 1001 .clk_id = {CLK_NONE}, 1002 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 1003 MT8173_TOP_AXI_PROT_EN_MFG_M0 | 1004 MT8173_TOP_AXI_PROT_EN_MFG_M1 | 1005 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, 1006 }, 1007}; 1008 1009static const struct scp_subdomain scp_subdomain_mt8173[] = { 1010 {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D}, 1011 {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG}, 1012}; 1013 1014static const struct scp_soc_data mt2701_data = { 1015 .domains = scp_domain_data_mt2701, 1016 .num_domains = ARRAY_SIZE(scp_domain_data_mt2701), 1017 .regs = { 1018 .pwr_sta_offs = SPM_PWR_STATUS, 1019 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 1020 }, 1021 .bus_prot_reg_update = true, 1022}; 1023 1024static const struct scp_soc_data mt2712_data = { 1025 .domains = scp_domain_data_mt2712, 1026 .num_domains = ARRAY_SIZE(scp_domain_data_mt2712), 1027 .subdomains = scp_subdomain_mt2712, 1028 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712), 1029 .regs = { 1030 .pwr_sta_offs = SPM_PWR_STATUS, 1031 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 1032 }, 1033 .bus_prot_reg_update = false, 1034}; 1035 1036static const struct scp_soc_data mt6797_data = { 1037 .domains = scp_domain_data_mt6797, 1038 .num_domains = ARRAY_SIZE(scp_domain_data_mt6797), 1039 .subdomains = scp_subdomain_mt6797, 1040 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797), 1041 .regs = { 1042 .pwr_sta_offs = SPM_PWR_STATUS_MT6797, 1043 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 1044 }, 1045 .bus_prot_reg_update = true, 1046}; 1047 1048static const struct scp_soc_data mt7622_data = { 1049 .domains = scp_domain_data_mt7622, 1050 .num_domains = ARRAY_SIZE(scp_domain_data_mt7622), 1051 .regs = { 1052 .pwr_sta_offs = SPM_PWR_STATUS, 1053 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 1054 }, 1055 .bus_prot_reg_update = true, 1056}; 1057 1058static const struct scp_soc_data mt7623a_data = { 1059 .domains = scp_domain_data_mt7623a, 1060 .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a), 1061 .regs = { 1062 .pwr_sta_offs = SPM_PWR_STATUS, 1063 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 1064 }, 1065 .bus_prot_reg_update = true, 1066}; 1067 1068static const struct scp_soc_data mt8173_data = { 1069 .domains = scp_domain_data_mt8173, 1070 .num_domains = ARRAY_SIZE(scp_domain_data_mt8173), 1071 .subdomains = scp_subdomain_mt8173, 1072 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173), 1073 .regs = { 1074 .pwr_sta_offs = SPM_PWR_STATUS, 1075 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 1076 }, 1077 .bus_prot_reg_update = true, 1078}; 1079 1080/* 1081 * scpsys driver init 1082 */ 1083 1084static const struct of_device_id of_scpsys_match_tbl[] = { 1085 { 1086 .compatible = "mediatek,mt2701-scpsys", 1087 .data = &mt2701_data, 1088 }, { 1089 .compatible = "mediatek,mt2712-scpsys", 1090 .data = &mt2712_data, 1091 }, { 1092 .compatible = "mediatek,mt6797-scpsys", 1093 .data = &mt6797_data, 1094 }, { 1095 .compatible = "mediatek,mt7622-scpsys", 1096 .data = &mt7622_data, 1097 }, { 1098 .compatible = "mediatek,mt7623a-scpsys", 1099 .data = &mt7623a_data, 1100 }, { 1101 .compatible = "mediatek,mt8173-scpsys", 1102 .data = &mt8173_data, 1103 }, { 1104 /* sentinel */ 1105 } 1106}; 1107 1108static int scpsys_probe(struct platform_device *pdev) 1109{ 1110 const struct scp_subdomain *sd; 1111 const struct scp_soc_data *soc; 1112 struct scp *scp; 1113 struct genpd_onecell_data *pd_data; 1114 int i, ret; 1115 1116 soc = of_device_get_match_data(&pdev->dev); 1117 1118 scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs, 1119 soc->bus_prot_reg_update); 1120 if (IS_ERR(scp)) 1121 return PTR_ERR(scp); 1122 1123 mtk_register_power_domains(pdev, scp, soc->num_domains); 1124 1125 pd_data = &scp->pd_data; 1126 1127 for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) { 1128 ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin], 1129 pd_data->domains[sd->subdomain]); 1130 if (ret && IS_ENABLED(CONFIG_PM)) 1131 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", 1132 ret); 1133 } 1134 1135 return 0; 1136} 1137 1138static struct platform_driver scpsys_drv = { 1139 .probe = scpsys_probe, 1140 .driver = { 1141 .name = "mtk-scpsys", 1142 .suppress_bind_attrs = true, 1143 .owner = THIS_MODULE, 1144 .of_match_table = of_match_ptr(of_scpsys_match_tbl), 1145 }, 1146}; 1147builtin_platform_driver(scpsys_drv);