File Index
Files and directories
Sign in
FILE

mtk-scpsys.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pmdomain/mediatek/mtk-scpsys.c C
   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.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	int i, j;
 429	struct scp *scp;
 430	struct clk *clk[CLK_MAX];
 431
 432	scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
 433	if (!scp)
 434		return ERR_PTR(-ENOMEM);
 435
 436	scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
 437	scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
 438
 439	scp->bus_prot_reg_update = bus_prot_reg_update;
 440
 441	scp->dev = &pdev->dev;
 442
 443	scp->base = devm_platform_ioremap_resource(pdev, 0);
 444	if (IS_ERR(scp->base))
 445		return ERR_CAST(scp->base);
 446
 447	scp->domains = devm_kcalloc(&pdev->dev,
 448				num, sizeof(*scp->domains), GFP_KERNEL);
 449	if (!scp->domains)
 450		return ERR_PTR(-ENOMEM);
 451
 452	pd_data = &scp->pd_data;
 453
 454	pd_data->domains = devm_kcalloc(&pdev->dev,
 455			num, sizeof(*pd_data->domains), GFP_KERNEL);
 456	if (!pd_data->domains)
 457		return ERR_PTR(-ENOMEM);
 458
 459	scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 460			"infracfg");
 461	if (IS_ERR(scp->infracfg)) {
 462		dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
 463				PTR_ERR(scp->infracfg));
 464		return ERR_CAST(scp->infracfg);
 465	}
 466
 467	for (i = 0; i < num; i++) {
 468		struct scp_domain *scpd = &scp->domains[i];
 469		const struct scp_domain_data *data = &scp_domain_data[i];
 470
 471		scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
 472		if (IS_ERR(scpd->supply)) {
 473			if (PTR_ERR(scpd->supply) == -ENODEV)
 474				scpd->supply = NULL;
 475			else
 476				return ERR_CAST(scpd->supply);
 477		}
 478	}
 479
 480	pd_data->num_domains = num;
 481
 482	init_clks(pdev, clk);
 483
 484	for (i = 0; i < num; i++) {
 485		struct scp_domain *scpd = &scp->domains[i];
 486		struct generic_pm_domain *genpd = &scpd->genpd;
 487		const struct scp_domain_data *data = &scp_domain_data[i];
 488
 489		pd_data->domains[i] = genpd;
 490		scpd->scp = scp;
 491
 492		scpd->data = data;
 493
 494		for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
 495			struct clk *c = clk[data->clk_id[j]];
 496
 497			if (IS_ERR(c)) {
 498				dev_err(&pdev->dev, "%s: clk unavailable\n",
 499					data->name);
 500				return ERR_CAST(c);
 501			}
 502
 503			scpd->clk[j] = c;
 504		}
 505
 506		genpd->name = data->name;
 507		genpd->power_off = scpsys_power_off;
 508		genpd->power_on = scpsys_power_on;
 509		if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
 510			genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
 511	}
 512
 513	return scp;
 514}
 515
 516static void mtk_register_power_domains(struct platform_device *pdev,
 517				struct scp *scp, int num)
 518{
 519	struct genpd_onecell_data *pd_data;
 520	int i, ret;
 521
 522	for (i = 0; i < num; i++) {
 523		struct scp_domain *scpd = &scp->domains[i];
 524		struct generic_pm_domain *genpd = &scpd->genpd;
 525		bool on;
 526
 527		/*
 528		 * Initially turn on all domains to make the domains usable
 529		 * with !CONFIG_PM and to get the hardware in sync with the
 530		 * software.  The unused domains will be switched off during
 531		 * late_init time.
 532		 */
 533		on = !WARN_ON(genpd->power_on(genpd) < 0);
 534
 535		pm_genpd_init(genpd, NULL, !on);
 536	}
 537
 538	/*
 539	 * We are not allowed to fail here since there is no way to unregister
 540	 * a power domain. Once registered above we have to keep the domains
 541	 * valid.
 542	 */
 543
 544	pd_data = &scp->pd_data;
 545
 546	ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
 547	if (ret)
 548		dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
 549}
 550
 551/*
 552 * MT2701 power domain support
 553 */
 554
 555static const struct scp_domain_data scp_domain_data_mt2701[] = {
 556	[MT2701_POWER_DOMAIN_CONN] = {
 557		.name = "conn",
 558		.sta_mask = PWR_STATUS_CONN,
 559		.ctl_offs = SPM_CONN_PWR_CON,
 560		.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
 561				 MT2701_TOP_AXI_PROT_EN_CONN_S,
 562		.clk_id = {CLK_NONE},
 563		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 564	},
 565	[MT2701_POWER_DOMAIN_DISP] = {
 566		.name = "disp",
 567		.sta_mask = PWR_STATUS_DISP,
 568		.ctl_offs = SPM_DIS_PWR_CON,
 569		.sram_pdn_bits = GENMASK(11, 8),
 570		.clk_id = {CLK_MM},
 571		.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
 572		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 573	},
 574	[MT2701_POWER_DOMAIN_MFG] = {
 575		.name = "mfg",
 576		.sta_mask = PWR_STATUS_MFG,
 577		.ctl_offs = SPM_MFG_PWR_CON,
 578		.sram_pdn_bits = GENMASK(11, 8),
 579		.sram_pdn_ack_bits = GENMASK(12, 12),
 580		.clk_id = {CLK_MFG},
 581		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 582	},
 583	[MT2701_POWER_DOMAIN_VDEC] = {
 584		.name = "vdec",
 585		.sta_mask = PWR_STATUS_VDEC,
 586		.ctl_offs = SPM_VDE_PWR_CON,
 587		.sram_pdn_bits = GENMASK(11, 8),
 588		.sram_pdn_ack_bits = GENMASK(12, 12),
 589		.clk_id = {CLK_MM},
 590		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 591	},
 592	[MT2701_POWER_DOMAIN_ISP] = {
 593		.name = "isp",
 594		.sta_mask = PWR_STATUS_ISP,
 595		.ctl_offs = SPM_ISP_PWR_CON,
 596		.sram_pdn_bits = GENMASK(11, 8),
 597		.sram_pdn_ack_bits = GENMASK(13, 12),
 598		.clk_id = {CLK_MM},
 599		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 600	},
 601	[MT2701_POWER_DOMAIN_BDP] = {
 602		.name = "bdp",
 603		.sta_mask = PWR_STATUS_BDP,
 604		.ctl_offs = SPM_BDP_PWR_CON,
 605		.sram_pdn_bits = GENMASK(11, 8),
 606		.clk_id = {CLK_NONE},
 607		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 608	},
 609	[MT2701_POWER_DOMAIN_ETH] = {
 610		.name = "eth",
 611		.sta_mask = PWR_STATUS_ETH,
 612		.ctl_offs = SPM_ETH_PWR_CON,
 613		.sram_pdn_bits = GENMASK(11, 8),
 614		.sram_pdn_ack_bits = GENMASK(15, 12),
 615		.clk_id = {CLK_ETHIF},
 616		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 617	},
 618	[MT2701_POWER_DOMAIN_HIF] = {
 619		.name = "hif",
 620		.sta_mask = PWR_STATUS_HIF,
 621		.ctl_offs = SPM_HIF_PWR_CON,
 622		.sram_pdn_bits = GENMASK(11, 8),
 623		.sram_pdn_ack_bits = GENMASK(15, 12),
 624		.clk_id = {CLK_ETHIF},
 625		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 626	},
 627	[MT2701_POWER_DOMAIN_IFR_MSC] = {
 628		.name = "ifr_msc",
 629		.sta_mask = PWR_STATUS_IFR_MSC,
 630		.ctl_offs = SPM_IFR_MSC_PWR_CON,
 631		.clk_id = {CLK_NONE},
 632		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 633	},
 634};
 635
 636/*
 637 * MT2712 power domain support
 638 */
 639static const struct scp_domain_data scp_domain_data_mt2712[] = {
 640	[MT2712_POWER_DOMAIN_MM] = {
 641		.name = "mm",
 642		.sta_mask = PWR_STATUS_DISP,
 643		.ctl_offs = SPM_DIS_PWR_CON,
 644		.sram_pdn_bits = GENMASK(8, 8),
 645		.sram_pdn_ack_bits = GENMASK(12, 12),
 646		.clk_id = {CLK_MM},
 647		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 648	},
 649	[MT2712_POWER_DOMAIN_VDEC] = {
 650		.name = "vdec",
 651		.sta_mask = PWR_STATUS_VDEC,
 652		.ctl_offs = SPM_VDE_PWR_CON,
 653		.sram_pdn_bits = GENMASK(8, 8),
 654		.sram_pdn_ack_bits = GENMASK(12, 12),
 655		.clk_id = {CLK_MM, CLK_VDEC},
 656		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 657	},
 658	[MT2712_POWER_DOMAIN_VENC] = {
 659		.name = "venc",
 660		.sta_mask = PWR_STATUS_VENC,
 661		.ctl_offs = SPM_VEN_PWR_CON,
 662		.sram_pdn_bits = GENMASK(11, 8),
 663		.sram_pdn_ack_bits = GENMASK(15, 12),
 664		.clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
 665		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 666	},
 667	[MT2712_POWER_DOMAIN_ISP] = {
 668		.name = "isp",
 669		.sta_mask = PWR_STATUS_ISP,
 670		.ctl_offs = SPM_ISP_PWR_CON,
 671		.sram_pdn_bits = GENMASK(11, 8),
 672		.sram_pdn_ack_bits = GENMASK(13, 12),
 673		.clk_id = {CLK_MM},
 674		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 675	},
 676	[MT2712_POWER_DOMAIN_AUDIO] = {
 677		.name = "audio",
 678		.sta_mask = PWR_STATUS_AUDIO,
 679		.ctl_offs = SPM_AUDIO_PWR_CON,
 680		.sram_pdn_bits = GENMASK(11, 8),
 681		.sram_pdn_ack_bits = GENMASK(15, 12),
 682		.clk_id = {CLK_AUDIO},
 683		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 684	},
 685	[MT2712_POWER_DOMAIN_USB] = {
 686		.name = "usb",
 687		.sta_mask = PWR_STATUS_USB,
 688		.ctl_offs = SPM_USB_PWR_CON,
 689		.sram_pdn_bits = GENMASK(10, 8),
 690		.sram_pdn_ack_bits = GENMASK(14, 12),
 691		.clk_id = {CLK_NONE},
 692		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 693	},
 694	[MT2712_POWER_DOMAIN_USB2] = {
 695		.name = "usb2",
 696		.sta_mask = PWR_STATUS_USB2,
 697		.ctl_offs = SPM_USB2_PWR_CON,
 698		.sram_pdn_bits = GENMASK(10, 8),
 699		.sram_pdn_ack_bits = GENMASK(14, 12),
 700		.clk_id = {CLK_NONE},
 701		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 702	},
 703	[MT2712_POWER_DOMAIN_MFG] = {
 704		.name = "mfg",
 705		.sta_mask = PWR_STATUS_MFG,
 706		.ctl_offs = SPM_MFG_PWR_CON,
 707		.sram_pdn_bits = GENMASK(8, 8),
 708		.sram_pdn_ack_bits = GENMASK(16, 16),
 709		.clk_id = {CLK_MFG},
 710		.bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
 711		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 712	},
 713	[MT2712_POWER_DOMAIN_MFG_SC1] = {
 714		.name = "mfg_sc1",
 715		.sta_mask = BIT(22),
 716		.ctl_offs = 0x02c0,
 717		.sram_pdn_bits = GENMASK(8, 8),
 718		.sram_pdn_ack_bits = GENMASK(16, 16),
 719		.clk_id = {CLK_NONE},
 720		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 721	},
 722	[MT2712_POWER_DOMAIN_MFG_SC2] = {
 723		.name = "mfg_sc2",
 724		.sta_mask = BIT(23),
 725		.ctl_offs = 0x02c4,
 726		.sram_pdn_bits = GENMASK(8, 8),
 727		.sram_pdn_ack_bits = GENMASK(16, 16),
 728		.clk_id = {CLK_NONE},
 729		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 730	},
 731	[MT2712_POWER_DOMAIN_MFG_SC3] = {
 732		.name = "mfg_sc3",
 733		.sta_mask = BIT(30),
 734		.ctl_offs = 0x01f8,
 735		.sram_pdn_bits = GENMASK(8, 8),
 736		.sram_pdn_ack_bits = GENMASK(16, 16),
 737		.clk_id = {CLK_NONE},
 738		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 739	},
 740};
 741
 742static const struct scp_subdomain scp_subdomain_mt2712[] = {
 743	{MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC},
 744	{MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC},
 745	{MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP},
 746	{MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1},
 747	{MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2},
 748	{MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3},
 749};
 750
 751/*
 752 * MT6797 power domain support
 753 */
 754
 755static const struct scp_domain_data scp_domain_data_mt6797[] = {
 756	[MT6797_POWER_DOMAIN_VDEC] = {
 757		.name = "vdec",
 758		.sta_mask = BIT(7),
 759		.ctl_offs = 0x300,
 760		.sram_pdn_bits = GENMASK(8, 8),
 761		.sram_pdn_ack_bits = GENMASK(12, 12),
 762		.clk_id = {CLK_VDEC},
 763	},
 764	[MT6797_POWER_DOMAIN_VENC] = {
 765		.name = "venc",
 766		.sta_mask = BIT(21),
 767		.ctl_offs = 0x304,
 768		.sram_pdn_bits = GENMASK(11, 8),
 769		.sram_pdn_ack_bits = GENMASK(15, 12),
 770		.clk_id = {CLK_NONE},
 771	},
 772	[MT6797_POWER_DOMAIN_ISP] = {
 773		.name = "isp",
 774		.sta_mask = BIT(5),
 775		.ctl_offs = 0x308,
 776		.sram_pdn_bits = GENMASK(9, 8),
 777		.sram_pdn_ack_bits = GENMASK(13, 12),
 778		.clk_id = {CLK_NONE},
 779	},
 780	[MT6797_POWER_DOMAIN_MM] = {
 781		.name = "mm",
 782		.sta_mask = BIT(3),
 783		.ctl_offs = 0x30C,
 784		.sram_pdn_bits = GENMASK(8, 8),
 785		.sram_pdn_ack_bits = GENMASK(12, 12),
 786		.clk_id = {CLK_MM},
 787		.bus_prot_mask = (BIT(1) | BIT(2)),
 788	},
 789	[MT6797_POWER_DOMAIN_AUDIO] = {
 790		.name = "audio",
 791		.sta_mask = BIT(24),
 792		.ctl_offs = 0x314,
 793		.sram_pdn_bits = GENMASK(11, 8),
 794		.sram_pdn_ack_bits = GENMASK(15, 12),
 795		.clk_id = {CLK_NONE},
 796	},
 797	[MT6797_POWER_DOMAIN_MFG_ASYNC] = {
 798		.name = "mfg_async",
 799		.sta_mask = BIT(13),
 800		.ctl_offs = 0x334,
 801		.sram_pdn_bits = 0,
 802		.sram_pdn_ack_bits = 0,
 803		.clk_id = {CLK_MFG},
 804	},
 805	[MT6797_POWER_DOMAIN_MJC] = {
 806		.name = "mjc",
 807		.sta_mask = BIT(20),
 808		.ctl_offs = 0x310,
 809		.sram_pdn_bits = GENMASK(8, 8),
 810		.sram_pdn_ack_bits = GENMASK(12, 12),
 811		.clk_id = {CLK_NONE},
 812	},
 813};
 814
 815#define SPM_PWR_STATUS_MT6797		0x0180
 816#define SPM_PWR_STATUS_2ND_MT6797	0x0184
 817
 818static const struct scp_subdomain scp_subdomain_mt6797[] = {
 819	{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
 820	{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
 821	{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
 822	{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
 823};
 824
 825/*
 826 * MT7622 power domain support
 827 */
 828
 829static const struct scp_domain_data scp_domain_data_mt7622[] = {
 830	[MT7622_POWER_DOMAIN_ETHSYS] = {
 831		.name = "ethsys",
 832		.sta_mask = PWR_STATUS_ETHSYS,
 833		.ctl_offs = SPM_ETHSYS_PWR_CON,
 834		.sram_pdn_bits = GENMASK(11, 8),
 835		.sram_pdn_ack_bits = GENMASK(15, 12),
 836		.clk_id = {CLK_NONE},
 837		.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
 838		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 839	},
 840	[MT7622_POWER_DOMAIN_HIF0] = {
 841		.name = "hif0",
 842		.sta_mask = PWR_STATUS_HIF0,
 843		.ctl_offs = SPM_HIF0_PWR_CON,
 844		.sram_pdn_bits = GENMASK(11, 8),
 845		.sram_pdn_ack_bits = GENMASK(15, 12),
 846		.clk_id = {CLK_HIFSEL},
 847		.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
 848		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 849	},
 850	[MT7622_POWER_DOMAIN_HIF1] = {
 851		.name = "hif1",
 852		.sta_mask = PWR_STATUS_HIF1,
 853		.ctl_offs = SPM_HIF1_PWR_CON,
 854		.sram_pdn_bits = GENMASK(11, 8),
 855		.sram_pdn_ack_bits = GENMASK(15, 12),
 856		.clk_id = {CLK_HIFSEL},
 857		.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
 858		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 859	},
 860	[MT7622_POWER_DOMAIN_WB] = {
 861		.name = "wb",
 862		.sta_mask = PWR_STATUS_WB,
 863		.ctl_offs = SPM_WB_PWR_CON,
 864		.sram_pdn_bits = 0,
 865		.sram_pdn_ack_bits = 0,
 866		.clk_id = {CLK_NONE},
 867		.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
 868		.caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
 869	},
 870};
 871
 872/*
 873 * MT7623A power domain support
 874 */
 875
 876static const struct scp_domain_data scp_domain_data_mt7623a[] = {
 877	[MT7623A_POWER_DOMAIN_CONN] = {
 878		.name = "conn",
 879		.sta_mask = PWR_STATUS_CONN,
 880		.ctl_offs = SPM_CONN_PWR_CON,
 881		.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
 882				 MT2701_TOP_AXI_PROT_EN_CONN_S,
 883		.clk_id = {CLK_NONE},
 884		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 885	},
 886	[MT7623A_POWER_DOMAIN_ETH] = {
 887		.name = "eth",
 888		.sta_mask = PWR_STATUS_ETH,
 889		.ctl_offs = SPM_ETH_PWR_CON,
 890		.sram_pdn_bits = GENMASK(11, 8),
 891		.sram_pdn_ack_bits = GENMASK(15, 12),
 892		.clk_id = {CLK_ETHIF},
 893		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 894	},
 895	[MT7623A_POWER_DOMAIN_HIF] = {
 896		.name = "hif",
 897		.sta_mask = PWR_STATUS_HIF,
 898		.ctl_offs = SPM_HIF_PWR_CON,
 899		.sram_pdn_bits = GENMASK(11, 8),
 900		.sram_pdn_ack_bits = GENMASK(15, 12),
 901		.clk_id = {CLK_ETHIF},
 902		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 903	},
 904	[MT7623A_POWER_DOMAIN_IFR_MSC] = {
 905		.name = "ifr_msc",
 906		.sta_mask = PWR_STATUS_IFR_MSC,
 907		.ctl_offs = SPM_IFR_MSC_PWR_CON,
 908		.clk_id = {CLK_NONE},
 909		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 910	},
 911};
 912
 913/*
 914 * MT8173 power domain support
 915 */
 916
 917static const struct scp_domain_data scp_domain_data_mt8173[] = {
 918	[MT8173_POWER_DOMAIN_VDEC] = {
 919		.name = "vdec",
 920		.sta_mask = PWR_STATUS_VDEC,
 921		.ctl_offs = SPM_VDE_PWR_CON,
 922		.sram_pdn_bits = GENMASK(11, 8),
 923		.sram_pdn_ack_bits = GENMASK(12, 12),
 924		.clk_id = {CLK_MM},
 925	},
 926	[MT8173_POWER_DOMAIN_VENC] = {
 927		.name = "venc",
 928		.sta_mask = PWR_STATUS_VENC,
 929		.ctl_offs = SPM_VEN_PWR_CON,
 930		.sram_pdn_bits = GENMASK(11, 8),
 931		.sram_pdn_ack_bits = GENMASK(15, 12),
 932		.clk_id = {CLK_MM, CLK_VENC},
 933	},
 934	[MT8173_POWER_DOMAIN_ISP] = {
 935		.name = "isp",
 936		.sta_mask = PWR_STATUS_ISP,
 937		.ctl_offs = SPM_ISP_PWR_CON,
 938		.sram_pdn_bits = GENMASK(11, 8),
 939		.sram_pdn_ack_bits = GENMASK(13, 12),
 940		.clk_id = {CLK_MM},
 941	},
 942	[MT8173_POWER_DOMAIN_MM] = {
 943		.name = "mm",
 944		.sta_mask = PWR_STATUS_DISP,
 945		.ctl_offs = SPM_DIS_PWR_CON,
 946		.sram_pdn_bits = GENMASK(11, 8),
 947		.sram_pdn_ack_bits = GENMASK(12, 12),
 948		.clk_id = {CLK_MM},
 949		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
 950			MT8173_TOP_AXI_PROT_EN_MM_M1,
 951	},
 952	[MT8173_POWER_DOMAIN_VENC_LT] = {
 953		.name = "venc_lt",
 954		.sta_mask = PWR_STATUS_VENC_LT,
 955		.ctl_offs = SPM_VEN2_PWR_CON,
 956		.sram_pdn_bits = GENMASK(11, 8),
 957		.sram_pdn_ack_bits = GENMASK(15, 12),
 958		.clk_id = {CLK_MM, CLK_VENC_LT},
 959	},
 960	[MT8173_POWER_DOMAIN_AUDIO] = {
 961		.name = "audio",
 962		.sta_mask = PWR_STATUS_AUDIO,
 963		.ctl_offs = SPM_AUDIO_PWR_CON,
 964		.sram_pdn_bits = GENMASK(11, 8),
 965		.sram_pdn_ack_bits = GENMASK(15, 12),
 966		.clk_id = {CLK_NONE},
 967	},
 968	[MT8173_POWER_DOMAIN_USB] = {
 969		.name = "usb",
 970		.sta_mask = PWR_STATUS_USB,
 971		.ctl_offs = SPM_USB_PWR_CON,
 972		.sram_pdn_bits = GENMASK(11, 8),
 973		.sram_pdn_ack_bits = GENMASK(15, 12),
 974		.clk_id = {CLK_NONE},
 975		.caps = MTK_SCPD_ACTIVE_WAKEUP,
 976	},
 977	[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
 978		.name = "mfg_async",
 979		.sta_mask = PWR_STATUS_MFG_ASYNC,
 980		.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
 981		.sram_pdn_bits = GENMASK(11, 8),
 982		.sram_pdn_ack_bits = 0,
 983		.clk_id = {CLK_MFG},
 984	},
 985	[MT8173_POWER_DOMAIN_MFG_2D] = {
 986		.name = "mfg_2d",
 987		.sta_mask = PWR_STATUS_MFG_2D,
 988		.ctl_offs = SPM_MFG_2D_PWR_CON,
 989		.sram_pdn_bits = GENMASK(11, 8),
 990		.sram_pdn_ack_bits = GENMASK(13, 12),
 991		.clk_id = {CLK_NONE},
 992	},
 993	[MT8173_POWER_DOMAIN_MFG] = {
 994		.name = "mfg",
 995		.sta_mask = PWR_STATUS_MFG,
 996		.ctl_offs = SPM_MFG_PWR_CON,
 997		.sram_pdn_bits = GENMASK(13, 8),
 998		.sram_pdn_ack_bits = GENMASK(21, 16),
 999		.clk_id = {CLK_NONE},
1000		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
1001			MT8173_TOP_AXI_PROT_EN_MFG_M0 |
1002			MT8173_TOP_AXI_PROT_EN_MFG_M1 |
1003			MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
1004	},
1005};
1006
1007static const struct scp_subdomain scp_subdomain_mt8173[] = {
1008	{MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
1009	{MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
1010};
1011
1012static const struct scp_soc_data mt2701_data = {
1013	.domains = scp_domain_data_mt2701,
1014	.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
1015	.regs = {
1016		.pwr_sta_offs = SPM_PWR_STATUS,
1017		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
1018	},
1019	.bus_prot_reg_update = true,
1020};
1021
1022static const struct scp_soc_data mt2712_data = {
1023	.domains = scp_domain_data_mt2712,
1024	.num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
1025	.subdomains = scp_subdomain_mt2712,
1026	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712),
1027	.regs = {
1028		.pwr_sta_offs = SPM_PWR_STATUS,
1029		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
1030	},
1031	.bus_prot_reg_update = false,
1032};
1033
1034static const struct scp_soc_data mt6797_data = {
1035	.domains = scp_domain_data_mt6797,
1036	.num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
1037	.subdomains = scp_subdomain_mt6797,
1038	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
1039	.regs = {
1040		.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
1041		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
1042	},
1043	.bus_prot_reg_update = true,
1044};
1045
1046static const struct scp_soc_data mt7622_data = {
1047	.domains = scp_domain_data_mt7622,
1048	.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
1049	.regs = {
1050		.pwr_sta_offs = SPM_PWR_STATUS,
1051		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
1052	},
1053	.bus_prot_reg_update = true,
1054};
1055
1056static const struct scp_soc_data mt7623a_data = {
1057	.domains = scp_domain_data_mt7623a,
1058	.num_domains = ARRAY_SIZE(scp_domain_data_mt7623a),
1059	.regs = {
1060		.pwr_sta_offs = SPM_PWR_STATUS,
1061		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
1062	},
1063	.bus_prot_reg_update = true,
1064};
1065
1066static const struct scp_soc_data mt8173_data = {
1067	.domains = scp_domain_data_mt8173,
1068	.num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
1069	.subdomains = scp_subdomain_mt8173,
1070	.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
1071	.regs = {
1072		.pwr_sta_offs = SPM_PWR_STATUS,
1073		.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
1074	},
1075	.bus_prot_reg_update = true,
1076};
1077
1078/*
1079 * scpsys driver init
1080 */
1081
1082static const struct of_device_id of_scpsys_match_tbl[] = {
1083	{
1084		.compatible = "mediatek,mt2701-scpsys",
1085		.data = &mt2701_data,
1086	}, {
1087		.compatible = "mediatek,mt2712-scpsys",
1088		.data = &mt2712_data,
1089	}, {
1090		.compatible = "mediatek,mt6797-scpsys",
1091		.data = &mt6797_data,
1092	}, {
1093		.compatible = "mediatek,mt7622-scpsys",
1094		.data = &mt7622_data,
1095	}, {
1096		.compatible = "mediatek,mt7623a-scpsys",
1097		.data = &mt7623a_data,
1098	}, {
1099		.compatible = "mediatek,mt8173-scpsys",
1100		.data = &mt8173_data,
1101	}, {
1102		/* sentinel */
1103	}
1104};
1105
1106static int scpsys_probe(struct platform_device *pdev)
1107{
1108	const struct scp_subdomain *sd;
1109	const struct scp_soc_data *soc;
1110	struct scp *scp;
1111	struct genpd_onecell_data *pd_data;
1112	int i, ret;
1113
1114	soc = of_device_get_match_data(&pdev->dev);
1115
1116	scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
1117			soc->bus_prot_reg_update);
1118	if (IS_ERR(scp))
1119		return PTR_ERR(scp);
1120
1121	mtk_register_power_domains(pdev, scp, soc->num_domains);
1122
1123	pd_data = &scp->pd_data;
1124
1125	for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
1126		ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
1127					     pd_data->domains[sd->subdomain]);
1128		if (ret && IS_ENABLED(CONFIG_PM))
1129			dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
1130				ret);
1131	}
1132
1133	return 0;
1134}
1135
1136static struct platform_driver scpsys_drv = {
1137	.probe = scpsys_probe,
1138	.driver = {
1139		.name = "mtk-scpsys",
1140		.suppress_bind_attrs = true,
1141		.of_match_table = of_scpsys_match_tbl,
1142	},
1143};
1144builtin_platform_driver(scpsys_drv);
~/ Read-only file preview.