1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
6 #include <linux/init.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>
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>
23 #define MTK_POLL_DELAY_US 10
24 #define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ))
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))
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 */
51 #define SPM_PWR_STATUS 0x060c
52 #define SPM_PWR_STATUS_2ND 0x0610
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)
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 */
95 static const char * const clk_names[] = {
111 struct scp_domain_data {
116 u32 sram_pdn_ack_bits;
118 enum clk_id clk_id[MAX_CLKS];
125 struct generic_pm_domain genpd;
127 struct clk *clk[MAX_CLKS];
128 const struct scp_domain_data *data;
129 struct regulator *supply;
132 struct scp_ctrl_reg {
138 struct scp_domain *domains;
139 struct genpd_onecell_data pd_data;
142 struct regmap *infracfg;
143 struct scp_ctrl_reg ctrl_reg;
144 bool bus_prot_reg_update;
147 struct scp_subdomain {
152 struct scp_soc_data {
153 const struct scp_domain_data *domains;
155 const struct scp_subdomain *subdomains;
157 const struct scp_ctrl_reg regs;
158 bool bus_prot_reg_update;
161 static int scpsys_domain_is_on(struct scp_domain *scpd)
163 struct scp *scp = scpd->scp;
165 u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
166 scpd->data->sta_mask;
167 u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
168 scpd->data->sta_mask;
171 * A domain is on when both status bits are set. If only one is set
172 * return an error. This happens while powering up a domain
175 if (status && status2)
177 if (!status && !status2)
183 static int scpsys_power_on(struct generic_pm_domain *genpd)
185 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
186 struct scp *scp = scpd->scp;
187 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
188 u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
194 ret = regulator_enable(scpd->supply);
199 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
200 ret = clk_prepare_enable(scpd->clk[i]);
202 for (--i; i >= 0; i--)
203 clk_disable_unprepare(scpd->clk[i]);
209 val = readl(ctl_addr);
211 writel(val, ctl_addr);
212 val |= PWR_ON_2ND_BIT;
213 writel(val, ctl_addr);
215 /* wait until PWR_ACK = 1 */
216 ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
217 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
221 val &= ~PWR_CLK_DIS_BIT;
222 writel(val, ctl_addr);
225 writel(val, ctl_addr);
227 val |= PWR_RST_B_BIT;
228 writel(val, ctl_addr);
230 val &= ~scpd->data->sram_pdn_bits;
231 writel(val, ctl_addr);
233 /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
234 if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
236 * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
237 * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is
240 usleep_range(12000, 12100);
243 ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
244 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
249 if (scpd->data->bus_prot_mask) {
250 ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
251 scpd->data->bus_prot_mask,
252 scp->bus_prot_reg_update);
260 for (i = MAX_CLKS - 1; i >= 0; i--) {
262 clk_disable_unprepare(scpd->clk[i]);
266 regulator_disable(scpd->supply);
268 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
273 static int scpsys_power_off(struct generic_pm_domain *genpd)
275 struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
276 struct scp *scp = scpd->scp;
277 void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
278 u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
283 if (scpd->data->bus_prot_mask) {
284 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
285 scpd->data->bus_prot_mask,
286 scp->bus_prot_reg_update);
291 val = readl(ctl_addr);
292 val |= scpd->data->sram_pdn_bits;
293 writel(val, ctl_addr);
295 /* wait until SRAM_PDN_ACK all 1 */
296 ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
297 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
302 writel(val, ctl_addr);
304 val &= ~PWR_RST_B_BIT;
305 writel(val, ctl_addr);
307 val |= PWR_CLK_DIS_BIT;
308 writel(val, ctl_addr);
311 writel(val, ctl_addr);
313 val &= ~PWR_ON_2ND_BIT;
314 writel(val, ctl_addr);
316 /* wait until PWR_ACK = 0 */
317 ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
318 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
322 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
323 clk_disable_unprepare(scpd->clk[i]);
326 regulator_disable(scpd->supply);
331 dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
336 static void init_clks(struct platform_device *pdev, struct clk **clk)
340 for (i = CLK_NONE + 1; i < CLK_MAX; i++)
341 clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
344 static struct scp *init_scp(struct platform_device *pdev,
345 const struct scp_domain_data *scp_domain_data, int num,
346 const struct scp_ctrl_reg *scp_ctrl_reg,
347 bool bus_prot_reg_update)
349 struct genpd_onecell_data *pd_data;
350 struct resource *res;
353 struct clk *clk[CLK_MAX];
355 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
357 return ERR_PTR(-ENOMEM);
359 scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
360 scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
362 scp->bus_prot_reg_update = bus_prot_reg_update;
364 scp->dev = &pdev->dev;
366 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
367 scp->base = devm_ioremap_resource(&pdev->dev, res);
368 if (IS_ERR(scp->base))
369 return ERR_CAST(scp->base);
371 scp->domains = devm_kcalloc(&pdev->dev,
372 num, sizeof(*scp->domains), GFP_KERNEL);
374 return ERR_PTR(-ENOMEM);
376 pd_data = &scp->pd_data;
378 pd_data->domains = devm_kcalloc(&pdev->dev,
379 num, sizeof(*pd_data->domains), GFP_KERNEL);
380 if (!pd_data->domains)
381 return ERR_PTR(-ENOMEM);
383 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
385 if (IS_ERR(scp->infracfg)) {
386 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
387 PTR_ERR(scp->infracfg));
388 return ERR_CAST(scp->infracfg);
391 for (i = 0; i < num; i++) {
392 struct scp_domain *scpd = &scp->domains[i];
393 const struct scp_domain_data *data = &scp_domain_data[i];
395 scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
396 if (IS_ERR(scpd->supply)) {
397 if (PTR_ERR(scpd->supply) == -ENODEV)
400 return ERR_CAST(scpd->supply);
404 pd_data->num_domains = num;
406 init_clks(pdev, clk);
408 for (i = 0; i < num; i++) {
409 struct scp_domain *scpd = &scp->domains[i];
410 struct generic_pm_domain *genpd = &scpd->genpd;
411 const struct scp_domain_data *data = &scp_domain_data[i];
413 pd_data->domains[i] = genpd;
418 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
419 struct clk *c = clk[data->clk_id[j]];
422 dev_err(&pdev->dev, "%s: clk unavailable\n",
430 genpd->name = data->name;
431 genpd->power_off = scpsys_power_off;
432 genpd->power_on = scpsys_power_on;
433 if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
434 genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
440 static void mtk_register_power_domains(struct platform_device *pdev,
441 struct scp *scp, int num)
443 struct genpd_onecell_data *pd_data;
446 for (i = 0; i < num; i++) {
447 struct scp_domain *scpd = &scp->domains[i];
448 struct generic_pm_domain *genpd = &scpd->genpd;
451 * Initially turn on all domains to make the domains usable
452 * with !CONFIG_PM and to get the hardware in sync with the
453 * software. The unused domains will be switched off during
456 genpd->power_on(genpd);
458 pm_genpd_init(genpd, NULL, false);
462 * We are not allowed to fail here since there is no way to unregister
463 * a power domain. Once registered above we have to keep the domains
467 pd_data = &scp->pd_data;
469 ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
471 dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
475 * MT2701 power domain support
478 static const struct scp_domain_data scp_domain_data_mt2701[] = {
479 [MT2701_POWER_DOMAIN_CONN] = {
481 .sta_mask = PWR_STATUS_CONN,
482 .ctl_offs = SPM_CONN_PWR_CON,
483 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
484 MT2701_TOP_AXI_PROT_EN_CONN_S,
485 .clk_id = {CLK_NONE},
486 .caps = MTK_SCPD_ACTIVE_WAKEUP,
488 [MT2701_POWER_DOMAIN_DISP] = {
490 .sta_mask = PWR_STATUS_DISP,
491 .ctl_offs = SPM_DIS_PWR_CON,
492 .sram_pdn_bits = GENMASK(11, 8),
494 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
495 .caps = MTK_SCPD_ACTIVE_WAKEUP,
497 [MT2701_POWER_DOMAIN_MFG] = {
499 .sta_mask = PWR_STATUS_MFG,
500 .ctl_offs = SPM_MFG_PWR_CON,
501 .sram_pdn_bits = GENMASK(11, 8),
502 .sram_pdn_ack_bits = GENMASK(12, 12),
504 .caps = MTK_SCPD_ACTIVE_WAKEUP,
506 [MT2701_POWER_DOMAIN_VDEC] = {
508 .sta_mask = PWR_STATUS_VDEC,
509 .ctl_offs = SPM_VDE_PWR_CON,
510 .sram_pdn_bits = GENMASK(11, 8),
511 .sram_pdn_ack_bits = GENMASK(12, 12),
513 .caps = MTK_SCPD_ACTIVE_WAKEUP,
515 [MT2701_POWER_DOMAIN_ISP] = {
517 .sta_mask = PWR_STATUS_ISP,
518 .ctl_offs = SPM_ISP_PWR_CON,
519 .sram_pdn_bits = GENMASK(11, 8),
520 .sram_pdn_ack_bits = GENMASK(13, 12),
522 .caps = MTK_SCPD_ACTIVE_WAKEUP,
524 [MT2701_POWER_DOMAIN_BDP] = {
526 .sta_mask = PWR_STATUS_BDP,
527 .ctl_offs = SPM_BDP_PWR_CON,
528 .sram_pdn_bits = GENMASK(11, 8),
529 .clk_id = {CLK_NONE},
530 .caps = MTK_SCPD_ACTIVE_WAKEUP,
532 [MT2701_POWER_DOMAIN_ETH] = {
534 .sta_mask = PWR_STATUS_ETH,
535 .ctl_offs = SPM_ETH_PWR_CON,
536 .sram_pdn_bits = GENMASK(11, 8),
537 .sram_pdn_ack_bits = GENMASK(15, 12),
538 .clk_id = {CLK_ETHIF},
539 .caps = MTK_SCPD_ACTIVE_WAKEUP,
541 [MT2701_POWER_DOMAIN_HIF] = {
543 .sta_mask = PWR_STATUS_HIF,
544 .ctl_offs = SPM_HIF_PWR_CON,
545 .sram_pdn_bits = GENMASK(11, 8),
546 .sram_pdn_ack_bits = GENMASK(15, 12),
547 .clk_id = {CLK_ETHIF},
548 .caps = MTK_SCPD_ACTIVE_WAKEUP,
550 [MT2701_POWER_DOMAIN_IFR_MSC] = {
552 .sta_mask = PWR_STATUS_IFR_MSC,
553 .ctl_offs = SPM_IFR_MSC_PWR_CON,
554 .clk_id = {CLK_NONE},
555 .caps = MTK_SCPD_ACTIVE_WAKEUP,
560 * MT2712 power domain support
562 static const struct scp_domain_data scp_domain_data_mt2712[] = {
563 [MT2712_POWER_DOMAIN_MM] = {
565 .sta_mask = PWR_STATUS_DISP,
566 .ctl_offs = SPM_DIS_PWR_CON,
567 .sram_pdn_bits = GENMASK(8, 8),
568 .sram_pdn_ack_bits = GENMASK(12, 12),
570 .caps = MTK_SCPD_ACTIVE_WAKEUP,
572 [MT2712_POWER_DOMAIN_VDEC] = {
574 .sta_mask = PWR_STATUS_VDEC,
575 .ctl_offs = SPM_VDE_PWR_CON,
576 .sram_pdn_bits = GENMASK(8, 8),
577 .sram_pdn_ack_bits = GENMASK(12, 12),
578 .clk_id = {CLK_MM, CLK_VDEC},
579 .caps = MTK_SCPD_ACTIVE_WAKEUP,
581 [MT2712_POWER_DOMAIN_VENC] = {
583 .sta_mask = PWR_STATUS_VENC,
584 .ctl_offs = SPM_VEN_PWR_CON,
585 .sram_pdn_bits = GENMASK(11, 8),
586 .sram_pdn_ack_bits = GENMASK(15, 12),
587 .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
588 .caps = MTK_SCPD_ACTIVE_WAKEUP,
590 [MT2712_POWER_DOMAIN_ISP] = {
592 .sta_mask = PWR_STATUS_ISP,
593 .ctl_offs = SPM_ISP_PWR_CON,
594 .sram_pdn_bits = GENMASK(11, 8),
595 .sram_pdn_ack_bits = GENMASK(13, 12),
597 .caps = MTK_SCPD_ACTIVE_WAKEUP,
599 [MT2712_POWER_DOMAIN_AUDIO] = {
601 .sta_mask = PWR_STATUS_AUDIO,
602 .ctl_offs = SPM_AUDIO_PWR_CON,
603 .sram_pdn_bits = GENMASK(11, 8),
604 .sram_pdn_ack_bits = GENMASK(15, 12),
605 .clk_id = {CLK_AUDIO},
606 .caps = MTK_SCPD_ACTIVE_WAKEUP,
608 [MT2712_POWER_DOMAIN_USB] = {
610 .sta_mask = PWR_STATUS_USB,
611 .ctl_offs = SPM_USB_PWR_CON,
612 .sram_pdn_bits = GENMASK(10, 8),
613 .sram_pdn_ack_bits = GENMASK(14, 12),
614 .clk_id = {CLK_NONE},
615 .caps = MTK_SCPD_ACTIVE_WAKEUP,
617 [MT2712_POWER_DOMAIN_USB2] = {
619 .sta_mask = PWR_STATUS_USB2,
620 .ctl_offs = SPM_USB2_PWR_CON,
621 .sram_pdn_bits = GENMASK(10, 8),
622 .sram_pdn_ack_bits = GENMASK(14, 12),
623 .clk_id = {CLK_NONE},
624 .caps = MTK_SCPD_ACTIVE_WAKEUP,
626 [MT2712_POWER_DOMAIN_MFG] = {
628 .sta_mask = PWR_STATUS_MFG,
629 .ctl_offs = SPM_MFG_PWR_CON,
630 .sram_pdn_bits = GENMASK(8, 8),
631 .sram_pdn_ack_bits = GENMASK(16, 16),
633 .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
634 .caps = MTK_SCPD_ACTIVE_WAKEUP,
636 [MT2712_POWER_DOMAIN_MFG_SC1] = {
640 .sram_pdn_bits = GENMASK(8, 8),
641 .sram_pdn_ack_bits = GENMASK(16, 16),
642 .clk_id = {CLK_NONE},
643 .caps = MTK_SCPD_ACTIVE_WAKEUP,
645 [MT2712_POWER_DOMAIN_MFG_SC2] = {
649 .sram_pdn_bits = GENMASK(8, 8),
650 .sram_pdn_ack_bits = GENMASK(16, 16),
651 .clk_id = {CLK_NONE},
652 .caps = MTK_SCPD_ACTIVE_WAKEUP,
654 [MT2712_POWER_DOMAIN_MFG_SC3] = {
658 .sram_pdn_bits = GENMASK(8, 8),
659 .sram_pdn_ack_bits = GENMASK(16, 16),
660 .clk_id = {CLK_NONE},
661 .caps = MTK_SCPD_ACTIVE_WAKEUP,
665 static const struct scp_subdomain scp_subdomain_mt2712[] = {
666 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC},
667 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC},
668 {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP},
669 {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1},
670 {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2},
671 {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3},
675 * MT6797 power domain support
678 static const struct scp_domain_data scp_domain_data_mt6797[] = {
679 [MT6797_POWER_DOMAIN_VDEC] = {
683 .sram_pdn_bits = GENMASK(8, 8),
684 .sram_pdn_ack_bits = GENMASK(12, 12),
685 .clk_id = {CLK_VDEC},
687 [MT6797_POWER_DOMAIN_VENC] = {
691 .sram_pdn_bits = GENMASK(11, 8),
692 .sram_pdn_ack_bits = GENMASK(15, 12),
693 .clk_id = {CLK_NONE},
695 [MT6797_POWER_DOMAIN_ISP] = {
699 .sram_pdn_bits = GENMASK(9, 8),
700 .sram_pdn_ack_bits = GENMASK(13, 12),
701 .clk_id = {CLK_NONE},
703 [MT6797_POWER_DOMAIN_MM] = {
707 .sram_pdn_bits = GENMASK(8, 8),
708 .sram_pdn_ack_bits = GENMASK(12, 12),
710 .bus_prot_mask = (BIT(1) | BIT(2)),
712 [MT6797_POWER_DOMAIN_AUDIO] = {
716 .sram_pdn_bits = GENMASK(11, 8),
717 .sram_pdn_ack_bits = GENMASK(15, 12),
718 .clk_id = {CLK_NONE},
720 [MT6797_POWER_DOMAIN_MFG_ASYNC] = {
725 .sram_pdn_ack_bits = 0,
728 [MT6797_POWER_DOMAIN_MJC] = {
732 .sram_pdn_bits = GENMASK(8, 8),
733 .sram_pdn_ack_bits = GENMASK(12, 12),
734 .clk_id = {CLK_NONE},
738 #define SPM_PWR_STATUS_MT6797 0x0180
739 #define SPM_PWR_STATUS_2ND_MT6797 0x0184
741 static const struct scp_subdomain scp_subdomain_mt6797[] = {
742 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
743 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
744 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
745 {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
749 * MT7622 power domain support
752 static const struct scp_domain_data scp_domain_data_mt7622[] = {
753 [MT7622_POWER_DOMAIN_ETHSYS] = {
755 .sta_mask = PWR_STATUS_ETHSYS,
756 .ctl_offs = SPM_ETHSYS_PWR_CON,
757 .sram_pdn_bits = GENMASK(11, 8),
758 .sram_pdn_ack_bits = GENMASK(15, 12),
759 .clk_id = {CLK_NONE},
760 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
761 .caps = MTK_SCPD_ACTIVE_WAKEUP,
763 [MT7622_POWER_DOMAIN_HIF0] = {
765 .sta_mask = PWR_STATUS_HIF0,
766 .ctl_offs = SPM_HIF0_PWR_CON,
767 .sram_pdn_bits = GENMASK(11, 8),
768 .sram_pdn_ack_bits = GENMASK(15, 12),
769 .clk_id = {CLK_HIFSEL},
770 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
771 .caps = MTK_SCPD_ACTIVE_WAKEUP,
773 [MT7622_POWER_DOMAIN_HIF1] = {
775 .sta_mask = PWR_STATUS_HIF1,
776 .ctl_offs = SPM_HIF1_PWR_CON,
777 .sram_pdn_bits = GENMASK(11, 8),
778 .sram_pdn_ack_bits = GENMASK(15, 12),
779 .clk_id = {CLK_HIFSEL},
780 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
781 .caps = MTK_SCPD_ACTIVE_WAKEUP,
783 [MT7622_POWER_DOMAIN_WB] = {
785 .sta_mask = PWR_STATUS_WB,
786 .ctl_offs = SPM_WB_PWR_CON,
788 .sram_pdn_ack_bits = 0,
789 .clk_id = {CLK_NONE},
790 .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
791 .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
796 * MT7623A power domain support
799 static const struct scp_domain_data scp_domain_data_mt7623a[] = {
800 [MT7623A_POWER_DOMAIN_CONN] = {
802 .sta_mask = PWR_STATUS_CONN,
803 .ctl_offs = SPM_CONN_PWR_CON,
804 .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
805 MT2701_TOP_AXI_PROT_EN_CONN_S,
806 .clk_id = {CLK_NONE},
807 .caps = MTK_SCPD_ACTIVE_WAKEUP,
809 [MT7623A_POWER_DOMAIN_ETH] = {
811 .sta_mask = PWR_STATUS_ETH,
812 .ctl_offs = SPM_ETH_PWR_CON,
813 .sram_pdn_bits = GENMASK(11, 8),
814 .sram_pdn_ack_bits = GENMASK(15, 12),
815 .clk_id = {CLK_ETHIF},
816 .caps = MTK_SCPD_ACTIVE_WAKEUP,
818 [MT7623A_POWER_DOMAIN_HIF] = {
820 .sta_mask = PWR_STATUS_HIF,
821 .ctl_offs = SPM_HIF_PWR_CON,
822 .sram_pdn_bits = GENMASK(11, 8),
823 .sram_pdn_ack_bits = GENMASK(15, 12),
824 .clk_id = {CLK_ETHIF},
825 .caps = MTK_SCPD_ACTIVE_WAKEUP,
827 [MT7623A_POWER_DOMAIN_IFR_MSC] = {
829 .sta_mask = PWR_STATUS_IFR_MSC,
830 .ctl_offs = SPM_IFR_MSC_PWR_CON,
831 .clk_id = {CLK_NONE},
832 .caps = MTK_SCPD_ACTIVE_WAKEUP,
837 * MT8173 power domain support
840 static const struct scp_domain_data scp_domain_data_mt8173[] = {
841 [MT8173_POWER_DOMAIN_VDEC] = {
843 .sta_mask = PWR_STATUS_VDEC,
844 .ctl_offs = SPM_VDE_PWR_CON,
845 .sram_pdn_bits = GENMASK(11, 8),
846 .sram_pdn_ack_bits = GENMASK(12, 12),
849 [MT8173_POWER_DOMAIN_VENC] = {
851 .sta_mask = PWR_STATUS_VENC,
852 .ctl_offs = SPM_VEN_PWR_CON,
853 .sram_pdn_bits = GENMASK(11, 8),
854 .sram_pdn_ack_bits = GENMASK(15, 12),
855 .clk_id = {CLK_MM, CLK_VENC},
857 [MT8173_POWER_DOMAIN_ISP] = {
859 .sta_mask = PWR_STATUS_ISP,
860 .ctl_offs = SPM_ISP_PWR_CON,
861 .sram_pdn_bits = GENMASK(11, 8),
862 .sram_pdn_ack_bits = GENMASK(13, 12),
865 [MT8173_POWER_DOMAIN_MM] = {
867 .sta_mask = PWR_STATUS_DISP,
868 .ctl_offs = SPM_DIS_PWR_CON,
869 .sram_pdn_bits = GENMASK(11, 8),
870 .sram_pdn_ack_bits = GENMASK(12, 12),
872 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
873 MT8173_TOP_AXI_PROT_EN_MM_M1,
875 [MT8173_POWER_DOMAIN_VENC_LT] = {
877 .sta_mask = PWR_STATUS_VENC_LT,
878 .ctl_offs = SPM_VEN2_PWR_CON,
879 .sram_pdn_bits = GENMASK(11, 8),
880 .sram_pdn_ack_bits = GENMASK(15, 12),
881 .clk_id = {CLK_MM, CLK_VENC_LT},
883 [MT8173_POWER_DOMAIN_AUDIO] = {
885 .sta_mask = PWR_STATUS_AUDIO,
886 .ctl_offs = SPM_AUDIO_PWR_CON,
887 .sram_pdn_bits = GENMASK(11, 8),
888 .sram_pdn_ack_bits = GENMASK(15, 12),
889 .clk_id = {CLK_NONE},
891 [MT8173_POWER_DOMAIN_USB] = {
893 .sta_mask = PWR_STATUS_USB,
894 .ctl_offs = SPM_USB_PWR_CON,
895 .sram_pdn_bits = GENMASK(11, 8),
896 .sram_pdn_ack_bits = GENMASK(15, 12),
897 .clk_id = {CLK_NONE},
898 .caps = MTK_SCPD_ACTIVE_WAKEUP,
900 [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
902 .sta_mask = PWR_STATUS_MFG_ASYNC,
903 .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
904 .sram_pdn_bits = GENMASK(11, 8),
905 .sram_pdn_ack_bits = 0,
908 [MT8173_POWER_DOMAIN_MFG_2D] = {
910 .sta_mask = PWR_STATUS_MFG_2D,
911 .ctl_offs = SPM_MFG_2D_PWR_CON,
912 .sram_pdn_bits = GENMASK(11, 8),
913 .sram_pdn_ack_bits = GENMASK(13, 12),
914 .clk_id = {CLK_NONE},
916 [MT8173_POWER_DOMAIN_MFG] = {
918 .sta_mask = PWR_STATUS_MFG,
919 .ctl_offs = SPM_MFG_PWR_CON,
920 .sram_pdn_bits = GENMASK(13, 8),
921 .sram_pdn_ack_bits = GENMASK(21, 16),
922 .clk_id = {CLK_NONE},
923 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
924 MT8173_TOP_AXI_PROT_EN_MFG_M0 |
925 MT8173_TOP_AXI_PROT_EN_MFG_M1 |
926 MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
930 static const struct scp_subdomain scp_subdomain_mt8173[] = {
931 {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
932 {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
935 static const struct scp_soc_data mt2701_data = {
936 .domains = scp_domain_data_mt2701,
937 .num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
939 .pwr_sta_offs = SPM_PWR_STATUS,
940 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
942 .bus_prot_reg_update = true,
945 static const struct scp_soc_data mt2712_data = {
946 .domains = scp_domain_data_mt2712,
947 .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
948 .subdomains = scp_subdomain_mt2712,
949 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712),
951 .pwr_sta_offs = SPM_PWR_STATUS,
952 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
954 .bus_prot_reg_update = false,
957 static const struct scp_soc_data mt6797_data = {
958 .domains = scp_domain_data_mt6797,
959 .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
960 .subdomains = scp_subdomain_mt6797,
961 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
963 .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
964 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
966 .bus_prot_reg_update = true,
969 static const struct scp_soc_data mt7622_data = {
970 .domains = scp_domain_data_mt7622,
971 .num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
973 .pwr_sta_offs = SPM_PWR_STATUS,
974 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
976 .bus_prot_reg_update = true,
979 static const struct scp_soc_data mt7623a_data = {
980 .domains = scp_domain_data_mt7623a,
981 .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a),
983 .pwr_sta_offs = SPM_PWR_STATUS,
984 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
986 .bus_prot_reg_update = true,
989 static const struct scp_soc_data mt8173_data = {
990 .domains = scp_domain_data_mt8173,
991 .num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
992 .subdomains = scp_subdomain_mt8173,
993 .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
995 .pwr_sta_offs = SPM_PWR_STATUS,
996 .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
998 .bus_prot_reg_update = true,
1002 * scpsys driver init
1005 static const struct of_device_id of_scpsys_match_tbl[] = {
1007 .compatible = "mediatek,mt2701-scpsys",
1008 .data = &mt2701_data,
1010 .compatible = "mediatek,mt2712-scpsys",
1011 .data = &mt2712_data,
1013 .compatible = "mediatek,mt6797-scpsys",
1014 .data = &mt6797_data,
1016 .compatible = "mediatek,mt7622-scpsys",
1017 .data = &mt7622_data,
1019 .compatible = "mediatek,mt7623a-scpsys",
1020 .data = &mt7623a_data,
1022 .compatible = "mediatek,mt8173-scpsys",
1023 .data = &mt8173_data,
1029 static int scpsys_probe(struct platform_device *pdev)
1031 const struct scp_subdomain *sd;
1032 const struct scp_soc_data *soc;
1034 struct genpd_onecell_data *pd_data;
1037 soc = of_device_get_match_data(&pdev->dev);
1039 scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
1040 soc->bus_prot_reg_update);
1042 return PTR_ERR(scp);
1044 mtk_register_power_domains(pdev, scp, soc->num_domains);
1046 pd_data = &scp->pd_data;
1048 for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
1049 ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
1050 pd_data->domains[sd->subdomain]);
1051 if (ret && IS_ENABLED(CONFIG_PM))
1052 dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
1059 static struct platform_driver scpsys_drv = {
1060 .probe = scpsys_probe,
1062 .name = "mtk-scpsys",
1063 .suppress_bind_attrs = true,
1064 .owner = THIS_MODULE,
1065 .of_match_table = of_match_ptr(of_scpsys_match_tbl),
1068 builtin_platform_driver(scpsys_drv);