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