// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2021 MediaTek Inc. */ #include #include #include #include #include #include "devapc-mt6886.h" static const struct mtk_device_num mtk6886_devices_num[] = { {SLAVE_TYPE_INFRA, VIO_SLAVE_NUM_INFRA, IRQ_TYPE_INFRA}, {SLAVE_TYPE_INFRA1, VIO_SLAVE_NUM_INFRA1, IRQ_TYPE_INFRA}, {SLAVE_TYPE_PERI_PAR, VIO_SLAVE_NUM_PERI_PAR, IRQ_TYPE_INFRA}, {SLAVE_TYPE_VLP, VIO_SLAVE_NUM_VLP, IRQ_TYPE_VLP}, {SLAVE_TYPE_ADSP, VIO_SLAVE_NUM_ADSP, IRQ_TYPE_ADSP}, {SLAVE_TYPE_MMINFRA, VIO_SLAVE_NUM_MMINFRA, IRQ_TYPE_MMINFRA}, {SLAVE_TYPE_MMUP, VIO_SLAVE_NUM_MMUP, IRQ_TYPE_MMUP}, }; static const struct INFRAAXI_ID_INFO infra_mi_id_to_master[] = { {"MD_AP_M", { 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"ADSPSYS_M0_M", { 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 } }, {"VLPSYS_M", { 1, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0 } }, {"SCP_M", { 1, 0, 0, 0, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0 } }, {"SSPM_M", { 1, 0, 0, 0, 1, 0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"SPM_M", { 1, 0, 0, 0, 1, 0, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"DXCC_M", { 1, 0, 0, 0, 1, 0, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 } }, {"CONN_M", { 1, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 } }, {"DEBUG_M", { 1, 0, 1, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0 } }, {"CPUM_M", { 1, 0, 1, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"CQDMA_M", { 1, 0, 1, 0, 1, 1, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"GPU_EB_M", { 1, 0, 1, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 0, 0, 0 } }, {"IPU_M", { 1, 0, 0, 1, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0 } }, {"INFRA_BUS_HRE_M", { 1, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"HWCCF_M", { 1, 0, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"THERM_M", { 1, 0, 1, 1, 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0 } }, {"THERM_M2", { 1, 0, 1, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0 } }, {"CCU_M", { 1, 0, 1, 1, 1, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0 } }, {"MCU_AP_M", { 0, 1, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, {"DPMAIF_M", { 0, 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"PERI2INFRA1_M", { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0 } }, {"APDMA_ext_M", { 0, 1, 0, 1, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0 } }, {"SSUSB_M", { 0, 1, 0, 1, 0, 0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"SSUSB2_M", { 0, 1, 0, 1, 0, 0, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"SPI0_M/SPI1_M/SPI2_M/PWM_M", { 0, 1, 0, 1, 0, 0, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"UFS_M", { 0, 1, 0, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, {"APDMA_int_M", { 0, 1, 0, 1, 0, 1, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0 } }, {"SPI3_M/SPI4_M/SPI5_M/SPI6_M", { 0, 1, 0, 1, 0, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"MSDC1_M/SPI7_M", { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"AFE_M", { 0, 1, 0, 1, 0, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0 } }, {"MM2SLB_M", { 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, {"MMUP2INFRA_M", { 0, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 1, 0 } }, {"GCE_D_M", { 0, 1, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 1, 0 } }, {"GCE_M_M", { 0, 1, 1, 1, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 1, 0 } }, }; static const struct ADSPAXI_ID_INFO ADSP_mi13_id_to_master[] = { {"DSP_M1", { 0, 0, 0, 2, 2, 2, 2, 0 } }, {"DMA_M1", { 0, 0, 1, 2, 0, 0, 0, 0 } }, {"DSP_M2", { 1, 0, 0, 2, 2, 2, 2, 0 } }, {"DMA_M2", { 1, 0, 1, 2, 0, 0, 0, 0 } }, {"AFE_M", { 0, 1, 2, 0, 0, 0, 0, 0 } }, }; static const struct ADSPAXI_ID_INFO ADSP_mi15_id_to_master[] = { {"DSP_M1", { 1, 0, 0, 2, 2, 2, 2, 0 } }, {"DMA_M1", { 1, 0, 1, 2, 0, 0, 0, 0 } }, {"DSP_M2", { 1, 1, 0, 2, 2, 2, 2, 0 } }, {"DMA_M2", { 1, 1, 1, 2, 0, 0, 0, 0 } }, {"AFE_M", { 0, 0, 2, 0, 0, 0, 0, 0 } }, }; static const char * const adsp_domain[] = { "AP", "SSPM", "CONN", "SCP", "MCUPM", "CCU", "others", "others", }; static const char * const mminfra_domain[] = { "AP", "SSPM", "CCU", "SCP", "GCE", "GZ", "MMuP", "others", }; static const char *infra_mi_trans(uint32_t bus_id) { int master_count = ARRAY_SIZE(infra_mi_id_to_master); const char *master = "UNKNOWN_MASTER_FROM_INFRA"; int i, j; for (i = 0; i < master_count; i++) { for (j = 0; j < INFRAAXI_MI_BIT_LENGTH; j++) { if (infra_mi_id_to_master[i].bit[j] == 2) continue; if (((bus_id >> j) & 0x1) == infra_mi_id_to_master[i].bit[j]) continue; break; } if (j == INFRAAXI_MI_BIT_LENGTH) { pr_info(PFX "%s %s %s\n", "catch it from INFRAAXI_MI", "Master is:", infra_mi_id_to_master[i].master); master = infra_mi_id_to_master[i].master; } } return master; } static const char *adsp_mi_trans(uint32_t bus_id, int mi) { int master_count = ARRAY_SIZE(infra_mi_id_to_master); const char *master = "UNKNOWN_MASTER_FROM_ADSP"; int i, j; const struct ADSPAXI_ID_INFO *ADSP_mi_id_to_master; if (mi == ADSP_MI13) ADSP_mi_id_to_master = ADSP_mi13_id_to_master; else ADSP_mi_id_to_master = ADSP_mi15_id_to_master; for (i = 0; i < master_count; i++) { for (j = 0; j < ADSPAXI_MI_BIT_LENGTH; j++) { if (ADSP_mi_id_to_master[i].bit[j] == 2) continue; if (((bus_id >> j) & 0x1) == ADSP_mi_id_to_master[i].bit[j]) continue; break; } if (j == ADSPAXI_MI_BIT_LENGTH) { pr_debug(PFX "%s %s %s\n", "catch it from ADSPAXI_MI", "Master is:", infra_mi_id_to_master[i].master); master = infra_mi_id_to_master[i].master; } } return master; } static const char *mt6886_bus_id_to_master(uint32_t bus_id, uint32_t vio_addr, int slave_type, int shift_sta_bit, uint32_t domain) { pr_debug(PFX "%s:0x%x, %s:0x%x, %s:0x%x, %s:%d\n", "bus_id", bus_id, "vio_addr", vio_addr, "slave_type", slave_type, "shift_sta_bit", shift_sta_bit); if (vio_addr <= SRAM_END_ADDR) { pr_info(PFX "vio_addr is from on-chip SRAMROM\n"); if ((bus_id & 0x1) == 0x0) return "NTH_EMI_GMC_M"; else return infra_mi_trans(bus_id >> 1); } else if ((vio_addr >= L3CACHE_0_START && vio_addr <= L3CACHE_0_END) || (vio_addr >= L3CACHE_1_START && vio_addr <= L3CACHE_1_END) || (vio_addr >= L3CACHE_2_START && vio_addr <= L3CACHE_2_END)) { pr_info(PFX "vio_addr is from L3Cache share SRAM\n"); if ((bus_id & 0x1) == 0x0) return "NTH_EMI_GMC_M"; else return infra_mi_trans(bus_id >> 1); } else if (slave_type == SLAVE_TYPE_VLP) { /* mi3 */ if ((vio_addr >= VLP_SCP_START_ADDR) && (vio_addr <= VLP_SCP_END_ADDR)) { if ((bus_id & 0x3) == 0x0) return "SSPM_M"; else if ((bus_id & 0x3) == 0x1) return "SPM_M"; else if ((bus_id & 0x3) == 0x2) return infra_mi_trans(bus_id >> 2); else return "UNKNOWN_MASTER_TO_SCP"; /* mi1 */ } else if ((vio_addr >= VLP_INFRA_START && vio_addr <= VLP_INFRA_END) || (vio_addr >= VLP_INFRA_1_START && vio_addr <= VLP_INFRA_1_END)) { if ((bus_id & 0x3) == 0x0) return "SCP_M"; else if ((bus_id & 0x3) == 0x1) return "SSPM_M"; else if ((bus_id & 0x3) == 0x2) return "SPM_M"; else return "DXCC_M"; /* mi2 */ } else { if ((bus_id & 0x3) == 0x0) return "SCP_M"; else if ((bus_id & 0x3) == 0x1) return "SSPM_M"; else if ((bus_id & 0x3) == 0x2) return "SPM_M"; else return infra_mi_trans(bus_id >> 2); } } else if (slave_type == SLAVE_TYPE_ADSP) { /* infra slave */ if ((vio_addr >= ADSP_INFRA_START && vio_addr <= ADSP_INFRA_END) || (vio_addr >= ADSP_INFRA_1_START && vio_addr <= ADSP_INFRA_1_END)) { return adsp_mi_trans(bus_id, ADSP_MI13); /* adsp misc slave */ } else if (vio_addr >= ADSP_OTHER_START && vio_addr <= ADSP_OTHER_END) { if ((bus_id & 0x1) == 0x1) return "HRE"; else if ((bus_id & 0x7) == 0x4) return adsp_domain[domain]; else return adsp_mi_trans(bus_id >> 1, ADSP_MI15); /* adsp audio_pwr, dsp_pwr slave */ } else { if ((bus_id & 0x3) == 0x2) return adsp_domain[domain]; else return adsp_mi_trans(bus_id, ADSP_MI15); } } else if (slave_type == SLAVE_TYPE_MMINFRA) { /* MM slave */ if (((vio_addr >= DISP_START_ADDR) && (vio_addr <= DISP_END_ADDR)) || ((vio_addr >= MML_START_ADDR) && (vio_addr <= MML_END_ADDR))) { if ((bus_id & 0x1) == 0x0) return "GCE_D"; else if ((bus_id & 0xF) == 0x1) return infra_mi_trans(bus_id >> 4); else if ((bus_id & 0xF) == 0x3) return "HRE"; else if ((bus_id & 0xF) == 0x5) return "MMUP"; else if ((bus_id & 0xF) == 0x7) return "GCE_D"; else if ((bus_id & 0xF) == 0x9) return "GCE_M"; else return NULL; /* ISP slave*/ } else if (((vio_addr >= IMG_START_ADDR) && (vio_addr <= IMG_END_ADDR)) || ((vio_addr >= CAM_START_ADDR) && (vio_addr <= CAM_END_ADDR)) || ((vio_addr >= CCU_START_ADDR) && (vio_addr <= CCU_END_ADDR))) { if ((bus_id & 0x1) == 0x0) return "GCE_M"; else if ((bus_id & 0xF) == 0x1) return infra_mi_trans(bus_id >> 4); else if ((bus_id & 0xF) == 0x3) return "HRE"; else if ((bus_id & 0xF) == 0x5) return "MMUP"; else if ((bus_id & 0xF) == 0x7) return "GCE_D"; else if ((bus_id & 0xF) == 0x9) return "GCE_M"; else return NULL; /* CODEC slave*/ } else if (((vio_addr >= VDEC_START_ADDR) && (vio_addr <= VDEC_END_ADDR)) || ((vio_addr >= VENC_START_ADDR) && (vio_addr <= VENC_END_ADDR)) || ((vio_addr >= MMUP_START_ADDR) && (vio_addr <= MMUP_END_ADDR))) { if ((bus_id & 0x3) == 0x0) return "MMUP"; else if ((bus_id & 0x3) == 0x1) return "GCE_M"; else if ((bus_id & 0x1F) == 0x2) return infra_mi_trans(bus_id >> 5); else if ((bus_id & 0x1F) == 0x6) return "HRE"; else if ((bus_id & 0x1F) == 0xA) return "MMUP"; else if ((bus_id & 0x1F) == 0xE) return "GCE_D"; else if ((bus_id & 0x1F) == 0x12) return "GCE_M"; else return NULL; /* other mminfra slave*/ } else { if ((bus_id & 0x7) == 0x0) return infra_mi_trans(bus_id >> 3); else if ((bus_id & 0x7) == 0x1) return "HRE"; else if ((bus_id & 0x7) == 0x2) return "MMUP"; else if ((bus_id & 0x7) == 0x3) return "GCE_D"; else if ((bus_id & 0x7) == 0x4) return "GCE_M"; else return NULL; } } else if (slave_type == SLAVE_TYPE_MMUP) { return mminfra_domain[domain]; } else { return infra_mi_trans(bus_id); } } /* violation index corresponds to subsys */ const char *index_to_subsys(int slave_type, uint32_t vio_index, uint32_t vio_addr) { int i; pr_debug(PFX "%s %s %d, %s %d, %s 0x%x\n", __func__, "slave_type", slave_type, "vio_index", vio_index, "vio_addr", vio_addr); /* Filter by violation index */ if (slave_type == SLAVE_TYPE_INFRA) { for (i = 0; i < VIO_SLAVE_NUM_INFRA; i++) { if (vio_index == mt6886_devices_infra[i].vio_index) return mt6886_devices_infra[i].device; } } else if (slave_type == SLAVE_TYPE_INFRA1) { for (i = 0; i < VIO_SLAVE_NUM_INFRA1; i++) { if (vio_index == mt6886_devices_infra1[i].vio_index) return mt6886_devices_infra1[i].device; } } else if (slave_type == SLAVE_TYPE_PERI_PAR) { for (i = 0; i < VIO_SLAVE_NUM_PERI_PAR; i++) { if (vio_index == mt6886_devices_peri_par[i].vio_index) return mt6886_devices_peri_par[i].device; } } else if (slave_type == SLAVE_TYPE_VLP) { for (i = 0; i < VIO_SLAVE_NUM_VLP; i++) { if (vio_index == mt6886_devices_vlp[i].vio_index) return mt6886_devices_vlp[i].device; } } else if (slave_type == SLAVE_TYPE_ADSP) { for (i = 0; i < VIO_SLAVE_NUM_ADSP; i++) { if (vio_index == mt6886_devices_adsp[i].vio_index) return mt6886_devices_adsp[i].device; } } else if (slave_type == SLAVE_TYPE_MMINFRA) { for (i = 0; i < VIO_SLAVE_NUM_MMINFRA; i++) { if (vio_index == mt6886_devices_mminfra[i].vio_index) return mt6886_devices_mminfra[i].device; } } else if (slave_type == SLAVE_TYPE_MMUP) { for (i = 0; i < VIO_SLAVE_NUM_MMUP; i++) { if (vio_index == mt6886_devices_mmup[i].vio_index) return mt6886_devices_mmup[i].device; } } return "OUT_OF_BOUND"; } static void mm2nd_vio_handler(void __iomem *infracfg, struct mtk_devapc_vio_info *vio_info, bool mdp_vio, bool disp2_vio, bool mmsys_vio) { uint32_t vio_sta, vio_dbg, rw; uint32_t vio_sta_num; uint32_t vio0_offset; char mm_str[64] = {0}; void __iomem *reg; int i; if (!infracfg) { pr_err(PFX "%s, param check failed, infracfg ptr is NULL\n", __func__); return; } if (mdp_vio) { vio_sta_num = INFRACFG_MDP_VIO_STA_NUM; vio0_offset = INFRACFG_MDP_SEC_VIO0_OFFSET; strncpy(mm_str, "INFRACFG_MDP_SEC_VIO", sizeof(mm_str)); } else if (disp2_vio) { vio_sta_num = INFRACFG_DISP2_VIO_STA_NUM; vio0_offset = INFRACFG_DISP2_SEC_VIO0_OFFSET; strncpy(mm_str, "INFRACFG_DISP2_SEC_VIO", sizeof(mm_str)); } else if (mmsys_vio) { vio_sta_num = INFRACFG_MM_VIO_STA_NUM; vio0_offset = INFRACFG_MM_SEC_VIO0_OFFSET; strncpy(mm_str, "INFRACFG_MM_SEC_VIO", sizeof(mm_str)); } else { pr_err(PFX "%s: param check failed, %s:%s, %s:%s, %s:%s\n", __func__, "mdp_vio", mdp_vio ? "true" : "false", "disp2_vio", disp2_vio ? "true" : "false", "mmsys_vio", mmsys_vio ? "true" : "false"); return; } /* Get mm2nd violation status */ for (i = 0; i < vio_sta_num; i++) { reg = infracfg + vio0_offset + i * 4; vio_sta = readl(reg); if (vio_sta) pr_info(PFX "MM 2nd violation: %s%d:0x%x\n", mm_str, i, vio_sta); } /* Get mm2nd violation address */ reg = infracfg + vio0_offset + i * 4; vio_info->vio_addr = readl(reg); /* Get mm2nd violation information */ reg = infracfg + vio0_offset + (i + 1) * 4; vio_dbg = readl(reg); vio_info->domain_id = (vio_dbg & INFRACFG_MM2ND_VIO_DOMAIN_MASK) >> INFRACFG_MM2ND_VIO_DOMAIN_SHIFT; vio_info->master_id = (vio_dbg & INFRACFG_MM2ND_VIO_ID_MASK) >> INFRACFG_MM2ND_VIO_ID_SHIFT; rw = (vio_dbg & INFRACFG_MM2ND_VIO_RW_MASK) >> INFRACFG_MM2ND_VIO_RW_SHIFT; vio_info->read = (rw == 0); vio_info->write = (rw == 1); } static uint32_t mt6886_shift_group_get(int slave_type, uint32_t vio_idx) { return 31; } void devapc_catch_illegal_range(phys_addr_t phys_addr, size_t size) { phys_addr_t test_pa = 0x17a54c50; /* * Catch BROM addr mapped */ if (phys_addr >= 0x0 && phys_addr < SRAM_START_ADDR) { pr_err(PFX "%s %s:(%pa), %s:(0x%lx)\n", "catch BROM address mapped!", "phys_addr", &phys_addr, "size", size); BUG_ON(1); } if ((phys_addr <= test_pa) && (phys_addr + size > test_pa)) { pr_err(PFX "%s %s:(%pa), %s:(0x%lx), %s:(%pa)\n", "catch VENCSYS address mapped!", "phys_addr", &phys_addr, "size", size, "test_pa", &test_pa); BUG_ON(1); } } static struct mtk_devapc_dbg_status mt6886_devapc_dbg_stat = { .enable_ut = PLAT_DBG_UT_DEFAULT, .enable_KE = PLAT_DBG_KE_DEFAULT, .enable_AEE = PLAT_DBG_AEE_DEFAULT, .enable_WARN = PLAT_DBG_WARN_DEFAULT, .enable_dapc = PLAT_DBG_DAPC_DEFAULT, }; static const char * const slave_type_to_str[] = { "SLAVE_TYPE_INFRA", "SLAVE_TYPE_INFRA1", "SLAVE_TYPE_PERI_PAR", "SLAVE_TYPE_VLP", "SLAVE_TYPE_ADSP", "SLAVE_TYPE_MMINFRA", "SLAVE_TYPE_MMUP", "WRONG_SLAVE_TYPE", }; static int mtk_vio_mask_sta_num[] = { VIO_MASK_STA_NUM_INFRA, VIO_MASK_STA_NUM_INFRA1, VIO_MASK_STA_NUM_PERI_PAR, VIO_MASK_STA_NUM_VLP, VIO_MASK_STA_NUM_ADSP, VIO_MASK_STA_NUM_MMINFRA, VIO_MASK_STA_NUM_MMUP, }; static struct mtk_devapc_vio_info mt6886_devapc_vio_info = { .vio_mask_sta_num = mtk_vio_mask_sta_num, .sramrom_vio_idx = SRAMROM_VIO_INDEX, .mdp_vio_idx = MDP_VIO_INDEX, .disp2_vio_idx = DISP2_VIO_INDEX, .mmsys_vio_idx = MMSYS_VIO_INDEX, .sramrom_slv_type = SRAMROM_SLAVE_TYPE, .mm2nd_slv_type = MM2ND_SLAVE_TYPE, }; static const struct mtk_infra_vio_dbg_desc mt6886_vio_dbgs = { .vio_dbg_mstid = INFRA_VIO_DBG_MSTID, .vio_dbg_mstid_start_bit = INFRA_VIO_DBG_MSTID_START_BIT, .vio_dbg_dmnid = INFRA_VIO_DBG_DMNID, .vio_dbg_dmnid_start_bit = INFRA_VIO_DBG_DMNID_START_BIT, .vio_dbg_w_vio = INFRA_VIO_DBG_W_VIO, .vio_dbg_w_vio_start_bit = INFRA_VIO_DBG_W_VIO_START_BIT, .vio_dbg_r_vio = INFRA_VIO_DBG_R_VIO, .vio_dbg_r_vio_start_bit = INFRA_VIO_DBG_R_VIO_START_BIT, .vio_addr_high = INFRA_VIO_ADDR_HIGH, .vio_addr_high_start_bit = INFRA_VIO_ADDR_HIGH_START_BIT, }; static const struct mtk_sramrom_sec_vio_desc mt6886_sramrom_sec_vios = { .vio_id_mask = SRAMROM_SEC_VIO_ID_MASK, .vio_id_shift = SRAMROM_SEC_VIO_ID_SHIFT, .vio_domain_mask = SRAMROM_SEC_VIO_DOMAIN_MASK, .vio_domain_shift = SRAMROM_SEC_VIO_DOMAIN_SHIFT, .vio_rw_mask = SRAMROM_SEC_VIO_RW_MASK, .vio_rw_shift = SRAMROM_SEC_VIO_RW_SHIFT, }; static const uint32_t mt6886_devapc_pds[] = { PD_VIO_MASK_OFFSET, PD_VIO_STA_OFFSET, PD_VIO_DBG0_OFFSET, PD_VIO_DBG1_OFFSET, PD_VIO_DBG2_OFFSET, PD_APC_CON_OFFSET, PD_SHIFT_STA_OFFSET, PD_SHIFT_SEL_OFFSET, PD_SHIFT_CON_OFFSET, PD_VIO_DBG3_OFFSET, }; static struct mtk_devapc_soc mt6886_data = { .dbg_stat = &mt6886_devapc_dbg_stat, .slave_type_arr = slave_type_to_str, .slave_type_num = SLAVE_TYPE_NUM, .device_info[SLAVE_TYPE_INFRA] = mt6886_devices_infra, .device_info[SLAVE_TYPE_INFRA1] = mt6886_devices_infra1, .device_info[SLAVE_TYPE_PERI_PAR] = mt6886_devices_peri_par, .device_info[SLAVE_TYPE_VLP] = mt6886_devices_vlp, .device_info[SLAVE_TYPE_ADSP] = mt6886_devices_adsp, .device_info[SLAVE_TYPE_MMINFRA] = mt6886_devices_mminfra, .device_info[SLAVE_TYPE_MMUP] = mt6886_devices_mmup, .ndevices = mtk6886_devices_num, .vio_info = &mt6886_devapc_vio_info, .vio_dbgs = &mt6886_vio_dbgs, .sramrom_sec_vios = &mt6886_sramrom_sec_vios, .devapc_pds = mt6886_devapc_pds, .irq_type_num = IRQ_TYPE_NUM, .subsys_get = &index_to_subsys, .master_get = &mt6886_bus_id_to_master, .mm2nd_vio_handler = &mm2nd_vio_handler, .shift_group_get = mt6886_shift_group_get, }; static const struct of_device_id mt6886_devapc_dt_match[] = { { .compatible = "mediatek,mt6886-devapc" }, {}, }; static const struct dev_pm_ops devapc_dev_pm_ops = { .suspend_noirq = devapc_suspend_noirq, .resume_noirq = devapc_resume_noirq, }; static int mt6886_devapc_probe(struct platform_device *pdev) { return mtk_devapc_probe(pdev, &mt6886_data); } static int mt6886_devapc_remove(struct platform_device *dev) { return mtk_devapc_remove(dev); } static struct platform_driver mt6886_devapc_driver = { .probe = mt6886_devapc_probe, .remove = mt6886_devapc_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = mt6886_devapc_dt_match, .pm = &devapc_dev_pm_ops, }, }; module_platform_driver(mt6886_devapc_driver); MODULE_DESCRIPTION("Mediatek MT6886 Device APC Driver"); MODULE_AUTHOR("Louis Yeh "); MODULE_LICENSE("GPL");