linux/drivers/soc/mediatek/mtk-scpsys.c
<<
>>
Prefs
   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);
1148