brintos

brintos / linux-shallow public Read only

0
0
Text · 28.2 KiB · 1a80c15 Raw
1145 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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   1024#define MTK_POLL_TIMEOUT    USEC_PER_SEC25 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			0x021031#define SPM_MFG_PWR_CON			0x021432#define SPM_VEN_PWR_CON			0x023033#define SPM_ISP_PWR_CON			0x023834#define SPM_DIS_PWR_CON			0x023c35#define SPM_CONN_PWR_CON		0x028036#define SPM_VEN2_PWR_CON		0x029837#define SPM_AUDIO_PWR_CON		0x029c	/* MT8173, MT2712 */38#define SPM_BDP_PWR_CON			0x029c	/* MT2701 */39#define SPM_ETH_PWR_CON			0x02a040#define SPM_HIF_PWR_CON			0x02a441#define SPM_IFR_MSC_PWR_CON		0x02a842#define SPM_MFG_2D_PWR_CON		0x02c043#define SPM_MFG_ASYNC_PWR_CON		0x02c444#define SPM_USB_PWR_CON			0x02cc45#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			0x060c52#define SPM_PWR_STATUS_2ND		0x061053 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	3110 111/**112 * struct scp_domain_data - scp domain data for power on/off flow113 * @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 set183	 * return an error. This happens while powering up a domain184	 */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 for247		 * MT7622_POWER_DOMAIN_WB and thus just a trivial setup248		 * 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			else476				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 usable529		 * with !CONFIG_PM and to get the hardware in sync with the530		 * software.  The unused domains will be switched off during531		 * 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 unregister540	 * a power domain. Once registered above we have to keep the domains541	 * 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 support553 */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 support638 */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 support753 */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		0x0180816#define SPM_PWR_STATUS_2ND_MT6797	0x0184817 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 support827 */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 support874 */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 support915 */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_2ND1018	},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_2ND1030	},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_MT67971042	},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_2ND1052	},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_2ND1062	},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_2ND1074	},1075	.bus_prot_reg_update = true,1076};1077 1078/*1079 * scpsys driver init1080 */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);1145