18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/clk.h> 68c2ecf20Sopenharmony_ci#include <linux/init.h> 78c2ecf20Sopenharmony_ci#include <linux/io.h> 88c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 98c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 108c2ecf20Sopenharmony_ci#include <linux/of_device.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/pm_domain.h> 138c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 148c2ecf20Sopenharmony_ci#include <linux/soc/mediatek/infracfg.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt2701-power.h> 178c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt2712-power.h> 188c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt6797-power.h> 198c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt7622-power.h> 208c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt7623a-power.h> 218c2ecf20Sopenharmony_ci#include <dt-bindings/power/mt8173-power.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define MTK_POLL_DELAY_US 10 248c2ecf20Sopenharmony_ci#define MTK_POLL_TIMEOUT USEC_PER_SEC 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define MTK_SCPD_ACTIVE_WAKEUP BIT(0) 278c2ecf20Sopenharmony_ci#define MTK_SCPD_FWAIT_SRAM BIT(1) 288c2ecf20Sopenharmony_ci#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define SPM_VDE_PWR_CON 0x0210 318c2ecf20Sopenharmony_ci#define SPM_MFG_PWR_CON 0x0214 328c2ecf20Sopenharmony_ci#define SPM_VEN_PWR_CON 0x0230 338c2ecf20Sopenharmony_ci#define SPM_ISP_PWR_CON 0x0238 348c2ecf20Sopenharmony_ci#define SPM_DIS_PWR_CON 0x023c 358c2ecf20Sopenharmony_ci#define SPM_CONN_PWR_CON 0x0280 368c2ecf20Sopenharmony_ci#define SPM_VEN2_PWR_CON 0x0298 378c2ecf20Sopenharmony_ci#define SPM_AUDIO_PWR_CON 0x029c /* MT8173, MT2712 */ 388c2ecf20Sopenharmony_ci#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ 398c2ecf20Sopenharmony_ci#define SPM_ETH_PWR_CON 0x02a0 408c2ecf20Sopenharmony_ci#define SPM_HIF_PWR_CON 0x02a4 418c2ecf20Sopenharmony_ci#define SPM_IFR_MSC_PWR_CON 0x02a8 428c2ecf20Sopenharmony_ci#define SPM_MFG_2D_PWR_CON 0x02c0 438c2ecf20Sopenharmony_ci#define SPM_MFG_ASYNC_PWR_CON 0x02c4 448c2ecf20Sopenharmony_ci#define SPM_USB_PWR_CON 0x02cc 458c2ecf20Sopenharmony_ci#define SPM_USB2_PWR_CON 0x02d4 /* MT2712 */ 468c2ecf20Sopenharmony_ci#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */ 478c2ecf20Sopenharmony_ci#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */ 488c2ecf20Sopenharmony_ci#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */ 498c2ecf20Sopenharmony_ci#define SPM_WB_PWR_CON 0x02ec /* MT7622 */ 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define SPM_PWR_STATUS 0x060c 528c2ecf20Sopenharmony_ci#define SPM_PWR_STATUS_2ND 0x0610 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define PWR_RST_B_BIT BIT(0) 558c2ecf20Sopenharmony_ci#define PWR_ISO_BIT BIT(1) 568c2ecf20Sopenharmony_ci#define PWR_ON_BIT BIT(2) 578c2ecf20Sopenharmony_ci#define PWR_ON_2ND_BIT BIT(3) 588c2ecf20Sopenharmony_ci#define PWR_CLK_DIS_BIT BIT(4) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define PWR_STATUS_CONN BIT(1) 618c2ecf20Sopenharmony_ci#define PWR_STATUS_DISP BIT(3) 628c2ecf20Sopenharmony_ci#define PWR_STATUS_MFG BIT(4) 638c2ecf20Sopenharmony_ci#define PWR_STATUS_ISP BIT(5) 648c2ecf20Sopenharmony_ci#define PWR_STATUS_VDEC BIT(7) 658c2ecf20Sopenharmony_ci#define PWR_STATUS_BDP BIT(14) 668c2ecf20Sopenharmony_ci#define PWR_STATUS_ETH BIT(15) 678c2ecf20Sopenharmony_ci#define PWR_STATUS_HIF BIT(16) 688c2ecf20Sopenharmony_ci#define PWR_STATUS_IFR_MSC BIT(17) 698c2ecf20Sopenharmony_ci#define PWR_STATUS_USB2 BIT(19) /* MT2712 */ 708c2ecf20Sopenharmony_ci#define PWR_STATUS_VENC_LT BIT(20) 718c2ecf20Sopenharmony_ci#define PWR_STATUS_VENC BIT(21) 728c2ecf20Sopenharmony_ci#define PWR_STATUS_MFG_2D BIT(22) /* MT8173 */ 738c2ecf20Sopenharmony_ci#define PWR_STATUS_MFG_ASYNC BIT(23) /* MT8173 */ 748c2ecf20Sopenharmony_ci#define PWR_STATUS_AUDIO BIT(24) /* MT8173, MT2712 */ 758c2ecf20Sopenharmony_ci#define PWR_STATUS_USB BIT(25) /* MT8173, MT2712 */ 768c2ecf20Sopenharmony_ci#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */ 778c2ecf20Sopenharmony_ci#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */ 788c2ecf20Sopenharmony_ci#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */ 798c2ecf20Sopenharmony_ci#define PWR_STATUS_WB BIT(27) /* MT7622 */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cienum clk_id { 828c2ecf20Sopenharmony_ci CLK_NONE, 838c2ecf20Sopenharmony_ci CLK_MM, 848c2ecf20Sopenharmony_ci CLK_MFG, 858c2ecf20Sopenharmony_ci CLK_VENC, 868c2ecf20Sopenharmony_ci CLK_VENC_LT, 878c2ecf20Sopenharmony_ci CLK_ETHIF, 888c2ecf20Sopenharmony_ci CLK_VDEC, 898c2ecf20Sopenharmony_ci CLK_HIFSEL, 908c2ecf20Sopenharmony_ci CLK_JPGDEC, 918c2ecf20Sopenharmony_ci CLK_AUDIO, 928c2ecf20Sopenharmony_ci CLK_MAX, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic const char * const clk_names[] = { 968c2ecf20Sopenharmony_ci NULL, 978c2ecf20Sopenharmony_ci "mm", 988c2ecf20Sopenharmony_ci "mfg", 998c2ecf20Sopenharmony_ci "venc", 1008c2ecf20Sopenharmony_ci "venc_lt", 1018c2ecf20Sopenharmony_ci "ethif", 1028c2ecf20Sopenharmony_ci "vdec", 1038c2ecf20Sopenharmony_ci "hif_sel", 1048c2ecf20Sopenharmony_ci "jpgdec", 1058c2ecf20Sopenharmony_ci "audio", 1068c2ecf20Sopenharmony_ci NULL, 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define MAX_CLKS 3 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/** 1128c2ecf20Sopenharmony_ci * struct scp_domain_data - scp domain data for power on/off flow 1138c2ecf20Sopenharmony_ci * @name: The domain name. 1148c2ecf20Sopenharmony_ci * @sta_mask: The mask for power on/off status bit. 1158c2ecf20Sopenharmony_ci * @ctl_offs: The offset for main power control register. 1168c2ecf20Sopenharmony_ci * @sram_pdn_bits: The mask for sram power control bits. 1178c2ecf20Sopenharmony_ci * @sram_pdn_ack_bits: The mask for sram power control acked bits. 1188c2ecf20Sopenharmony_ci * @bus_prot_mask: The mask for single step bus protection. 1198c2ecf20Sopenharmony_ci * @clk_id: The basic clocks required by this power domain. 1208c2ecf20Sopenharmony_ci * @caps: The flag for active wake-up action. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_cistruct scp_domain_data { 1238c2ecf20Sopenharmony_ci const char *name; 1248c2ecf20Sopenharmony_ci u32 sta_mask; 1258c2ecf20Sopenharmony_ci int ctl_offs; 1268c2ecf20Sopenharmony_ci u32 sram_pdn_bits; 1278c2ecf20Sopenharmony_ci u32 sram_pdn_ack_bits; 1288c2ecf20Sopenharmony_ci u32 bus_prot_mask; 1298c2ecf20Sopenharmony_ci enum clk_id clk_id[MAX_CLKS]; 1308c2ecf20Sopenharmony_ci u8 caps; 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistruct scp; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistruct scp_domain { 1368c2ecf20Sopenharmony_ci struct generic_pm_domain genpd; 1378c2ecf20Sopenharmony_ci struct scp *scp; 1388c2ecf20Sopenharmony_ci struct clk *clk[MAX_CLKS]; 1398c2ecf20Sopenharmony_ci const struct scp_domain_data *data; 1408c2ecf20Sopenharmony_ci struct regulator *supply; 1418c2ecf20Sopenharmony_ci}; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistruct scp_ctrl_reg { 1448c2ecf20Sopenharmony_ci int pwr_sta_offs; 1458c2ecf20Sopenharmony_ci int pwr_sta2nd_offs; 1468c2ecf20Sopenharmony_ci}; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistruct scp { 1498c2ecf20Sopenharmony_ci struct scp_domain *domains; 1508c2ecf20Sopenharmony_ci struct genpd_onecell_data pd_data; 1518c2ecf20Sopenharmony_ci struct device *dev; 1528c2ecf20Sopenharmony_ci void __iomem *base; 1538c2ecf20Sopenharmony_ci struct regmap *infracfg; 1548c2ecf20Sopenharmony_ci struct scp_ctrl_reg ctrl_reg; 1558c2ecf20Sopenharmony_ci bool bus_prot_reg_update; 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistruct scp_subdomain { 1598c2ecf20Sopenharmony_ci int origin; 1608c2ecf20Sopenharmony_ci int subdomain; 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistruct scp_soc_data { 1648c2ecf20Sopenharmony_ci const struct scp_domain_data *domains; 1658c2ecf20Sopenharmony_ci int num_domains; 1668c2ecf20Sopenharmony_ci const struct scp_subdomain *subdomains; 1678c2ecf20Sopenharmony_ci int num_subdomains; 1688c2ecf20Sopenharmony_ci const struct scp_ctrl_reg regs; 1698c2ecf20Sopenharmony_ci bool bus_prot_reg_update; 1708c2ecf20Sopenharmony_ci}; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int scpsys_domain_is_on(struct scp_domain *scpd) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct scp *scp = scpd->scp; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) & 1778c2ecf20Sopenharmony_ci scpd->data->sta_mask; 1788c2ecf20Sopenharmony_ci u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) & 1798c2ecf20Sopenharmony_ci scpd->data->sta_mask; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * A domain is on when both status bits are set. If only one is set 1838c2ecf20Sopenharmony_ci * return an error. This happens while powering up a domain 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (status && status2) 1878c2ecf20Sopenharmony_ci return true; 1888c2ecf20Sopenharmony_ci if (!status && !status2) 1898c2ecf20Sopenharmony_ci return false; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return -EINVAL; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int scpsys_regulator_enable(struct scp_domain *scpd) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci if (!scpd->supply) 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci return regulator_enable(scpd->supply); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic int scpsys_regulator_disable(struct scp_domain *scpd) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci if (!scpd->supply) 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci return regulator_disable(scpd->supply); 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic void scpsys_clk_disable(struct clk *clk[], int max_num) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci int i; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci for (i = max_num - 1; i >= 0; i--) 2158c2ecf20Sopenharmony_ci clk_disable_unprepare(clk[i]); 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic int scpsys_clk_enable(struct clk *clk[], int max_num) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci int i, ret = 0; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci for (i = 0; i < max_num && clk[i]; i++) { 2238c2ecf20Sopenharmony_ci ret = clk_prepare_enable(clk[i]); 2248c2ecf20Sopenharmony_ci if (ret) { 2258c2ecf20Sopenharmony_ci scpsys_clk_disable(clk, i); 2268c2ecf20Sopenharmony_ci break; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci return ret; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci u32 val; 2368c2ecf20Sopenharmony_ci u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 2378c2ecf20Sopenharmony_ci int tmp; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci val = readl(ctl_addr); 2408c2ecf20Sopenharmony_ci val &= ~scpd->data->sram_pdn_bits; 2418c2ecf20Sopenharmony_ci writel(val, ctl_addr); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */ 2448c2ecf20Sopenharmony_ci if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) { 2458c2ecf20Sopenharmony_ci /* 2468c2ecf20Sopenharmony_ci * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for 2478c2ecf20Sopenharmony_ci * MT7622_POWER_DOMAIN_WB and thus just a trivial setup 2488c2ecf20Sopenharmony_ci * is applied here. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ci usleep_range(12000, 12100); 2518c2ecf20Sopenharmony_ci } else { 2528c2ecf20Sopenharmony_ci /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 2538c2ecf20Sopenharmony_ci int ret = readl_poll_timeout(ctl_addr, tmp, 2548c2ecf20Sopenharmony_ci (tmp & pdn_ack) == 0, 2558c2ecf20Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 2568c2ecf20Sopenharmony_ci if (ret < 0) 2578c2ecf20Sopenharmony_ci return ret; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci u32 val; 2668c2ecf20Sopenharmony_ci u32 pdn_ack = scpd->data->sram_pdn_ack_bits; 2678c2ecf20Sopenharmony_ci int tmp; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci val = readl(ctl_addr); 2708c2ecf20Sopenharmony_ci val |= scpd->data->sram_pdn_bits; 2718c2ecf20Sopenharmony_ci writel(val, ctl_addr); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* Either wait until SRAM_PDN_ACK all 1 or 0 */ 2748c2ecf20Sopenharmony_ci return readl_poll_timeout(ctl_addr, tmp, 2758c2ecf20Sopenharmony_ci (tmp & pdn_ack) == pdn_ack, 2768c2ecf20Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int scpsys_bus_protect_enable(struct scp_domain *scpd) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci struct scp *scp = scpd->scp; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (!scpd->data->bus_prot_mask) 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return mtk_infracfg_set_bus_protection(scp->infracfg, 2878c2ecf20Sopenharmony_ci scpd->data->bus_prot_mask, 2888c2ecf20Sopenharmony_ci scp->bus_prot_reg_update); 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic int scpsys_bus_protect_disable(struct scp_domain *scpd) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct scp *scp = scpd->scp; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (!scpd->data->bus_prot_mask) 2968c2ecf20Sopenharmony_ci return 0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci return mtk_infracfg_clear_bus_protection(scp->infracfg, 2998c2ecf20Sopenharmony_ci scpd->data->bus_prot_mask, 3008c2ecf20Sopenharmony_ci scp->bus_prot_reg_update); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int scpsys_power_on(struct generic_pm_domain *genpd) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 3068c2ecf20Sopenharmony_ci struct scp *scp = scpd->scp; 3078c2ecf20Sopenharmony_ci void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 3088c2ecf20Sopenharmony_ci u32 val; 3098c2ecf20Sopenharmony_ci int ret, tmp; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci ret = scpsys_regulator_enable(scpd); 3128c2ecf20Sopenharmony_ci if (ret < 0) 3138c2ecf20Sopenharmony_ci return ret; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci ret = scpsys_clk_enable(scpd->clk, MAX_CLKS); 3168c2ecf20Sopenharmony_ci if (ret) 3178c2ecf20Sopenharmony_ci goto err_clk; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* subsys power on */ 3208c2ecf20Sopenharmony_ci val = readl(ctl_addr); 3218c2ecf20Sopenharmony_ci val |= PWR_ON_BIT; 3228c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3238c2ecf20Sopenharmony_ci val |= PWR_ON_2ND_BIT; 3248c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* wait until PWR_ACK = 1 */ 3278c2ecf20Sopenharmony_ci ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0, 3288c2ecf20Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 3298c2ecf20Sopenharmony_ci if (ret < 0) 3308c2ecf20Sopenharmony_ci goto err_pwr_ack; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci val &= ~PWR_CLK_DIS_BIT; 3338c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci val &= ~PWR_ISO_BIT; 3368c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci val |= PWR_RST_B_BIT; 3398c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci ret = scpsys_sram_enable(scpd, ctl_addr); 3428c2ecf20Sopenharmony_ci if (ret < 0) 3438c2ecf20Sopenharmony_ci goto err_pwr_ack; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci ret = scpsys_bus_protect_disable(scpd); 3468c2ecf20Sopenharmony_ci if (ret < 0) 3478c2ecf20Sopenharmony_ci goto err_pwr_ack; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return 0; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cierr_pwr_ack: 3528c2ecf20Sopenharmony_ci scpsys_clk_disable(scpd->clk, MAX_CLKS); 3538c2ecf20Sopenharmony_cierr_clk: 3548c2ecf20Sopenharmony_ci scpsys_regulator_disable(scpd); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return ret; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic int scpsys_power_off(struct generic_pm_domain *genpd) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd); 3648c2ecf20Sopenharmony_ci struct scp *scp = scpd->scp; 3658c2ecf20Sopenharmony_ci void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs; 3668c2ecf20Sopenharmony_ci u32 val; 3678c2ecf20Sopenharmony_ci int ret, tmp; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci ret = scpsys_bus_protect_enable(scpd); 3708c2ecf20Sopenharmony_ci if (ret < 0) 3718c2ecf20Sopenharmony_ci goto out; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci ret = scpsys_sram_disable(scpd, ctl_addr); 3748c2ecf20Sopenharmony_ci if (ret < 0) 3758c2ecf20Sopenharmony_ci goto out; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* subsys power off */ 3788c2ecf20Sopenharmony_ci val = readl(ctl_addr); 3798c2ecf20Sopenharmony_ci val |= PWR_ISO_BIT; 3808c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci val &= ~PWR_RST_B_BIT; 3838c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci val |= PWR_CLK_DIS_BIT; 3868c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci val &= ~PWR_ON_BIT; 3898c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci val &= ~PWR_ON_2ND_BIT; 3928c2ecf20Sopenharmony_ci writel(val, ctl_addr); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* wait until PWR_ACK = 0 */ 3958c2ecf20Sopenharmony_ci ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0, 3968c2ecf20Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 3978c2ecf20Sopenharmony_ci if (ret < 0) 3988c2ecf20Sopenharmony_ci goto out; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci scpsys_clk_disable(scpd->clk, MAX_CLKS); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci ret = scpsys_regulator_disable(scpd); 4038c2ecf20Sopenharmony_ci if (ret < 0) 4048c2ecf20Sopenharmony_ci goto out; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci return 0; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ciout: 4098c2ecf20Sopenharmony_ci dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci return ret; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic void init_clks(struct platform_device *pdev, struct clk **clk) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci int i; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci for (i = CLK_NONE + 1; i < CLK_MAX; i++) 4198c2ecf20Sopenharmony_ci clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic struct scp *init_scp(struct platform_device *pdev, 4238c2ecf20Sopenharmony_ci const struct scp_domain_data *scp_domain_data, int num, 4248c2ecf20Sopenharmony_ci const struct scp_ctrl_reg *scp_ctrl_reg, 4258c2ecf20Sopenharmony_ci bool bus_prot_reg_update) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci struct genpd_onecell_data *pd_data; 4288c2ecf20Sopenharmony_ci struct resource *res; 4298c2ecf20Sopenharmony_ci int i, j; 4308c2ecf20Sopenharmony_ci struct scp *scp; 4318c2ecf20Sopenharmony_ci struct clk *clk[CLK_MAX]; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); 4348c2ecf20Sopenharmony_ci if (!scp) 4358c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; 4388c2ecf20Sopenharmony_ci scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci scp->bus_prot_reg_update = bus_prot_reg_update; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci scp->dev = &pdev->dev; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 4458c2ecf20Sopenharmony_ci scp->base = devm_ioremap_resource(&pdev->dev, res); 4468c2ecf20Sopenharmony_ci if (IS_ERR(scp->base)) 4478c2ecf20Sopenharmony_ci return ERR_CAST(scp->base); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci scp->domains = devm_kcalloc(&pdev->dev, 4508c2ecf20Sopenharmony_ci num, sizeof(*scp->domains), GFP_KERNEL); 4518c2ecf20Sopenharmony_ci if (!scp->domains) 4528c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci pd_data = &scp->pd_data; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci pd_data->domains = devm_kcalloc(&pdev->dev, 4578c2ecf20Sopenharmony_ci num, sizeof(*pd_data->domains), GFP_KERNEL); 4588c2ecf20Sopenharmony_ci if (!pd_data->domains) 4598c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 4628c2ecf20Sopenharmony_ci "infracfg"); 4638c2ecf20Sopenharmony_ci if (IS_ERR(scp->infracfg)) { 4648c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", 4658c2ecf20Sopenharmony_ci PTR_ERR(scp->infracfg)); 4668c2ecf20Sopenharmony_ci return ERR_CAST(scp->infracfg); 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 4708c2ecf20Sopenharmony_ci struct scp_domain *scpd = &scp->domains[i]; 4718c2ecf20Sopenharmony_ci const struct scp_domain_data *data = &scp_domain_data[i]; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name); 4748c2ecf20Sopenharmony_ci if (IS_ERR(scpd->supply)) { 4758c2ecf20Sopenharmony_ci if (PTR_ERR(scpd->supply) == -ENODEV) 4768c2ecf20Sopenharmony_ci scpd->supply = NULL; 4778c2ecf20Sopenharmony_ci else 4788c2ecf20Sopenharmony_ci return ERR_CAST(scpd->supply); 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci pd_data->num_domains = num; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci init_clks(pdev, clk); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 4878c2ecf20Sopenharmony_ci struct scp_domain *scpd = &scp->domains[i]; 4888c2ecf20Sopenharmony_ci struct generic_pm_domain *genpd = &scpd->genpd; 4898c2ecf20Sopenharmony_ci const struct scp_domain_data *data = &scp_domain_data[i]; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci pd_data->domains[i] = genpd; 4928c2ecf20Sopenharmony_ci scpd->scp = scp; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci scpd->data = data; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { 4978c2ecf20Sopenharmony_ci struct clk *c = clk[data->clk_id[j]]; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (IS_ERR(c)) { 5008c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "%s: clk unavailable\n", 5018c2ecf20Sopenharmony_ci data->name); 5028c2ecf20Sopenharmony_ci return ERR_CAST(c); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci scpd->clk[j] = c; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci genpd->name = data->name; 5098c2ecf20Sopenharmony_ci genpd->power_off = scpsys_power_off; 5108c2ecf20Sopenharmony_ci genpd->power_on = scpsys_power_on; 5118c2ecf20Sopenharmony_ci if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP)) 5128c2ecf20Sopenharmony_ci genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return scp; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic void mtk_register_power_domains(struct platform_device *pdev, 5198c2ecf20Sopenharmony_ci struct scp *scp, int num) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci struct genpd_onecell_data *pd_data; 5228c2ecf20Sopenharmony_ci int i, ret; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 5258c2ecf20Sopenharmony_ci struct scp_domain *scpd = &scp->domains[i]; 5268c2ecf20Sopenharmony_ci struct generic_pm_domain *genpd = &scpd->genpd; 5278c2ecf20Sopenharmony_ci bool on; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* 5308c2ecf20Sopenharmony_ci * Initially turn on all domains to make the domains usable 5318c2ecf20Sopenharmony_ci * with !CONFIG_PM and to get the hardware in sync with the 5328c2ecf20Sopenharmony_ci * software. The unused domains will be switched off during 5338c2ecf20Sopenharmony_ci * late_init time. 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_ci on = !WARN_ON(genpd->power_on(genpd) < 0); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci pm_genpd_init(genpd, NULL, !on); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* 5418c2ecf20Sopenharmony_ci * We are not allowed to fail here since there is no way to unregister 5428c2ecf20Sopenharmony_ci * a power domain. Once registered above we have to keep the domains 5438c2ecf20Sopenharmony_ci * valid. 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci pd_data = &scp->pd_data; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); 5498c2ecf20Sopenharmony_ci if (ret) 5508c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci/* 5548c2ecf20Sopenharmony_ci * MT2701 power domain support 5558c2ecf20Sopenharmony_ci */ 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt2701[] = { 5588c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_CONN] = { 5598c2ecf20Sopenharmony_ci .name = "conn", 5608c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_CONN, 5618c2ecf20Sopenharmony_ci .ctl_offs = SPM_CONN_PWR_CON, 5628c2ecf20Sopenharmony_ci .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | 5638c2ecf20Sopenharmony_ci MT2701_TOP_AXI_PROT_EN_CONN_S, 5648c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 5658c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 5668c2ecf20Sopenharmony_ci }, 5678c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_DISP] = { 5688c2ecf20Sopenharmony_ci .name = "disp", 5698c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_DISP, 5708c2ecf20Sopenharmony_ci .ctl_offs = SPM_DIS_PWR_CON, 5718c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 5728c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 5738c2ecf20Sopenharmony_ci .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0, 5748c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 5758c2ecf20Sopenharmony_ci }, 5768c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_MFG] = { 5778c2ecf20Sopenharmony_ci .name = "mfg", 5788c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_MFG, 5798c2ecf20Sopenharmony_ci .ctl_offs = SPM_MFG_PWR_CON, 5808c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 5818c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 5828c2ecf20Sopenharmony_ci .clk_id = {CLK_MFG}, 5838c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 5848c2ecf20Sopenharmony_ci }, 5858c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_VDEC] = { 5868c2ecf20Sopenharmony_ci .name = "vdec", 5878c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VDEC, 5888c2ecf20Sopenharmony_ci .ctl_offs = SPM_VDE_PWR_CON, 5898c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 5908c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 5918c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 5928c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 5938c2ecf20Sopenharmony_ci }, 5948c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_ISP] = { 5958c2ecf20Sopenharmony_ci .name = "isp", 5968c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ISP, 5978c2ecf20Sopenharmony_ci .ctl_offs = SPM_ISP_PWR_CON, 5988c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 5998c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(13, 12), 6008c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 6018c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6028c2ecf20Sopenharmony_ci }, 6038c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_BDP] = { 6048c2ecf20Sopenharmony_ci .name = "bdp", 6058c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_BDP, 6068c2ecf20Sopenharmony_ci .ctl_offs = SPM_BDP_PWR_CON, 6078c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6088c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 6098c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6108c2ecf20Sopenharmony_ci }, 6118c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_ETH] = { 6128c2ecf20Sopenharmony_ci .name = "eth", 6138c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ETH, 6148c2ecf20Sopenharmony_ci .ctl_offs = SPM_ETH_PWR_CON, 6158c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6168c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 6178c2ecf20Sopenharmony_ci .clk_id = {CLK_ETHIF}, 6188c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6198c2ecf20Sopenharmony_ci }, 6208c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_HIF] = { 6218c2ecf20Sopenharmony_ci .name = "hif", 6228c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_HIF, 6238c2ecf20Sopenharmony_ci .ctl_offs = SPM_HIF_PWR_CON, 6248c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6258c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 6268c2ecf20Sopenharmony_ci .clk_id = {CLK_ETHIF}, 6278c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6288c2ecf20Sopenharmony_ci }, 6298c2ecf20Sopenharmony_ci [MT2701_POWER_DOMAIN_IFR_MSC] = { 6308c2ecf20Sopenharmony_ci .name = "ifr_msc", 6318c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_IFR_MSC, 6328c2ecf20Sopenharmony_ci .ctl_offs = SPM_IFR_MSC_PWR_CON, 6338c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 6348c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6358c2ecf20Sopenharmony_ci }, 6368c2ecf20Sopenharmony_ci}; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci/* 6398c2ecf20Sopenharmony_ci * MT2712 power domain support 6408c2ecf20Sopenharmony_ci */ 6418c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt2712[] = { 6428c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_MM] = { 6438c2ecf20Sopenharmony_ci .name = "mm", 6448c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_DISP, 6458c2ecf20Sopenharmony_ci .ctl_offs = SPM_DIS_PWR_CON, 6468c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 6478c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 6488c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 6498c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6508c2ecf20Sopenharmony_ci }, 6518c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_VDEC] = { 6528c2ecf20Sopenharmony_ci .name = "vdec", 6538c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VDEC, 6548c2ecf20Sopenharmony_ci .ctl_offs = SPM_VDE_PWR_CON, 6558c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 6568c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 6578c2ecf20Sopenharmony_ci .clk_id = {CLK_MM, CLK_VDEC}, 6588c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6598c2ecf20Sopenharmony_ci }, 6608c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_VENC] = { 6618c2ecf20Sopenharmony_ci .name = "venc", 6628c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VENC, 6638c2ecf20Sopenharmony_ci .ctl_offs = SPM_VEN_PWR_CON, 6648c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6658c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 6668c2ecf20Sopenharmony_ci .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC}, 6678c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6688c2ecf20Sopenharmony_ci }, 6698c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_ISP] = { 6708c2ecf20Sopenharmony_ci .name = "isp", 6718c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ISP, 6728c2ecf20Sopenharmony_ci .ctl_offs = SPM_ISP_PWR_CON, 6738c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6748c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(13, 12), 6758c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 6768c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6778c2ecf20Sopenharmony_ci }, 6788c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_AUDIO] = { 6798c2ecf20Sopenharmony_ci .name = "audio", 6808c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_AUDIO, 6818c2ecf20Sopenharmony_ci .ctl_offs = SPM_AUDIO_PWR_CON, 6828c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 6838c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 6848c2ecf20Sopenharmony_ci .clk_id = {CLK_AUDIO}, 6858c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6868c2ecf20Sopenharmony_ci }, 6878c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_USB] = { 6888c2ecf20Sopenharmony_ci .name = "usb", 6898c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_USB, 6908c2ecf20Sopenharmony_ci .ctl_offs = SPM_USB_PWR_CON, 6918c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(10, 8), 6928c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(14, 12), 6938c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 6948c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 6958c2ecf20Sopenharmony_ci }, 6968c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_USB2] = { 6978c2ecf20Sopenharmony_ci .name = "usb2", 6988c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_USB2, 6998c2ecf20Sopenharmony_ci .ctl_offs = SPM_USB2_PWR_CON, 7008c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(10, 8), 7018c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(14, 12), 7028c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7038c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 7048c2ecf20Sopenharmony_ci }, 7058c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_MFG] = { 7068c2ecf20Sopenharmony_ci .name = "mfg", 7078c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_MFG, 7088c2ecf20Sopenharmony_ci .ctl_offs = SPM_MFG_PWR_CON, 7098c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7108c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(16, 16), 7118c2ecf20Sopenharmony_ci .clk_id = {CLK_MFG}, 7128c2ecf20Sopenharmony_ci .bus_prot_mask = BIT(14) | BIT(21) | BIT(23), 7138c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 7148c2ecf20Sopenharmony_ci }, 7158c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_MFG_SC1] = { 7168c2ecf20Sopenharmony_ci .name = "mfg_sc1", 7178c2ecf20Sopenharmony_ci .sta_mask = BIT(22), 7188c2ecf20Sopenharmony_ci .ctl_offs = 0x02c0, 7198c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7208c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(16, 16), 7218c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7228c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 7238c2ecf20Sopenharmony_ci }, 7248c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_MFG_SC2] = { 7258c2ecf20Sopenharmony_ci .name = "mfg_sc2", 7268c2ecf20Sopenharmony_ci .sta_mask = BIT(23), 7278c2ecf20Sopenharmony_ci .ctl_offs = 0x02c4, 7288c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7298c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(16, 16), 7308c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7318c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 7328c2ecf20Sopenharmony_ci }, 7338c2ecf20Sopenharmony_ci [MT2712_POWER_DOMAIN_MFG_SC3] = { 7348c2ecf20Sopenharmony_ci .name = "mfg_sc3", 7358c2ecf20Sopenharmony_ci .sta_mask = BIT(30), 7368c2ecf20Sopenharmony_ci .ctl_offs = 0x01f8, 7378c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7388c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(16, 16), 7398c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7408c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 7418c2ecf20Sopenharmony_ci }, 7428c2ecf20Sopenharmony_ci}; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic const struct scp_subdomain scp_subdomain_mt2712[] = { 7458c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC}, 7468c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC}, 7478c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP}, 7488c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1}, 7498c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2}, 7508c2ecf20Sopenharmony_ci {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3}, 7518c2ecf20Sopenharmony_ci}; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci/* 7548c2ecf20Sopenharmony_ci * MT6797 power domain support 7558c2ecf20Sopenharmony_ci */ 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt6797[] = { 7588c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_VDEC] = { 7598c2ecf20Sopenharmony_ci .name = "vdec", 7608c2ecf20Sopenharmony_ci .sta_mask = BIT(7), 7618c2ecf20Sopenharmony_ci .ctl_offs = 0x300, 7628c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7638c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 7648c2ecf20Sopenharmony_ci .clk_id = {CLK_VDEC}, 7658c2ecf20Sopenharmony_ci }, 7668c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_VENC] = { 7678c2ecf20Sopenharmony_ci .name = "venc", 7688c2ecf20Sopenharmony_ci .sta_mask = BIT(21), 7698c2ecf20Sopenharmony_ci .ctl_offs = 0x304, 7708c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 7718c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 7728c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7738c2ecf20Sopenharmony_ci }, 7748c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_ISP] = { 7758c2ecf20Sopenharmony_ci .name = "isp", 7768c2ecf20Sopenharmony_ci .sta_mask = BIT(5), 7778c2ecf20Sopenharmony_ci .ctl_offs = 0x308, 7788c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(9, 8), 7798c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(13, 12), 7808c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7818c2ecf20Sopenharmony_ci }, 7828c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_MM] = { 7838c2ecf20Sopenharmony_ci .name = "mm", 7848c2ecf20Sopenharmony_ci .sta_mask = BIT(3), 7858c2ecf20Sopenharmony_ci .ctl_offs = 0x30C, 7868c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 7878c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 7888c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 7898c2ecf20Sopenharmony_ci .bus_prot_mask = (BIT(1) | BIT(2)), 7908c2ecf20Sopenharmony_ci }, 7918c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_AUDIO] = { 7928c2ecf20Sopenharmony_ci .name = "audio", 7938c2ecf20Sopenharmony_ci .sta_mask = BIT(24), 7948c2ecf20Sopenharmony_ci .ctl_offs = 0x314, 7958c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 7968c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 7978c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 7988c2ecf20Sopenharmony_ci }, 7998c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_MFG_ASYNC] = { 8008c2ecf20Sopenharmony_ci .name = "mfg_async", 8018c2ecf20Sopenharmony_ci .sta_mask = BIT(13), 8028c2ecf20Sopenharmony_ci .ctl_offs = 0x334, 8038c2ecf20Sopenharmony_ci .sram_pdn_bits = 0, 8048c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = 0, 8058c2ecf20Sopenharmony_ci .clk_id = {CLK_MFG}, 8068c2ecf20Sopenharmony_ci }, 8078c2ecf20Sopenharmony_ci [MT6797_POWER_DOMAIN_MJC] = { 8088c2ecf20Sopenharmony_ci .name = "mjc", 8098c2ecf20Sopenharmony_ci .sta_mask = BIT(20), 8108c2ecf20Sopenharmony_ci .ctl_offs = 0x310, 8118c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(8, 8), 8128c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 8138c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 8148c2ecf20Sopenharmony_ci }, 8158c2ecf20Sopenharmony_ci}; 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci#define SPM_PWR_STATUS_MT6797 0x0180 8188c2ecf20Sopenharmony_ci#define SPM_PWR_STATUS_2ND_MT6797 0x0184 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic const struct scp_subdomain scp_subdomain_mt6797[] = { 8218c2ecf20Sopenharmony_ci {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC}, 8228c2ecf20Sopenharmony_ci {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP}, 8238c2ecf20Sopenharmony_ci {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC}, 8248c2ecf20Sopenharmony_ci {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC}, 8258c2ecf20Sopenharmony_ci}; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci/* 8288c2ecf20Sopenharmony_ci * MT7622 power domain support 8298c2ecf20Sopenharmony_ci */ 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt7622[] = { 8328c2ecf20Sopenharmony_ci [MT7622_POWER_DOMAIN_ETHSYS] = { 8338c2ecf20Sopenharmony_ci .name = "ethsys", 8348c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ETHSYS, 8358c2ecf20Sopenharmony_ci .ctl_offs = SPM_ETHSYS_PWR_CON, 8368c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 8378c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 8388c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 8398c2ecf20Sopenharmony_ci .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS, 8408c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 8418c2ecf20Sopenharmony_ci }, 8428c2ecf20Sopenharmony_ci [MT7622_POWER_DOMAIN_HIF0] = { 8438c2ecf20Sopenharmony_ci .name = "hif0", 8448c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_HIF0, 8458c2ecf20Sopenharmony_ci .ctl_offs = SPM_HIF0_PWR_CON, 8468c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 8478c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 8488c2ecf20Sopenharmony_ci .clk_id = {CLK_HIFSEL}, 8498c2ecf20Sopenharmony_ci .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0, 8508c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 8518c2ecf20Sopenharmony_ci }, 8528c2ecf20Sopenharmony_ci [MT7622_POWER_DOMAIN_HIF1] = { 8538c2ecf20Sopenharmony_ci .name = "hif1", 8548c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_HIF1, 8558c2ecf20Sopenharmony_ci .ctl_offs = SPM_HIF1_PWR_CON, 8568c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 8578c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 8588c2ecf20Sopenharmony_ci .clk_id = {CLK_HIFSEL}, 8598c2ecf20Sopenharmony_ci .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1, 8608c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 8618c2ecf20Sopenharmony_ci }, 8628c2ecf20Sopenharmony_ci [MT7622_POWER_DOMAIN_WB] = { 8638c2ecf20Sopenharmony_ci .name = "wb", 8648c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_WB, 8658c2ecf20Sopenharmony_ci .ctl_offs = SPM_WB_PWR_CON, 8668c2ecf20Sopenharmony_ci .sram_pdn_bits = 0, 8678c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = 0, 8688c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 8698c2ecf20Sopenharmony_ci .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB, 8708c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM, 8718c2ecf20Sopenharmony_ci }, 8728c2ecf20Sopenharmony_ci}; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci/* 8758c2ecf20Sopenharmony_ci * MT7623A power domain support 8768c2ecf20Sopenharmony_ci */ 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt7623a[] = { 8798c2ecf20Sopenharmony_ci [MT7623A_POWER_DOMAIN_CONN] = { 8808c2ecf20Sopenharmony_ci .name = "conn", 8818c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_CONN, 8828c2ecf20Sopenharmony_ci .ctl_offs = SPM_CONN_PWR_CON, 8838c2ecf20Sopenharmony_ci .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M | 8848c2ecf20Sopenharmony_ci MT2701_TOP_AXI_PROT_EN_CONN_S, 8858c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 8868c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 8878c2ecf20Sopenharmony_ci }, 8888c2ecf20Sopenharmony_ci [MT7623A_POWER_DOMAIN_ETH] = { 8898c2ecf20Sopenharmony_ci .name = "eth", 8908c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ETH, 8918c2ecf20Sopenharmony_ci .ctl_offs = SPM_ETH_PWR_CON, 8928c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 8938c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 8948c2ecf20Sopenharmony_ci .clk_id = {CLK_ETHIF}, 8958c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 8968c2ecf20Sopenharmony_ci }, 8978c2ecf20Sopenharmony_ci [MT7623A_POWER_DOMAIN_HIF] = { 8988c2ecf20Sopenharmony_ci .name = "hif", 8998c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_HIF, 9008c2ecf20Sopenharmony_ci .ctl_offs = SPM_HIF_PWR_CON, 9018c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9028c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 9038c2ecf20Sopenharmony_ci .clk_id = {CLK_ETHIF}, 9048c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 9058c2ecf20Sopenharmony_ci }, 9068c2ecf20Sopenharmony_ci [MT7623A_POWER_DOMAIN_IFR_MSC] = { 9078c2ecf20Sopenharmony_ci .name = "ifr_msc", 9088c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_IFR_MSC, 9098c2ecf20Sopenharmony_ci .ctl_offs = SPM_IFR_MSC_PWR_CON, 9108c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 9118c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 9128c2ecf20Sopenharmony_ci }, 9138c2ecf20Sopenharmony_ci}; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci/* 9168c2ecf20Sopenharmony_ci * MT8173 power domain support 9178c2ecf20Sopenharmony_ci */ 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic const struct scp_domain_data scp_domain_data_mt8173[] = { 9208c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_VDEC] = { 9218c2ecf20Sopenharmony_ci .name = "vdec", 9228c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VDEC, 9238c2ecf20Sopenharmony_ci .ctl_offs = SPM_VDE_PWR_CON, 9248c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9258c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 9268c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 9278c2ecf20Sopenharmony_ci }, 9288c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_VENC] = { 9298c2ecf20Sopenharmony_ci .name = "venc", 9308c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VENC, 9318c2ecf20Sopenharmony_ci .ctl_offs = SPM_VEN_PWR_CON, 9328c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9338c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 9348c2ecf20Sopenharmony_ci .clk_id = {CLK_MM, CLK_VENC}, 9358c2ecf20Sopenharmony_ci }, 9368c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_ISP] = { 9378c2ecf20Sopenharmony_ci .name = "isp", 9388c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_ISP, 9398c2ecf20Sopenharmony_ci .ctl_offs = SPM_ISP_PWR_CON, 9408c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9418c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(13, 12), 9428c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 9438c2ecf20Sopenharmony_ci }, 9448c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_MM] = { 9458c2ecf20Sopenharmony_ci .name = "mm", 9468c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_DISP, 9478c2ecf20Sopenharmony_ci .ctl_offs = SPM_DIS_PWR_CON, 9488c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9498c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(12, 12), 9508c2ecf20Sopenharmony_ci .clk_id = {CLK_MM}, 9518c2ecf20Sopenharmony_ci .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 9528c2ecf20Sopenharmony_ci MT8173_TOP_AXI_PROT_EN_MM_M1, 9538c2ecf20Sopenharmony_ci }, 9548c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_VENC_LT] = { 9558c2ecf20Sopenharmony_ci .name = "venc_lt", 9568c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_VENC_LT, 9578c2ecf20Sopenharmony_ci .ctl_offs = SPM_VEN2_PWR_CON, 9588c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9598c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 9608c2ecf20Sopenharmony_ci .clk_id = {CLK_MM, CLK_VENC_LT}, 9618c2ecf20Sopenharmony_ci }, 9628c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_AUDIO] = { 9638c2ecf20Sopenharmony_ci .name = "audio", 9648c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_AUDIO, 9658c2ecf20Sopenharmony_ci .ctl_offs = SPM_AUDIO_PWR_CON, 9668c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9678c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 9688c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 9698c2ecf20Sopenharmony_ci }, 9708c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_USB] = { 9718c2ecf20Sopenharmony_ci .name = "usb", 9728c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_USB, 9738c2ecf20Sopenharmony_ci .ctl_offs = SPM_USB_PWR_CON, 9748c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9758c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(15, 12), 9768c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 9778c2ecf20Sopenharmony_ci .caps = MTK_SCPD_ACTIVE_WAKEUP, 9788c2ecf20Sopenharmony_ci }, 9798c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 9808c2ecf20Sopenharmony_ci .name = "mfg_async", 9818c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_MFG_ASYNC, 9828c2ecf20Sopenharmony_ci .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 9838c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9848c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = 0, 9858c2ecf20Sopenharmony_ci .clk_id = {CLK_MFG}, 9868c2ecf20Sopenharmony_ci }, 9878c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_MFG_2D] = { 9888c2ecf20Sopenharmony_ci .name = "mfg_2d", 9898c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_MFG_2D, 9908c2ecf20Sopenharmony_ci .ctl_offs = SPM_MFG_2D_PWR_CON, 9918c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(11, 8), 9928c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(13, 12), 9938c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 9948c2ecf20Sopenharmony_ci }, 9958c2ecf20Sopenharmony_ci [MT8173_POWER_DOMAIN_MFG] = { 9968c2ecf20Sopenharmony_ci .name = "mfg", 9978c2ecf20Sopenharmony_ci .sta_mask = PWR_STATUS_MFG, 9988c2ecf20Sopenharmony_ci .ctl_offs = SPM_MFG_PWR_CON, 9998c2ecf20Sopenharmony_ci .sram_pdn_bits = GENMASK(13, 8), 10008c2ecf20Sopenharmony_ci .sram_pdn_ack_bits = GENMASK(21, 16), 10018c2ecf20Sopenharmony_ci .clk_id = {CLK_NONE}, 10028c2ecf20Sopenharmony_ci .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 10038c2ecf20Sopenharmony_ci MT8173_TOP_AXI_PROT_EN_MFG_M0 | 10048c2ecf20Sopenharmony_ci MT8173_TOP_AXI_PROT_EN_MFG_M1 | 10058c2ecf20Sopenharmony_ci MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, 10068c2ecf20Sopenharmony_ci }, 10078c2ecf20Sopenharmony_ci}; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic const struct scp_subdomain scp_subdomain_mt8173[] = { 10108c2ecf20Sopenharmony_ci {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D}, 10118c2ecf20Sopenharmony_ci {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG}, 10128c2ecf20Sopenharmony_ci}; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt2701_data = { 10158c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt2701, 10168c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt2701), 10178c2ecf20Sopenharmony_ci .regs = { 10188c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS, 10198c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 10208c2ecf20Sopenharmony_ci }, 10218c2ecf20Sopenharmony_ci .bus_prot_reg_update = true, 10228c2ecf20Sopenharmony_ci}; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt2712_data = { 10258c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt2712, 10268c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt2712), 10278c2ecf20Sopenharmony_ci .subdomains = scp_subdomain_mt2712, 10288c2ecf20Sopenharmony_ci .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712), 10298c2ecf20Sopenharmony_ci .regs = { 10308c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS, 10318c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 10328c2ecf20Sopenharmony_ci }, 10338c2ecf20Sopenharmony_ci .bus_prot_reg_update = false, 10348c2ecf20Sopenharmony_ci}; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt6797_data = { 10378c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt6797, 10388c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt6797), 10398c2ecf20Sopenharmony_ci .subdomains = scp_subdomain_mt6797, 10408c2ecf20Sopenharmony_ci .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797), 10418c2ecf20Sopenharmony_ci .regs = { 10428c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS_MT6797, 10438c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 10448c2ecf20Sopenharmony_ci }, 10458c2ecf20Sopenharmony_ci .bus_prot_reg_update = true, 10468c2ecf20Sopenharmony_ci}; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt7622_data = { 10498c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt7622, 10508c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt7622), 10518c2ecf20Sopenharmony_ci .regs = { 10528c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS, 10538c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 10548c2ecf20Sopenharmony_ci }, 10558c2ecf20Sopenharmony_ci .bus_prot_reg_update = true, 10568c2ecf20Sopenharmony_ci}; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt7623a_data = { 10598c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt7623a, 10608c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a), 10618c2ecf20Sopenharmony_ci .regs = { 10628c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS, 10638c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 10648c2ecf20Sopenharmony_ci }, 10658c2ecf20Sopenharmony_ci .bus_prot_reg_update = true, 10668c2ecf20Sopenharmony_ci}; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic const struct scp_soc_data mt8173_data = { 10698c2ecf20Sopenharmony_ci .domains = scp_domain_data_mt8173, 10708c2ecf20Sopenharmony_ci .num_domains = ARRAY_SIZE(scp_domain_data_mt8173), 10718c2ecf20Sopenharmony_ci .subdomains = scp_subdomain_mt8173, 10728c2ecf20Sopenharmony_ci .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173), 10738c2ecf20Sopenharmony_ci .regs = { 10748c2ecf20Sopenharmony_ci .pwr_sta_offs = SPM_PWR_STATUS, 10758c2ecf20Sopenharmony_ci .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND 10768c2ecf20Sopenharmony_ci }, 10778c2ecf20Sopenharmony_ci .bus_prot_reg_update = true, 10788c2ecf20Sopenharmony_ci}; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci/* 10818c2ecf20Sopenharmony_ci * scpsys driver init 10828c2ecf20Sopenharmony_ci */ 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_cistatic const struct of_device_id of_scpsys_match_tbl[] = { 10858c2ecf20Sopenharmony_ci { 10868c2ecf20Sopenharmony_ci .compatible = "mediatek,mt2701-scpsys", 10878c2ecf20Sopenharmony_ci .data = &mt2701_data, 10888c2ecf20Sopenharmony_ci }, { 10898c2ecf20Sopenharmony_ci .compatible = "mediatek,mt2712-scpsys", 10908c2ecf20Sopenharmony_ci .data = &mt2712_data, 10918c2ecf20Sopenharmony_ci }, { 10928c2ecf20Sopenharmony_ci .compatible = "mediatek,mt6797-scpsys", 10938c2ecf20Sopenharmony_ci .data = &mt6797_data, 10948c2ecf20Sopenharmony_ci }, { 10958c2ecf20Sopenharmony_ci .compatible = "mediatek,mt7622-scpsys", 10968c2ecf20Sopenharmony_ci .data = &mt7622_data, 10978c2ecf20Sopenharmony_ci }, { 10988c2ecf20Sopenharmony_ci .compatible = "mediatek,mt7623a-scpsys", 10998c2ecf20Sopenharmony_ci .data = &mt7623a_data, 11008c2ecf20Sopenharmony_ci }, { 11018c2ecf20Sopenharmony_ci .compatible = "mediatek,mt8173-scpsys", 11028c2ecf20Sopenharmony_ci .data = &mt8173_data, 11038c2ecf20Sopenharmony_ci }, { 11048c2ecf20Sopenharmony_ci /* sentinel */ 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci}; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic int scpsys_probe(struct platform_device *pdev) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci const struct scp_subdomain *sd; 11118c2ecf20Sopenharmony_ci const struct scp_soc_data *soc; 11128c2ecf20Sopenharmony_ci struct scp *scp; 11138c2ecf20Sopenharmony_ci struct genpd_onecell_data *pd_data; 11148c2ecf20Sopenharmony_ci int i, ret; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci soc = of_device_get_match_data(&pdev->dev); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs, 11198c2ecf20Sopenharmony_ci soc->bus_prot_reg_update); 11208c2ecf20Sopenharmony_ci if (IS_ERR(scp)) 11218c2ecf20Sopenharmony_ci return PTR_ERR(scp); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci mtk_register_power_domains(pdev, scp, soc->num_domains); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci pd_data = &scp->pd_data; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) { 11288c2ecf20Sopenharmony_ci ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin], 11298c2ecf20Sopenharmony_ci pd_data->domains[sd->subdomain]); 11308c2ecf20Sopenharmony_ci if (ret && IS_ENABLED(CONFIG_PM)) 11318c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to add subdomain: %d\n", 11328c2ecf20Sopenharmony_ci ret); 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return 0; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistatic struct platform_driver scpsys_drv = { 11398c2ecf20Sopenharmony_ci .probe = scpsys_probe, 11408c2ecf20Sopenharmony_ci .driver = { 11418c2ecf20Sopenharmony_ci .name = "mtk-scpsys", 11428c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 11438c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 11448c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(of_scpsys_match_tbl), 11458c2ecf20Sopenharmony_ci }, 11468c2ecf20Sopenharmony_ci}; 11478c2ecf20Sopenharmony_cibuiltin_platform_driver(scpsys_drv); 1148