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.15-rc2 905 lines 22 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/mt6797-power.h> 25#include <dt-bindings/power/mt7622-power.h> 26#include <dt-bindings/power/mt8173-power.h> 27 28#define SPM_VDE_PWR_CON 0x0210 29#define SPM_MFG_PWR_CON 0x0214 30#define SPM_VEN_PWR_CON 0x0230 31#define SPM_ISP_PWR_CON 0x0238 32#define SPM_DIS_PWR_CON 0x023c 33#define SPM_CONN_PWR_CON 0x0280 34#define SPM_VEN2_PWR_CON 0x0298 35#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */ 36#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ 37#define SPM_ETH_PWR_CON 0x02a0 38#define SPM_HIF_PWR_CON 0x02a4 39#define SPM_IFR_MSC_PWR_CON 0x02a8 40#define SPM_MFG_2D_PWR_CON 0x02c0 41#define SPM_MFG_ASYNC_PWR_CON 0x02c4 42#define SPM_USB_PWR_CON 0x02cc 43#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */ 44#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */ 45#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */ 46#define SPM_WB_PWR_CON 0x02ec /* MT7622 */ 47 48 49#define SPM_PWR_STATUS 0x060c 50#define SPM_PWR_STATUS_2ND 0x0610 51 52#define PWR_RST_B_BIT BIT(0) 53#define PWR_ISO_BIT BIT(1) 54#define PWR_ON_BIT BIT(2) 55#define PWR_ON_2ND_BIT BIT(3) 56#define PWR_CLK_DIS_BIT BIT(4) 57 58#define PWR_STATUS_CONN BIT(1) 59#define PWR_STATUS_DISP BIT(3) 60#define PWR_STATUS_MFG BIT(4) 61#define PWR_STATUS_ISP BIT(5) 62#define PWR_STATUS_VDEC BIT(7) 63#define PWR_STATUS_BDP BIT(14) 64#define PWR_STATUS_ETH BIT(15) 65#define PWR_STATUS_HIF BIT(16) 66#define PWR_STATUS_IFR_MSC BIT(17) 67#define PWR_STATUS_VENC_LT BIT(20) 68#define PWR_STATUS_VENC BIT(21) 69#define PWR_STATUS_MFG_2D BIT(22) 70#define PWR_STATUS_MFG_ASYNC BIT(23) 71#define PWR_STATUS_AUDIO BIT(24) 72#define PWR_STATUS_USB BIT(25) 73#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */ 74#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */ 75#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ 76#define PWR_STATUS_WB BIT(27) /* MT7622 */ 77 78enum clk_id { 79 CLK_NONE, 80 CLK_MM, 81 CLK_MFG, 82 CLK_VENC, 83 CLK_VENC_LT, 84 CLK_ETHIF, 85 CLK_VDEC, 86 CLK_HIFSEL, 87 CLK_MAX, 88}; 89 90static const char * const clk_names[] = { 91 NULL, 92 "mm", 93 "mfg", 94 "venc", 95 "venc_lt", 96 "ethif", 97 "vdec", 98 "hif_sel", 99 NULL, 100}; 101 102#define MAX_CLKS 2 103 104struct scp_domain_data { 105 const char *name; 106 u32 sta_mask; 107 int ctl_offs; 108 u32 sram_pdn_bits; 109 u32 sram_pdn_ack_bits; 110 u32 bus_prot_mask; 111 enum clk_id clk_id[MAX_CLKS]; 112 bool active_wakeup; 113}; 114 115struct scp; 116 117struct scp_domain { 118 struct generic_pm_domain genpd; 119 struct scp *scp; 120 struct clk *clk[MAX_CLKS]; 121 const struct scp_domain_data *data; 122 struct regulator *supply; 123}; 124 125struct scp_ctrl_reg { 126 int pwr_sta_offs; 127 int pwr_sta2nd_offs; 128}; 129 130struct scp { 131 struct scp_domain *domains; 132 struct genpd_onecell_data pd_data; 133 struct device *dev; 134 void __iomem *base; 135 struct regmap *infracfg; 136 struct scp_ctrl_reg ctrl_reg; 137}; 138 139struct scp_subdomain { 140 int origin; 141 int subdomain; 142}; 143 144struct scp_soc_data { 145 const struct scp_domain_data *domains; 146 int num_domains; 147 const struct scp_subdomain *subdomains; 148 int num_subdomains; 149 const struct scp_ctrl_reg regs; 150}; 151 152static int scpsys_domain_is_on(struct scp_domain *scpd) 153{ 154 struct scp *scp = scpd->scp; 155 156 u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) & 157 scpd->data->sta_mask; 158 u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) & 159 scpd->data->sta_mask; 160 161 /* 162 * A domain is on when both status bits are set. If only one is set 163 * return an error. This happens while powering up a domain 164 */ 165 166 if (status && status2) 167 return true; 168 if (!status && !status2) 169 return false; 170 171 return -EINVAL; 172} 173 174static int scpsys_power_on(struct generic_pm_domain *genpd) 175{ 176 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 177 struct scp *scp = scpd->scp; 178 unsigned long timeout; 179 bool expired; 180 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 181 u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits; 182 u32 val; 183 int ret; 184 int i; 185 186 if (scpd->supply) { 187 ret = regulator_enable(scpd->supply); 188 if (ret) 189 return ret; 190 } 191 192 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) { 193 ret = clk_prepare_enable(scpd->clk[i]); 194 if (ret) { 195 for (--i; i >= 0; i--) 196 clk_disable_unprepare(scpd->clk[i]); 197 198 goto err_clk; 199 } 200 } 201 202 val = readl(ctl_addr); 203 val |= PWR_ON_BIT; 204 writel(val, ctl_addr); 205 val |= PWR_ON_2ND_BIT; 206 writel(val, ctl_addr); 207 208 /* wait until PWR_ACK = 1 */ 209 timeout = jiffies + HZ; 210 expired = false; 211 while (1) { 212 ret = scpsys_domain_is_on(scpd); 213 if (ret > 0) 214 break; 215 216 if (expired) { 217 ret = -ETIMEDOUT; 218 goto err_pwr_ack; 219 } 220 221 cpu_relax(); 222 223 if (time_after(jiffies, timeout)) 224 expired = true; 225 } 226 227 val &= ~PWR_CLK_DIS_BIT; 228 writel(val, ctl_addr); 229 230 val &= ~PWR_ISO_BIT; 231 writel(val, ctl_addr); 232 233 val |= PWR_RST_B_BIT; 234 writel(val, ctl_addr); 235 236 val &= ~scpd->data->sram_pdn_bits; 237 writel(val, ctl_addr); 238 239 /* wait until SRAM_PDN_ACK all 0 */ 240 timeout = jiffies + HZ; 241 expired = false; 242 while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) { 243 244 if (expired) { 245 ret = -ETIMEDOUT; 246 goto err_pwr_ack; 247 } 248 249 cpu_relax(); 250 251 if (time_after(jiffies, timeout)) 252 expired = true; 253 } 254 255 if (scpd->data->bus_prot_mask) { 256 ret = mtk_infracfg_clear_bus_protection(scp->infracfg, 257 scpd->data->bus_prot_mask); 258 if (ret) 259 goto err_pwr_ack; 260 } 261 262 return 0; 263 264err_pwr_ack: 265 for (i = MAX_CLKS - 1; i >= 0; i--) { 266 if (scpd->clk[i]) 267 clk_disable_unprepare(scpd->clk[i]); 268 } 269err_clk: 270 if (scpd->supply) 271 regulator_disable(scpd->supply); 272 273 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 274 275 return ret; 276} 277 278static int scpsys_power_off(struct generic_pm_domain *genpd) 279{ 280 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 281 struct scp *scp = scpd->scp; 282 unsigned long timeout; 283 bool expired; 284 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 285 u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 286 u32 val; 287 int ret; 288 int i; 289 290 if (scpd->data->bus_prot_mask) { 291 ret = mtk_infracfg_set_bus_protection(scp->infracfg, 292 scpd->data->bus_prot_mask); 293 if (ret) 294 goto out; 295 } 296 297 val = readl(ctl_addr); 298 val |= scpd->data->sram_pdn_bits; 299 writel(val, ctl_addr); 300 301 /* wait until SRAM_PDN_ACK all 1 */ 302 timeout = jiffies + HZ; 303 expired = false; 304 while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) { 305 if (expired) { 306 ret = -ETIMEDOUT; 307 goto out; 308 } 309 310 cpu_relax(); 311 312 if (time_after(jiffies, timeout)) 313 expired = true; 314 } 315 316 val |= PWR_ISO_BIT; 317 writel(val, ctl_addr); 318 319 val &= ~PWR_RST_B_BIT; 320 writel(val, ctl_addr); 321 322 val |= PWR_CLK_DIS_BIT; 323 writel(val, ctl_addr); 324 325 val &= ~PWR_ON_BIT; 326 writel(val, ctl_addr); 327 328 val &= ~PWR_ON_2ND_BIT; 329 writel(val, ctl_addr); 330 331 /* wait until PWR_ACK = 0 */ 332 timeout = jiffies + HZ; 333 expired = false; 334 while (1) { 335 ret = scpsys_domain_is_on(scpd); 336 if (ret == 0) 337 break; 338 339 if (expired) { 340 ret = -ETIMEDOUT; 341 goto out; 342 } 343 344 cpu_relax(); 345 346 if (time_after(jiffies, timeout)) 347 expired = true; 348 } 349 350 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) 351 clk_disable_unprepare(scpd->clk[i]); 352 353 if (scpd->supply) 354 regulator_disable(scpd->supply); 355 356 return 0; 357 358out: 359 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); 360 361 return ret; 362} 363 364static void init_clks(struct platform_device *pdev, struct clk **clk) 365{ 366 int i; 367 368 for (i = CLK_NONE + 1; i < CLK_MAX; i++) 369 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); 370} 371 372static struct scp *init_scp(struct platform_device *pdev, 373 const struct scp_domain_data *scp_domain_data, int num, 374 const struct scp_ctrl_reg *scp_ctrl_reg) 375{ 376 struct genpd_onecell_data *pd_data; 377 struct resource *res; 378 int i, j; 379 struct scp *scp; 380 struct clk *clk[CLK_MAX]; 381 382 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); 383 if (!scp) 384 return ERR_PTR(-ENOMEM); 385 386 scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; 387 scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; 388 389 scp->dev = &pdev->dev; 390 391 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 392 scp->base = devm_ioremap_resource(&pdev->dev, res); 393 if (IS_ERR(scp->base)) 394 return ERR_CAST(scp->base); 395 396 scp->domains = devm_kzalloc(&pdev->dev, 397 sizeof(*scp->domains) * num, GFP_KERNEL); 398 if (!scp->domains) 399 return ERR_PTR(-ENOMEM); 400 401 pd_data = &scp->pd_data; 402 403 pd_data->domains = devm_kzalloc(&pdev->dev, 404 sizeof(*pd_data->domains) * num, GFP_KERNEL); 405 if (!pd_data->domains) 406 return ERR_PTR(-ENOMEM); 407 408 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 409 "infracfg"); 410 if (IS_ERR(scp->infracfg)) { 411 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", 412 PTR_ERR(scp->infracfg)); 413 return ERR_CAST(scp->infracfg); 414 } 415 416 for (i = 0; i < num; i++) { 417 struct scp_domain *scpd = &scp->domains[i]; 418 const struct scp_domain_data *data = &scp_domain_data[i]; 419 420 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); 421 if (IS_ERR(scpd->supply)) { 422 if (PTR_ERR(scpd->supply) == -ENODEV) 423 scpd->supply = NULL; 424 else 425 return ERR_CAST(scpd->supply); 426 } 427 } 428 429 pd_data->num_domains = num; 430 431 init_clks(pdev, clk); 432 433 for (i = 0; i < num; i++) { 434 struct scp_domain *scpd = &scp->domains[i]; 435 struct generic_pm_domain *genpd = &scpd->genpd; 436 const struct scp_domain_data *data = &scp_domain_data[i]; 437 438 pd_data->domains[i] = genpd; 439 scpd->scp = scp; 440 441 scpd->data = data; 442 443 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { 444 struct clk *c = clk[data->clk_id[j]]; 445 446 if (IS_ERR(c)) { 447 dev_err(&pdev->dev, "%s: clk unavailable\n", 448 data->name); 449 return ERR_CAST(c); 450 } 451 452 scpd->clk[j] = c; 453 } 454 455 genpd->name = data->name; 456 genpd->power_off = scpsys_power_off; 457 genpd->power_on = scpsys_power_on; 458 if (scpd->data->active_wakeup) 459 genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP; 460 } 461 462 return scp; 463} 464 465static void mtk_register_power_domains(struct platform_device *pdev, 466 struct scp *scp, int num) 467{ 468 struct genpd_onecell_data *pd_data; 469 int i, ret; 470 471 for (i = 0; i < num; i++) { 472 struct scp_domain *scpd = &scp->domains[i]; 473 struct generic_pm_domain *genpd = &scpd->genpd; 474 475 /* 476 * Initially turn on all domains to make the domains usable 477 * with !CONFIG_PM and to get the hardware in sync with the 478 * software. The unused domains will be switched off during 479 * late_init time. 480 */ 481 genpd->power_on(genpd); 482 483 pm_genpd_init(genpd, NULL, false); 484 } 485 486 /* 487 * We are not allowed to fail here since there is no way to unregister 488 * a power domain. Once registered above we have to keep the domains 489 * valid. 490 */ 491 492 pd_data = &scp->pd_data; 493 494 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); 495 if (ret) 496 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); 497} 498 499/* 500 * MT2701 power domain support 501 */ 502 503static const struct scp_domain_data scp_domain_data_mt2701[] = { 504 [MT2701_POWER_DOMAIN_CONN] = { 505 .name = "conn", 506 .sta_mask = PWR_STATUS_CONN, 507 .ctl_offs = SPM_CONN_PWR_CON, 508 .bus_prot_mask = 0x0104, 509 .clk_id = {CLK_NONE}, 510 .active_wakeup = true, 511 }, 512 [MT2701_POWER_DOMAIN_DISP] = { 513 .name = "disp", 514 .sta_mask = PWR_STATUS_DISP, 515 .ctl_offs = SPM_DIS_PWR_CON, 516 .sram_pdn_bits = GENMASK(11, 8), 517 .clk_id = {CLK_MM}, 518 .bus_prot_mask = 0x0002, 519 .active_wakeup = true, 520 }, 521 [MT2701_POWER_DOMAIN_MFG] = { 522 .name = "mfg", 523 .sta_mask = PWR_STATUS_MFG, 524 .ctl_offs = SPM_MFG_PWR_CON, 525 .sram_pdn_bits = GENMASK(11, 8), 526 .sram_pdn_ack_bits = GENMASK(12, 12), 527 .clk_id = {CLK_MFG}, 528 .active_wakeup = true, 529 }, 530 [MT2701_POWER_DOMAIN_VDEC] = { 531 .name = "vdec", 532 .sta_mask = PWR_STATUS_VDEC, 533 .ctl_offs = SPM_VDE_PWR_CON, 534 .sram_pdn_bits = GENMASK(11, 8), 535 .sram_pdn_ack_bits = GENMASK(12, 12), 536 .clk_id = {CLK_MM}, 537 .active_wakeup = true, 538 }, 539 [MT2701_POWER_DOMAIN_ISP] = { 540 .name = "isp", 541 .sta_mask = PWR_STATUS_ISP, 542 .ctl_offs = SPM_ISP_PWR_CON, 543 .sram_pdn_bits = GENMASK(11, 8), 544 .sram_pdn_ack_bits = GENMASK(13, 12), 545 .clk_id = {CLK_MM}, 546 .active_wakeup = true, 547 }, 548 [MT2701_POWER_DOMAIN_BDP] = { 549 .name = "bdp", 550 .sta_mask = PWR_STATUS_BDP, 551 .ctl_offs = SPM_BDP_PWR_CON, 552 .sram_pdn_bits = GENMASK(11, 8), 553 .clk_id = {CLK_NONE}, 554 .active_wakeup = true, 555 }, 556 [MT2701_POWER_DOMAIN_ETH] = { 557 .name = "eth", 558 .sta_mask = PWR_STATUS_ETH, 559 .ctl_offs = SPM_ETH_PWR_CON, 560 .sram_pdn_bits = GENMASK(11, 8), 561 .sram_pdn_ack_bits = GENMASK(15, 12), 562 .clk_id = {CLK_ETHIF}, 563 .active_wakeup = true, 564 }, 565 [MT2701_POWER_DOMAIN_HIF] = { 566 .name = "hif", 567 .sta_mask = PWR_STATUS_HIF, 568 .ctl_offs = SPM_HIF_PWR_CON, 569 .sram_pdn_bits = GENMASK(11, 8), 570 .sram_pdn_ack_bits = GENMASK(15, 12), 571 .clk_id = {CLK_ETHIF}, 572 .active_wakeup = true, 573 }, 574 [MT2701_POWER_DOMAIN_IFR_MSC] = { 575 .name = "ifr_msc", 576 .sta_mask = PWR_STATUS_IFR_MSC, 577 .ctl_offs = SPM_IFR_MSC_PWR_CON, 578 .clk_id = {CLK_NONE}, 579 .active_wakeup = true, 580 }, 581}; 582 583/* 584 * MT6797 power domain support 585 */ 586 587static const struct scp_domain_data scp_domain_data_mt6797[] = { 588 [MT6797_POWER_DOMAIN_VDEC] = { 589 .name = "vdec", 590 .sta_mask = BIT(7), 591 .ctl_offs = 0x300, 592 .sram_pdn_bits = GENMASK(8, 8), 593 .sram_pdn_ack_bits = GENMASK(12, 12), 594 .clk_id = {CLK_VDEC}, 595 }, 596 [MT6797_POWER_DOMAIN_VENC] = { 597 .name = "venc", 598 .sta_mask = BIT(21), 599 .ctl_offs = 0x304, 600 .sram_pdn_bits = GENMASK(11, 8), 601 .sram_pdn_ack_bits = GENMASK(15, 12), 602 .clk_id = {CLK_NONE}, 603 }, 604 [MT6797_POWER_DOMAIN_ISP] = { 605 .name = "isp", 606 .sta_mask = BIT(5), 607 .ctl_offs = 0x308, 608 .sram_pdn_bits = GENMASK(9, 8), 609 .sram_pdn_ack_bits = GENMASK(13, 12), 610 .clk_id = {CLK_NONE}, 611 }, 612 [MT6797_POWER_DOMAIN_MM] = { 613 .name = "mm", 614 .sta_mask = BIT(3), 615 .ctl_offs = 0x30C, 616 .sram_pdn_bits = GENMASK(8, 8), 617 .sram_pdn_ack_bits = GENMASK(12, 12), 618 .clk_id = {CLK_MM}, 619 .bus_prot_mask = (BIT(1) | BIT(2)), 620 }, 621 [MT6797_POWER_DOMAIN_AUDIO] = { 622 .name = "audio", 623 .sta_mask = BIT(24), 624 .ctl_offs = 0x314, 625 .sram_pdn_bits = GENMASK(11, 8), 626 .sram_pdn_ack_bits = GENMASK(15, 12), 627 .clk_id = {CLK_NONE}, 628 }, 629 [MT6797_POWER_DOMAIN_MFG_ASYNC] = { 630 .name = "mfg_async", 631 .sta_mask = BIT(13), 632 .ctl_offs = 0x334, 633 .sram_pdn_bits = 0, 634 .sram_pdn_ack_bits = 0, 635 .clk_id = {CLK_MFG}, 636 }, 637 [MT6797_POWER_DOMAIN_MJC] = { 638 .name = "mjc", 639 .sta_mask = BIT(20), 640 .ctl_offs = 0x310, 641 .sram_pdn_bits = GENMASK(8, 8), 642 .sram_pdn_ack_bits = GENMASK(12, 12), 643 .clk_id = {CLK_NONE}, 644 }, 645}; 646 647#define SPM_PWR_STATUS_MT6797 0x0180 648#define SPM_PWR_STATUS_2ND_MT6797 0x0184 649 650static const struct scp_subdomain scp_subdomain_mt6797[] = { 651 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC}, 652 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP}, 653 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC}, 654 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC}, 655}; 656 657/* 658 * MT7622 power domain support 659 */ 660 661static const struct scp_domain_data scp_domain_data_mt7622[] = { 662 [MT7622_POWER_DOMAIN_ETHSYS] = { 663 .name = "ethsys", 664 .sta_mask = PWR_STATUS_ETHSYS, 665 .ctl_offs = SPM_ETHSYS_PWR_CON, 666 .sram_pdn_bits = GENMASK(11, 8), 667 .sram_pdn_ack_bits = GENMASK(15, 12), 668 .clk_id = {CLK_NONE}, 669 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS, 670 .active_wakeup = true, 671 }, 672 [MT7622_POWER_DOMAIN_HIF0] = { 673 .name = "hif0", 674 .sta_mask = PWR_STATUS_HIF0, 675 .ctl_offs = SPM_HIF0_PWR_CON, 676 .sram_pdn_bits = GENMASK(11, 8), 677 .sram_pdn_ack_bits = GENMASK(15, 12), 678 .clk_id = {CLK_HIFSEL}, 679 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0, 680 .active_wakeup = true, 681 }, 682 [MT7622_POWER_DOMAIN_HIF1] = { 683 .name = "hif1", 684 .sta_mask = PWR_STATUS_HIF1, 685 .ctl_offs = SPM_HIF1_PWR_CON, 686 .sram_pdn_bits = GENMASK(11, 8), 687 .sram_pdn_ack_bits = GENMASK(15, 12), 688 .clk_id = {CLK_HIFSEL}, 689 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1, 690 .active_wakeup = true, 691 }, 692 [MT7622_POWER_DOMAIN_WB] = { 693 .name = "wb", 694 .sta_mask = PWR_STATUS_WB, 695 .ctl_offs = SPM_WB_PWR_CON, 696 .sram_pdn_bits = 0, 697 .sram_pdn_ack_bits = 0, 698 .clk_id = {CLK_NONE}, 699 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB, 700 .active_wakeup = true, 701 }, 702}; 703 704/* 705 * MT8173 power domain support 706 */ 707 708static const struct scp_domain_data scp_domain_data_mt8173[] = { 709 [MT8173_POWER_DOMAIN_VDEC] = { 710 .name = "vdec", 711 .sta_mask = PWR_STATUS_VDEC, 712 .ctl_offs = SPM_VDE_PWR_CON, 713 .sram_pdn_bits = GENMASK(11, 8), 714 .sram_pdn_ack_bits = GENMASK(12, 12), 715 .clk_id = {CLK_MM}, 716 }, 717 [MT8173_POWER_DOMAIN_VENC] = { 718 .name = "venc", 719 .sta_mask = PWR_STATUS_VENC, 720 .ctl_offs = SPM_VEN_PWR_CON, 721 .sram_pdn_bits = GENMASK(11, 8), 722 .sram_pdn_ack_bits = GENMASK(15, 12), 723 .clk_id = {CLK_MM, CLK_VENC}, 724 }, 725 [MT8173_POWER_DOMAIN_ISP] = { 726 .name = "isp", 727 .sta_mask = PWR_STATUS_ISP, 728 .ctl_offs = SPM_ISP_PWR_CON, 729 .sram_pdn_bits = GENMASK(11, 8), 730 .sram_pdn_ack_bits = GENMASK(13, 12), 731 .clk_id = {CLK_MM}, 732 }, 733 [MT8173_POWER_DOMAIN_MM] = { 734 .name = "mm", 735 .sta_mask = PWR_STATUS_DISP, 736 .ctl_offs = SPM_DIS_PWR_CON, 737 .sram_pdn_bits = GENMASK(11, 8), 738 .sram_pdn_ack_bits = GENMASK(12, 12), 739 .clk_id = {CLK_MM}, 740 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 741 MT8173_TOP_AXI_PROT_EN_MM_M1, 742 }, 743 [MT8173_POWER_DOMAIN_VENC_LT] = { 744 .name = "venc_lt", 745 .sta_mask = PWR_STATUS_VENC_LT, 746 .ctl_offs = SPM_VEN2_PWR_CON, 747 .sram_pdn_bits = GENMASK(11, 8), 748 .sram_pdn_ack_bits = GENMASK(15, 12), 749 .clk_id = {CLK_MM, CLK_VENC_LT}, 750 }, 751 [MT8173_POWER_DOMAIN_AUDIO] = { 752 .name = "audio", 753 .sta_mask = PWR_STATUS_AUDIO, 754 .ctl_offs = SPM_AUDIO_PWR_CON, 755 .sram_pdn_bits = GENMASK(11, 8), 756 .sram_pdn_ack_bits = GENMASK(15, 12), 757 .clk_id = {CLK_NONE}, 758 }, 759 [MT8173_POWER_DOMAIN_USB] = { 760 .name = "usb", 761 .sta_mask = PWR_STATUS_USB, 762 .ctl_offs = SPM_USB_PWR_CON, 763 .sram_pdn_bits = GENMASK(11, 8), 764 .sram_pdn_ack_bits = GENMASK(15, 12), 765 .clk_id = {CLK_NONE}, 766 .active_wakeup = true, 767 }, 768 [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 769 .name = "mfg_async", 770 .sta_mask = PWR_STATUS_MFG_ASYNC, 771 .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 772 .sram_pdn_bits = GENMASK(11, 8), 773 .sram_pdn_ack_bits = 0, 774 .clk_id = {CLK_MFG}, 775 }, 776 [MT8173_POWER_DOMAIN_MFG_2D] = { 777 .name = "mfg_2d", 778 .sta_mask = PWR_STATUS_MFG_2D, 779 .ctl_offs = SPM_MFG_2D_PWR_CON, 780 .sram_pdn_bits = GENMASK(11, 8), 781 .sram_pdn_ack_bits = GENMASK(13, 12), 782 .clk_id = {CLK_NONE}, 783 }, 784 [MT8173_POWER_DOMAIN_MFG] = { 785 .name = "mfg", 786 .sta_mask = PWR_STATUS_MFG, 787 .ctl_offs = SPM_MFG_PWR_CON, 788 .sram_pdn_bits = GENMASK(13, 8), 789 .sram_pdn_ack_bits = GENMASK(21, 16), 790 .clk_id = {CLK_NONE}, 791 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 792 MT8173_TOP_AXI_PROT_EN_MFG_M0 | 793 MT8173_TOP_AXI_PROT_EN_MFG_M1 | 794 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, 795 }, 796}; 797 798static const struct scp_subdomain scp_subdomain_mt8173[] = { 799 {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D}, 800 {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG}, 801}; 802 803static const struct scp_soc_data mt2701_data = { 804 .domains = scp_domain_data_mt2701, 805 .num_domains = ARRAY_SIZE(scp_domain_data_mt2701), 806 .regs = { 807 .pwr_sta_offs = SPM_PWR_STATUS, 808 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 809 } 810}; 811 812static const struct scp_soc_data mt6797_data = { 813 .domains = scp_domain_data_mt6797, 814 .num_domains = ARRAY_SIZE(scp_domain_data_mt6797), 815 .subdomains = scp_subdomain_mt6797, 816 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797), 817 .regs = { 818 .pwr_sta_offs = SPM_PWR_STATUS_MT6797, 819 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 820 } 821}; 822 823static const struct scp_soc_data mt7622_data = { 824 .domains = scp_domain_data_mt7622, 825 .num_domains = ARRAY_SIZE(scp_domain_data_mt7622), 826 .regs = { 827 .pwr_sta_offs = SPM_PWR_STATUS, 828 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 829 } 830}; 831 832static const struct scp_soc_data mt8173_data = { 833 .domains = scp_domain_data_mt8173, 834 .num_domains = ARRAY_SIZE(scp_domain_data_mt8173), 835 .subdomains = scp_subdomain_mt8173, 836 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173), 837 .regs = { 838 .pwr_sta_offs = SPM_PWR_STATUS, 839 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 840 } 841}; 842 843/* 844 * scpsys driver init 845 */ 846 847static const struct of_device_id of_scpsys_match_tbl[] = { 848 { 849 .compatible = "mediatek,mt2701-scpsys", 850 .data = &mt2701_data, 851 }, { 852 .compatible = "mediatek,mt6797-scpsys", 853 .data = &mt6797_data, 854 }, { 855 .compatible = "mediatek,mt7622-scpsys", 856 .data = &mt7622_data, 857 }, { 858 .compatible = "mediatek,mt8173-scpsys", 859 .data = &mt8173_data, 860 }, { 861 /* sentinel */ 862 } 863}; 864 865static int scpsys_probe(struct platform_device *pdev) 866{ 867 const struct of_device_id *match; 868 const struct scp_subdomain *sd; 869 const struct scp_soc_data *soc; 870 struct scp *scp; 871 struct genpd_onecell_data *pd_data; 872 int i, ret; 873 874 match = of_match_device(of_scpsys_match_tbl, &pdev->dev); 875 soc = (const struct scp_soc_data *)match->data; 876 877 scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs); 878 if (IS_ERR(scp)) 879 return PTR_ERR(scp); 880 881 mtk_register_power_domains(pdev, scp, soc->num_domains); 882 883 pd_data = &scp->pd_data; 884 885 for (i = 0, sd = soc->subdomains ; i < soc->num_subdomains ; i++) { 886 ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin], 887 pd_data->domains[sd->subdomain]); 888 if (ret && IS_ENABLED(CONFIG_PM)) 889 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", 890 ret); 891 } 892 893 return 0; 894} 895 896static struct platform_driver scpsys_drv = { 897 .probe = scpsys_probe, 898 .driver = { 899 .name = "mtk-scpsys", 900 .suppress_bind_attrs = true, 901 .owner = THIS_MODULE, 902 .of_match_table = of_match_ptr(of_scpsys_match_tbl), 903 }, 904}; 905builtin_platform_driver(scpsys_drv);