| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (C) 2020 MediaTek Inc. |
| */ |
| |
| #include <linux/bug.h> |
| #include <linux/module.h> |
| #include <linux/of.h> |
| #include <linux/platform_device.h> |
| #include <linux/io.h> |
| |
| #include "devapc-mt6893.h" |
| |
| static const struct mtk_device_num mtk6893_devices_num[] = { |
| {SLAVE_TYPE_INFRA, VIO_SLAVE_NUM_INFRA}, |
| {SLAVE_TYPE_PERI, VIO_SLAVE_NUM_PERI}, |
| {SLAVE_TYPE_PERI2, VIO_SLAVE_NUM_PERI2}, |
| }; |
| |
| static const struct PERIAXI_ID_INFO peri_mi_id_to_master[] = { |
| {"THERM2", { 0, 0, 0 } }, |
| {"SPM", { 0, 1, 0 } }, |
| {"CCU", { 0, 0, 1 } }, |
| {"THERM", { 0, 1, 1 } }, |
| {"SPM_DRAMC", { 1, 1, 0 } }, |
| }; |
| |
| static const struct INFRAAXI_ID_INFO infra_mi_id_to_master[] = { |
| {"CONNSYS_WFDMA", { 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2 } }, |
| {"CONNSYS_ICAP", { 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2 } }, |
| {"CONNSYS_WF_MCU", { 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2 } }, |
| {"CONNSYS_BT_MCU", { 0, 0, 0, 0, 1, 0, 0, 1, 2, 2, 2, 2, 2 } }, |
| {"CONNSYS_GPS", { 0, 0, 0, 0, 1, 0, 0, 0, 2, 2, 2, 2, 2 } }, |
| {"Tinysys", { 0, 1, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0 } }, |
| {"GCE_M2", { 0, 0, 1, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0 } }, |
| {"CQ_DMA", { 0, 0, 1, 0, 1, 0, 0, 2, 2, 2, 0, 0, 0 } }, |
| {"DebugTop", { 0, 0, 1, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0 } }, |
| {"SSUSB", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2 } }, |
| {"PWM", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0 } }, |
| {"MSDC1", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0 } }, |
| {"SPI6", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 } }, |
| {"SPI0", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 } }, |
| {"APU", { 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 2, 2, 0 } }, |
| {"MSDC0", { 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 2, 2, 0 } }, |
| {"SPI2", { 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0 } }, |
| {"SPI3", { 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0 } }, |
| {"SPI4", { 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0 } }, |
| {"SPI5", { 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0 } }, |
| {"SPI7", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0 } }, |
| {"Audio", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 } }, |
| {"SPI1", { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 } }, |
| {"AP_DMA_EXT", { 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 2, 2, 2 } }, |
| {"THERM2", { 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0 } }, |
| {"SPM", { 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 } }, |
| {"CCU", { 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } }, |
| {"THERM", { 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0 } }, |
| {"DX_CC", { 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 2, 0, 0 } }, |
| {"GCE_M", { 0, 0, 1, 0, 1, 0, 1, 2, 2, 0, 0, 0, 0 } }, |
| {"DPMAIF", { 0, 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0 } }, |
| {"MCUPM", { 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, |
| {"SSPM", { 0, 1, 0, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0 } }, |
| {"UFS", { 0, 0, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0 } }, |
| {"APMCU_write", { 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, |
| {"APMCU_write", { 1, 2, 2, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0 } }, |
| {"APMCU_write", { 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 2, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0 } }, |
| {"APMCU_read", { 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0 } }, |
| }; |
| |
| 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_debug(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 *peri_mi_trans(uint32_t bus_id) |
| { |
| int master_count = ARRAY_SIZE(peri_mi_id_to_master); |
| const char *master = "UNKNOWN_MASTER_FROM_PERI"; |
| int i, j; |
| |
| if ((bus_id & 0x3) == 0x0) |
| return infra_mi_trans(bus_id >> 2); |
| else if ((bus_id & 0x3) == 0x2) |
| return "MD_AP_M"; |
| else if ((bus_id & 0x3) == 0x3) |
| return "AP_DMA_M"; |
| |
| for (i = 0 ; i < master_count; i++) { |
| for (j = 0 ; j < PERIAXI_MI_BIT_LENGTH ; j++) { |
| if (peri_mi_id_to_master[i].bit[j] == 2) |
| continue; |
| if (((bus_id >> j) & 0x1) == |
| peri_mi_id_to_master[i].bit[j]) |
| continue; |
| break; |
| } |
| if (j == PERIAXI_MI_BIT_LENGTH) { |
| pr_debug(PFX "%s %s %s\n", |
| "catch it from PERIAXI_MI.", |
| "Master is:", |
| peri_mi_id_to_master[i].master); |
| master = peri_mi_id_to_master[i].master; |
| } |
| } |
| |
| return master; |
| } |
| |
| static const char *mt6893_bus_id_to_master(uint32_t bus_id, uint32_t vio_addr, |
| int slave_type, int shift_sta_bit, int domain) |
| { |
| uint16_t h_2byte; |
| uint8_t h_1byte; |
| |
| UNUSED(slave_type); |
| UNUSED(shift_sta_bit); |
| |
| pr_debug(PFX "[DEVAPC] bus_id:0x%x, vio_addr:0x%x\n", |
| bus_id, vio_addr); |
| |
| if (bus_id == 0x0 && vio_addr == 0x0) |
| return NULL; |
| |
| /* bus only reference bit 0~29 */ |
| vio_addr = vio_addr & 0x3FFFFFFF; |
| |
| h_1byte = (vio_addr >> 24) & 0xFF; |
| h_2byte = (vio_addr >> 16) & 0xFFFF; |
| |
| if ((vio_addr >= TINYSYS_START_ADDR && vio_addr <= TINYSYS_END_ADDR) || |
| (vio_addr >= MD_START_ADDR && vio_addr <= MD_END_ADDR)) { |
| pr_info(PFX "[DEVAPC] bus_id might be wrong\n"); |
| |
| if (domain == 0x1) |
| return "SSPM"; |
| else if (domain == 0x2) |
| return "CONNSYS"; |
| |
| } else if (vio_addr >= CONN_START_ADDR && vio_addr <= CONN_END_ADDR) { |
| pr_info(PFX "[DEVAPC] bus_id might be wrong\n"); |
| |
| if (domain == 0x1) |
| return "MD"; |
| else if (domain == 0x2) |
| return "ADSP"; |
| } |
| |
| if (h_2byte < 0x0C51 || (h_2byte >= 0x0C80 && h_2byte < 0x0CC0)) { |
| pr_debug(PFX "vio_addr is from L3C or on-chip SRAMROM\n"); |
| if ((bus_id & 0x1) == 1) |
| return "EMI_L2C_M"; |
| |
| return infra_mi_trans(bus_id >> 1); |
| |
| } else if (h_1byte == 0x15 || h_1byte == 0x1A || h_1byte == 0x1B || |
| h_1byte == 0x1F) { |
| pr_debug(PFX "vio_addr is from MDP System\n"); |
| if ((bus_id & 0x1) == 0) |
| return "GCE_M2"; |
| |
| return infra_mi_trans(bus_id >> 1); |
| |
| } else if (h_2byte >= 0x1410 && h_2byte < 0x1420) { |
| pr_debug(PFX "vio_addr is from DISP-2 MM System\n"); |
| if ((bus_id & 0x1) == 1) |
| return "GCE_M"; |
| else if ((bus_id >> 3) == 0) |
| pr_info(PFX "Master might be %s\n", "GCE_M2"); |
| |
| return infra_mi_trans(bus_id >> 1); |
| |
| } else if (h_1byte == 0x14 || h_1byte == 0x16 || h_1byte == 0x17) { |
| pr_debug(PFX "vio_addr is from DISP MM System\n"); |
| if ((bus_id & 0x1) == 1) |
| return "GCE_M"; |
| |
| return infra_mi_trans(bus_id >> 1); |
| |
| } else if (h_1byte == 0x13 || h_1byte == 0x19) { |
| pr_debug(PFX "vio_addr is from APU or GPU\n"); |
| return infra_mi_trans(bus_id); |
| |
| } else if (h_2byte >= 0x1050 && h_2byte < 0x1090) { |
| pr_debug(PFX "vio_addr is from Tinysys\n"); |
| if ((bus_id & 0x1) == 0) |
| return "MD_AP_M"; |
| |
| return peri_mi_trans(bus_id >> 1); |
| |
| } else if (h_2byte >= 0x1040 && h_2byte < 0x1050) { |
| pr_debug(PFX "vio_addr is from PWR_MD32\n"); |
| if ((bus_id & 0x1) == 0) |
| return "MD_AP_M"; |
| |
| return peri_mi_trans(bus_id >> 1); |
| |
| } else if (h_2byte >= 0x1120 && h_2byte < 0x1121) { |
| pr_debug(PFX "vio_addr is from SSUSB\n"); |
| if ((bus_id & 0x1) == 0) |
| return "MD_AP_M"; |
| |
| return peri_mi_trans(bus_id >> 1); |
| |
| } else { |
| return peri_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; |
| |
| if (slave_type == SLAVE_TYPE_INFRA && |
| vio_index < VIO_SLAVE_NUM_INFRA) { |
| |
| /* check violation address */ |
| if (vio_addr >= MFG_START_ADDR && vio_addr <= MFG_END_ADDR) |
| return "MFGSYS"; |
| |
| /* check violation index */ |
| if (vio_index == SMI_LARB0_VIO_INDEX || |
| vio_index == SMI_LARB1_VIO_INDEX || |
| vio_index == SMI_LARB2_VIO_INDEX || |
| vio_index == SMI_LARB3_VIO_INDEX || |
| vio_index == SMI_LARB4_VIO_INDEX || |
| vio_index == SMI_LARB5_VIO_INDEX || |
| vio_index == SMI_LARB6_VIO_INDEX || |
| vio_index == SMI_LARB7_VIO_INDEX || |
| vio_index == SMI_LARB8_VIO_INDEX || |
| vio_index == SMI_LARB9_VIO_INDEX || |
| vio_index == SMI_LARB10_VIO_INDEX || |
| vio_index == SMI_LARB11_VIO_INDEX || |
| vio_index == SMI_LARB12_VIO_INDEX || |
| vio_index == SMI_LARB13_VIO_INDEX || |
| vio_index == SMI_LARB14_VIO_INDEX || |
| vio_index == SMI_LARB15_VIO_INDEX || |
| vio_index == SMI_LARB16_VIO_INDEX || |
| vio_index == SMI_LARB17_VIO_INDEX || |
| vio_index == SMI_LARB18_VIO_INDEX || |
| vio_index == SMI_LARB19_VIO_INDEX || |
| vio_index == SMI_LARB20_VIO_INDEX) |
| return "SMI"; |
| |
| if (vio_index == IOMMU0_VIO_INDEX || |
| vio_index == IOMMU1_VIO_INDEX || |
| vio_index == IOMMU0_SEC_VIO_INDEX || |
| vio_index == IOMMU1_SEC_VIO_INDEX) |
| return "IOMMU"; |
| |
| else if (vio_index >= CAM_SENINF_START && |
| vio_index <= CAM_SENINF_END) |
| return "CAMSYS_SENINF"; |
| |
| switch (vio_index) { |
| case MFG_START ... MFG_END: |
| return "MFGSYS"; |
| case MM_DISP_START ... MM_DISP_END: |
| case MM_DISP2_START ... MM_DISP2_END: |
| return "MMSYS_DISP"; |
| case MM_SSRAM_VIO_INDEX: |
| case MM_MDP_START ... MM_MDP_END: |
| return "MMSYS_MDP"; |
| case IMG_START ... IMG_END: |
| return "IMGSYS"; |
| case VDEC_START ... VDEC_END: |
| return "VDECSYS"; |
| case VENC_START ... VENC_END: |
| return "VENCSYS"; |
| case APU_SSRAM_VIO_INDEX: |
| case APU_START ... APU_END: |
| return "APUSYS"; |
| case CAM_CCU_START ... CAM_CCU_END: |
| return "CAMSYS_CCU"; |
| case CAM_START ... CAM_END: |
| return "CAMSYS"; |
| case IPE_START ... IPE_END: |
| return "IPESYS"; |
| case MDP_START ... MDP_END: |
| return "MMSYS_MDP"; |
| default: |
| break; |
| } |
| |
| for (i = 0; i < VIO_SLAVE_NUM_INFRA; i++) { |
| if (vio_index == mt6893_devices_infra[i].vio_index) |
| return mt6893_devices_infra[i].device; |
| } |
| |
| } else if (slave_type == SLAVE_TYPE_PERI && |
| vio_index < VIO_SLAVE_NUM_PERI) { |
| |
| /* check violation index */ |
| switch (vio_index) { |
| case TINY_START ... TINY_END: |
| return "TINYSYS"; |
| case MD_START ... MD_END: |
| return "MDSYS"; |
| case CONN_VIO_INDEX: |
| return "CONNSYS"; |
| default: |
| break; |
| } |
| |
| for (i = 0; i < VIO_SLAVE_NUM_PERI; i++) { |
| if (vio_index == mt6893_devices_peri[i].vio_index) |
| return mt6893_devices_peri[i].device; |
| } |
| |
| } else if (slave_type == SLAVE_TYPE_PERI2 && |
| vio_index < VIO_SLAVE_NUM_PERI2) { |
| |
| /* check violation address */ |
| if ((vio_addr >= GCE_START_ADDR && vio_addr <= GCE_END_ADDR) || |
| (vio_addr >= GCE_M2_START_ADDR && |
| vio_addr <= GCE_M2_END_ADDR)) |
| return "GCE"; |
| |
| for (i = 0; i < VIO_SLAVE_NUM_PERI2; i++) { |
| if (vio_index == mt6893_devices_peri2[i].vio_index) |
| return mt6893_devices_peri2[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 mt6893_shift_group_get(int slave_type, uint32_t vio_idx) |
| { |
| if (slave_type == SLAVE_TYPE_INFRA) { |
| if ((vio_idx >= 0 && vio_idx <= 8) || vio_idx == 412) |
| return 0; |
| else if ((vio_idx >= 9 && vio_idx <= 14) || vio_idx == 413) |
| return 1; |
| else if ((vio_idx >= 15 && vio_idx <= 16) || vio_idx == 414) |
| return 2; |
| else if ((vio_idx >= 17 && vio_idx <= 18) || vio_idx == 415) |
| return 3; |
| else if (vio_idx >= 19 && vio_idx <= 70) |
| return 4; |
| else if (vio_idx >= 71 && vio_idx <= 369) |
| return 5; |
| else if (vio_idx >= 370 && vio_idx <= 409) |
| return 6; |
| else if (vio_idx == 410 || vio_idx == 416) |
| return 7; |
| else if (vio_idx == 411 || vio_idx == 417) |
| return 8; |
| |
| pr_err(PFX "%s:%d Wrong vio_idx:0x%x\n", |
| __func__, __LINE__, vio_idx); |
| |
| } else if (slave_type == SLAVE_TYPE_PERI) { |
| if (vio_idx >= 0 && vio_idx <= 4) |
| return 0; |
| else if (vio_idx >= 5 && vio_idx <= 6) |
| return 1; |
| else if ((vio_idx >= 7 && vio_idx <= 38) || vio_idx == 216 || |
| (vio_idx >= 217 && vio_idx <= 248) || |
| vio_idx == 346) |
| return 2; |
| else if ((vio_idx >= 39 && vio_idx <= 61) || vio_idx == 249) |
| return 3; |
| else if ((vio_idx >= 62 && vio_idx <= 72) || vio_idx == 250) |
| return 4; |
| else if ((vio_idx >= 73 && vio_idx <= 74) || vio_idx == 251) |
| return 5; |
| else if ((vio_idx >= 75 && vio_idx <= 78) || vio_idx == 252) |
| return 6; |
| else if ((vio_idx >= 79 && vio_idx <= 121) || vio_idx == 253) |
| return 7; |
| else if ((vio_idx >= 122 && vio_idx <= 124) || vio_idx == 254) |
| return 8; |
| else if (vio_idx == 125 || vio_idx == 255 || |
| vio_idx == 256 || vio_idx == 347) |
| return 9; |
| else if (vio_idx == 126 || vio_idx == 257) |
| return 10; |
| else if (vio_idx == 127 || vio_idx == 128) |
| return 11; |
| else if (vio_idx == 129 || vio_idx == 130) |
| return 12; |
| else if ((vio_idx >= 131 && vio_idx <= 142) || |
| (vio_idx >= 258 && vio_idx <= 269) || |
| vio_idx == 348) |
| return 13; |
| else if ((vio_idx >= 143 && vio_idx <= 172) || vio_idx == 270 || |
| (vio_idx >= 271 && vio_idx <= 300) || |
| vio_idx == 349) |
| return 14; |
| else if ((vio_idx >= 173 && vio_idx <= 202) || vio_idx == 301 || |
| (vio_idx >= 302 && vio_idx <= 331) || |
| vio_idx == 350) |
| return 15; |
| else if ((vio_idx >= 203 && vio_idx <= 215) || |
| (vio_idx >= 332 && vio_idx <= 345) || |
| vio_idx == 351) |
| return 16; |
| |
| pr_err(PFX "%s:%d Wrong vio_idx:0x%x\n", |
| __func__, __LINE__, vio_idx); |
| |
| } else if (slave_type == SLAVE_TYPE_PERI2) { |
| if ((vio_idx >= 0 && vio_idx <= 8) || |
| (vio_idx >= 130 && vio_idx <= 139) || |
| vio_idx == 252) |
| return 0; |
| else if (vio_idx >= 9 && vio_idx <= 12) |
| return 1; |
| else if (vio_idx >= 13 && vio_idx <= 16) |
| return 2; |
| else if (vio_idx >= 17 && vio_idx <= 20) |
| return 3; |
| else if (vio_idx >= 21 && vio_idx <= 24) |
| return 4; |
| else if ((vio_idx >= 25 && vio_idx <= 40) || |
| (vio_idx >= 140 && vio_idx <= 156) || |
| vio_idx == 253) |
| return 5; |
| else if ((vio_idx >= 41 && vio_idx <= 48) || |
| (vio_idx >= 157 && vio_idx <= 165) || |
| vio_idx == 254) |
| return 6; |
| else if ((vio_idx >= 49 && vio_idx <= 64) || |
| (vio_idx >= 166 && vio_idx <= 182) || |
| vio_idx == 255) |
| return 7; |
| else if ((vio_idx >= 65 && vio_idx <= 80) || |
| (vio_idx >= 183 && vio_idx <= 199) || |
| vio_idx == 256) |
| return 8; |
| else if ((vio_idx >= 81 && vio_idx <= 88) || |
| (vio_idx >= 200 && vio_idx <= 208) || |
| vio_idx == 257) |
| return 9; |
| else if ((vio_idx >= 89 && vio_idx <= 111) || |
| (vio_idx >= 209 && vio_idx <= 232) || |
| vio_idx == 258) |
| return 10; |
| else if ((vio_idx >= 40 && vio_idx <= 112) || |
| (vio_idx >= 233 && vio_idx <= 251) || |
| vio_idx == 259) |
| return 11; |
| |
| pr_err(PFX "%s:%d Wrong vio_idx:0x%x\n", |
| __func__, __LINE__, vio_idx); |
| |
| } else { |
| pr_err(PFX "%s:%d Wrong slave_type:0x%x\n", |
| __func__, __LINE__, slave_type); |
| } |
| |
| 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 mt6893_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_PERI", |
| "SLAVE_TYPE_PERI2", |
| "WRONG_SLAVE_TYPE", |
| }; |
| |
| static int mtk_vio_mask_sta_num[] = { |
| VIO_MASK_STA_NUM_INFRA, |
| VIO_MASK_STA_NUM_PERI, |
| VIO_MASK_STA_NUM_PERI2, |
| }; |
| |
| static struct mtk_devapc_vio_info mt6893_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 mt6893_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 mt6893_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 mt6893_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 mt6893_data = { |
| .dbg_stat = &mt6893_devapc_dbg_stat, |
| .slave_type_arr = slave_type_to_str, |
| .slave_type_num = SLAVE_TYPE_NUM, |
| .device_info[SLAVE_TYPE_INFRA] = mt6893_devices_infra, |
| .device_info[SLAVE_TYPE_PERI] = mt6893_devices_peri, |
| .device_info[SLAVE_TYPE_PERI2] = mt6893_devices_peri2, |
| .ndevices = mtk6893_devices_num, |
| .vio_info = &mt6893_devapc_vio_info, |
| .vio_dbgs = &mt6893_vio_dbgs, |
| .sramrom_sec_vios = &mt6893_sramrom_sec_vios, |
| .devapc_pds = mt6893_devapc_pds, |
| .subsys_get = &index_to_subsys, |
| .master_get = &mt6893_bus_id_to_master, |
| .mm2nd_vio_handler = &mm2nd_vio_handler, |
| .shift_group_get = mt6893_shift_group_get, |
| }; |
| |
| static const struct of_device_id mt6893_devapc_dt_match[] = { |
| { .compatible = "mediatek,mt6893-devapc" }, |
| {}, |
| }; |
| |
| static int mt6893_devapc_probe(struct platform_device *pdev) |
| { |
| return mtk_devapc_probe(pdev, &mt6893_data); |
| } |
| |
| static int mt6893_devapc_remove(struct platform_device *dev) |
| { |
| return mtk_devapc_remove(dev); |
| } |
| |
| static struct platform_driver mt6893_devapc_driver = { |
| .probe = mt6893_devapc_probe, |
| .remove = mt6893_devapc_remove, |
| .driver = { |
| .name = KBUILD_MODNAME, |
| .of_match_table = mt6893_devapc_dt_match, |
| }, |
| }; |
| |
| module_platform_driver(mt6893_devapc_driver); |
| |
| MODULE_DESCRIPTION("Mediatek MT6893 Device APC Driver"); |
| MODULE_AUTHOR("Neal Liu <neal.liu@mediatek.com>"); |
| MODULE_LICENSE("GPL"); |