| /* |
| * Copyright (C) 2018 MediaTek Inc. |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/sched.h> |
| #include <linux/device.h> |
| #include <linux/miscdevice.h> |
| #include <linux/module.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/string.h> |
| |
| #define MET_USER_EVENT_SUPPORT |
| #include "met_drv.h" |
| #include "trace.h" |
| #include "interface.h" |
| |
| #include "mtk_typedefs.h" |
| #include "core_plf_init.h" |
| /* #include "plf_trace.h" */ |
| #include "mtk_emi_bm.h" |
| |
| #ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT |
| #include "sspm/ondiemet_sspm.h" |
| #endif |
| |
| /*======================================================================*/ |
| /* Global variable definitions */ |
| /*======================================================================*/ |
| int emi_TP_busfiltr_enable; |
| static int msel_enable; |
| static unsigned int msel_group1 = _GP_1_Default; |
| static unsigned int msel_group2 = _GP_2_Default; |
| static unsigned int msel_group3 = _GP_3_Default; |
| |
| /* Global variables */ |
| static struct kobject *kobj_emi; |
| |
| static int ttype1_16_en = BM_TTYPE1_16_DISABLE; |
| static int ttype17_21_en = BM_TTYPE17_21_DISABLE; |
| |
| |
| |
| static int times; |
| static ssize_t test_store(struct kobject *kobj, |
| struct kobj_attribute *attr, |
| const char *buf, |
| size_t n) |
| { |
| int i; |
| unsigned int *src_addr_v; |
| dma_addr_t src_addr_p; |
| |
| if ((n == 0) || (buf == NULL)) |
| return -EINVAL; |
| if (kstrtoint(buf, 10, ×) != 0) |
| return -EINVAL; |
| if (times < 0) |
| return -EINVAL; |
| |
| if (times > 5000) |
| return -EINVAL; |
| |
| |
| src_addr_v = dma_alloc_coherent(met_device.this_device, |
| PAGE_SIZE, |
| &src_addr_p, |
| GFP_KERNEL); |
| if (src_addr_v == NULL) { |
| #ifdef CONFIG_MET_MODULE |
| met_tag_oneshot_real(0, "test dma alloc fail", PAGE_SIZE); |
| #else |
| met_tag_oneshot(0, "test dma alloc fail", PAGE_SIZE); |
| #endif |
| return -ENOMEM; |
| } |
| |
| preempt_disable(); |
| #ifdef CONFIG_MET_MODULE |
| met_tag_start_real(0, "TEST_EMI"); |
| #else |
| met_tag_start(0, "TEST_EMI"); |
| #endif |
| for (i = 0; i < times; i++) { |
| memset(src_addr_v, 2*i, PAGE_SIZE); |
| #ifdef CONFIG_MET_MODULE |
| met_tag_oneshot_real(0, "TEST_EMI", PAGE_SIZE); |
| #else |
| met_tag_oneshot(0, "TEST_EMI", PAGE_SIZE); |
| #endif |
| } |
| #ifdef CONFIG_MET_MODULE |
| met_tag_end_real(0, "TEST_EMI"); |
| #else |
| met_tag_end(0, "TEST_EMI"); |
| #endif |
| |
| my_preempt_enable(); |
| |
| if (src_addr_v != NULL) |
| dma_free_coherent(met_device.this_device, |
| PAGE_SIZE, |
| src_addr_v, |
| src_addr_p); |
| return n; |
| } |
| |
| /*======================================================================*/ |
| /* KOBJ Declarations */ |
| /*======================================================================*/ |
| DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable); |
| DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable); |
| DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= _ALL); |
| DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= _ALL); |
| DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= _ALL); |
| |
| |
| DECLARE_KOBJ_ATTR_STR_LIST_ITEM( |
| ttype1_16_en, |
| KOBJ_ITEM_LIST( |
| { BM_TTYPE1_16_ENABLE, "ENABLE" }, |
| { BM_TTYPE1_16_DISABLE, "DISABLE" } |
| ) |
| ); |
| DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en); |
| |
| |
| DECLARE_KOBJ_ATTR_STR_LIST_ITEM( |
| ttype17_21_en, |
| KOBJ_ITEM_LIST( |
| { BM_TTYPE17_21_ENABLE, "ENABLE" }, |
| { BM_TTYPE17_21_DISABLE, "DISABLE" } |
| ) |
| ); |
| DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en); |
| |
| DECLARE_KOBJ_ATTR_STR_LIST_ITEM( |
| ttype_master, |
| KOBJ_ITEM_LIST( |
| { _M0, "M0" }, |
| { _M1, "M1" }, |
| { _M2, "M2" }, |
| { _M3, "M3" }, |
| { _M4, "M4" }, |
| { _M5, "M5" }, |
| { _M6, "M6" }, |
| { _M7, "M7" } |
| ) |
| ); |
| |
| |
| DECLARE_KOBJ_ATTR_INT_LIST_ITEM( |
| ttype_nbeat, |
| KOBJ_ITEM_LIST( |
| { BM_TRANS_TYPE_1BEAT, 1 }, |
| { BM_TRANS_TYPE_2BEAT, 2 }, |
| { BM_TRANS_TYPE_3BEAT, 3 }, |
| { BM_TRANS_TYPE_4BEAT, 4 }, |
| { BM_TRANS_TYPE_5BEAT, 5 }, |
| { BM_TRANS_TYPE_6BEAT, 6 }, |
| { BM_TRANS_TYPE_7BEAT, 7 }, |
| { BM_TRANS_TYPE_8BEAT, 8 }, |
| { BM_TRANS_TYPE_9BEAT, 9 }, |
| { BM_TRANS_TYPE_10BEAT, 10 }, |
| { BM_TRANS_TYPE_11BEAT, 11 }, |
| { BM_TRANS_TYPE_12BEAT, 12 }, |
| { BM_TRANS_TYPE_13BEAT, 13 }, |
| { BM_TRANS_TYPE_14BEAT, 14 }, |
| { BM_TRANS_TYPE_15BEAT, 15 }, |
| { BM_TRANS_TYPE_16BEAT, 16 } |
| ) |
| ); |
| DECLARE_KOBJ_ATTR_INT_LIST_ITEM( |
| ttype_nbyte, |
| KOBJ_ITEM_LIST( |
| { BM_TRANS_TYPE_1Byte, 1 }, |
| { BM_TRANS_TYPE_2Byte, 2 }, |
| { BM_TRANS_TYPE_4Byte, 4 }, |
| { BM_TRANS_TYPE_8Byte, 8 }, |
| { BM_TRANS_TYPE_16Byte, 16 }, |
| { BM_TRANS_TYPE_32Byte, 32 } |
| ) |
| ); |
| DECLARE_KOBJ_ATTR_STR_LIST_ITEM( |
| ttype_burst, |
| KOBJ_ITEM_LIST( |
| { BM_TRANS_TYPE_BURST_INCR, "INCR" }, |
| { BM_TRANS_TYPE_BURST_WRAP, "WRAP" } |
| ) |
| ); |
| |
| DECLARE_KOBJ_ATTR_STR_LIST_ITEM( |
| ttype_rw, |
| KOBJ_ITEM_LIST( |
| { BM_TRANS_RW_DEFAULT, "DEFAULT" }, |
| { BM_TRANS_RW_READONLY, "R" }, |
| { BM_TRANS_RW_WRITEONLY, "W" }, |
| { BM_TRANS_RW_RWBOTH, "BOTH" } |
| ) |
| ); |
| |
| |
| DECLARE_KOBJ_ATTR_SHOW_INT(test, times); |
| |
| DECLARE_KOBJ_ATTR(test); |
| |
| |
| static int high_priority_filter; |
| DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter); |
| |
| |
| static int ttype_master_val[21]; |
| static int ttype_busid_val[21]; |
| static int ttype_nbeat_val[21]; |
| static int ttype_nbyte_val[21]; |
| static int ttype_burst_val[21]; |
| static int ttype_rw_val[21]; |
| |
| #define DECLARE_KOBJ_TTYPE_MASTER(nr) \ |
| DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master) |
| |
| #define DECLARE_KOBJ_TTYPE_NBEAT(nr) \ |
| DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat) |
| |
| #define DECLARE_KOBJ_TTYPE_NBYTE(nr) \ |
| DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte) |
| |
| #define DECLARE_KOBJ_TTYPE_BURST(nr) \ |
| DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst) |
| |
| #define DECLARE_KOBJ_TTYPE_RW(nr) \ |
| DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw) |
| |
| #define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \ |
| DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1]) |
| |
| DECLARE_KOBJ_TTYPE_MASTER(1); |
| DECLARE_KOBJ_TTYPE_NBEAT(1); |
| DECLARE_KOBJ_TTYPE_NBYTE(1); |
| DECLARE_KOBJ_TTYPE_BURST(1); |
| DECLARE_KOBJ_TTYPE_RW(1); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(1); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(2); |
| DECLARE_KOBJ_TTYPE_NBEAT(2); |
| DECLARE_KOBJ_TTYPE_NBYTE(2); |
| DECLARE_KOBJ_TTYPE_BURST(2); |
| DECLARE_KOBJ_TTYPE_RW(2); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(2); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(3); |
| DECLARE_KOBJ_TTYPE_NBEAT(3); |
| DECLARE_KOBJ_TTYPE_NBYTE(3); |
| DECLARE_KOBJ_TTYPE_BURST(3); |
| DECLARE_KOBJ_TTYPE_RW(3); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(3); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(4); |
| DECLARE_KOBJ_TTYPE_NBEAT(4); |
| DECLARE_KOBJ_TTYPE_NBYTE(4); |
| DECLARE_KOBJ_TTYPE_BURST(4); |
| DECLARE_KOBJ_TTYPE_RW(4); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(4); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(5); |
| DECLARE_KOBJ_TTYPE_NBEAT(5); |
| DECLARE_KOBJ_TTYPE_NBYTE(5); |
| DECLARE_KOBJ_TTYPE_BURST(5); |
| DECLARE_KOBJ_TTYPE_RW(5); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(5); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(6); |
| DECLARE_KOBJ_TTYPE_NBEAT(6); |
| DECLARE_KOBJ_TTYPE_NBYTE(6); |
| DECLARE_KOBJ_TTYPE_BURST(6); |
| DECLARE_KOBJ_TTYPE_RW(6); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(6); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(7); |
| DECLARE_KOBJ_TTYPE_NBEAT(7); |
| DECLARE_KOBJ_TTYPE_NBYTE(7); |
| DECLARE_KOBJ_TTYPE_BURST(7); |
| DECLARE_KOBJ_TTYPE_RW(7); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(7); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(8); |
| DECLARE_KOBJ_TTYPE_NBEAT(8); |
| DECLARE_KOBJ_TTYPE_NBYTE(8); |
| DECLARE_KOBJ_TTYPE_BURST(8); |
| DECLARE_KOBJ_TTYPE_RW(8); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(8); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(9); |
| DECLARE_KOBJ_TTYPE_NBEAT(9); |
| DECLARE_KOBJ_TTYPE_NBYTE(9); |
| DECLARE_KOBJ_TTYPE_BURST(9); |
| DECLARE_KOBJ_TTYPE_RW(9); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(9); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(10); |
| DECLARE_KOBJ_TTYPE_NBEAT(10); |
| DECLARE_KOBJ_TTYPE_NBYTE(10); |
| DECLARE_KOBJ_TTYPE_BURST(10); |
| DECLARE_KOBJ_TTYPE_RW(10); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(10); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(11); |
| DECLARE_KOBJ_TTYPE_NBEAT(11); |
| DECLARE_KOBJ_TTYPE_NBYTE(11); |
| DECLARE_KOBJ_TTYPE_BURST(11); |
| DECLARE_KOBJ_TTYPE_RW(11); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(11); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(12); |
| DECLARE_KOBJ_TTYPE_NBEAT(12); |
| DECLARE_KOBJ_TTYPE_NBYTE(12); |
| DECLARE_KOBJ_TTYPE_BURST(12); |
| DECLARE_KOBJ_TTYPE_RW(12); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(12); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(13); |
| DECLARE_KOBJ_TTYPE_NBEAT(13); |
| DECLARE_KOBJ_TTYPE_NBYTE(13); |
| DECLARE_KOBJ_TTYPE_BURST(13); |
| DECLARE_KOBJ_TTYPE_RW(13); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(13); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(14); |
| DECLARE_KOBJ_TTYPE_NBEAT(14); |
| DECLARE_KOBJ_TTYPE_NBYTE(14); |
| DECLARE_KOBJ_TTYPE_BURST(14); |
| DECLARE_KOBJ_TTYPE_RW(14); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(14); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(15); |
| DECLARE_KOBJ_TTYPE_NBEAT(15); |
| DECLARE_KOBJ_TTYPE_NBYTE(15); |
| DECLARE_KOBJ_TTYPE_BURST(15); |
| DECLARE_KOBJ_TTYPE_RW(15); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(15); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(16); |
| DECLARE_KOBJ_TTYPE_NBEAT(16); |
| DECLARE_KOBJ_TTYPE_NBYTE(16); |
| DECLARE_KOBJ_TTYPE_BURST(16); |
| DECLARE_KOBJ_TTYPE_RW(16); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(16); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(17); |
| DECLARE_KOBJ_TTYPE_NBEAT(17); |
| DECLARE_KOBJ_TTYPE_NBYTE(17); |
| DECLARE_KOBJ_TTYPE_BURST(17); |
| DECLARE_KOBJ_TTYPE_RW(17); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(17); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(18); |
| DECLARE_KOBJ_TTYPE_NBEAT(18); |
| DECLARE_KOBJ_TTYPE_NBYTE(18); |
| DECLARE_KOBJ_TTYPE_BURST(18); |
| DECLARE_KOBJ_TTYPE_RW(18); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(18); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(19); |
| DECLARE_KOBJ_TTYPE_NBEAT(19); |
| DECLARE_KOBJ_TTYPE_NBYTE(19); |
| DECLARE_KOBJ_TTYPE_BURST(19); |
| DECLARE_KOBJ_TTYPE_RW(19); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(19); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(20); |
| DECLARE_KOBJ_TTYPE_NBEAT(20); |
| DECLARE_KOBJ_TTYPE_NBYTE(20); |
| DECLARE_KOBJ_TTYPE_BURST(20); |
| DECLARE_KOBJ_TTYPE_RW(20); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(20); |
| |
| DECLARE_KOBJ_TTYPE_MASTER(21); |
| DECLARE_KOBJ_TTYPE_NBEAT(21); |
| DECLARE_KOBJ_TTYPE_NBYTE(21); |
| DECLARE_KOBJ_TTYPE_BURST(21); |
| DECLARE_KOBJ_TTYPE_RW(21); |
| DECLARE_KOBJ_TTYPE_BUSID_VAL(21); |
| |
| #define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \ |
| do { \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _master); \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \ |
| KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \ |
| } while (0) |
| |
| #define KOBJ_ATTR_LIST \ |
| do { \ |
| KOBJ_ATTR_ITEM(high_priority_filter); \ |
| KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \ |
| KOBJ_ATTR_ITEM(msel_enable); \ |
| KOBJ_ATTR_ITEM(msel_group1); \ |
| KOBJ_ATTR_ITEM(msel_group2); \ |
| KOBJ_ATTR_ITEM(msel_group3); \ |
| KOBJ_ATTR_ITEM(ttype17_21_en); \ |
| KOBJ_ATTR_ITEM(ttype1_16_en); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \ |
| KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \ |
| KOBJ_ATTR_ITEM(test); \ |
| } while (0) |
| |
| /*======================================================================*/ |
| /* EMI Operations */ |
| /*======================================================================*/ |
| static void emi_init(void) |
| { |
| unsigned int bmrw0_val = 0, bmrw1_val = 0, i, enable; |
| unsigned int msel_group_val[4]; |
| |
| MET_BM_SaveCfg(); |
| |
| if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) { |
| if (msel_enable) { |
| msel_group_val[0] = _ALL; |
| msel_group_val[1] = msel_group1; |
| msel_group_val[2] = msel_group2; |
| msel_group_val[3] = msel_group3; |
| } else { |
| msel_group_val[0] = _ALL; |
| msel_group_val[1] = _GP_1_Default; |
| msel_group_val[2] = _GP_2_Default; |
| msel_group_val[3] = _GP_3_Default; |
| } |
| |
| MET_BM_SetLatencyCounter(1); |
| |
| for (i = 1; i <= 4; i++) { |
| MET_BM_SetMonitorCounter(i, |
| msel_group_val[i - 1] & _ALL, |
| BM_TRANS_TYPE_4BEAT | |
| BM_TRANS_TYPE_8Byte | |
| BM_TRANS_TYPE_BURST_WRAP); |
| MET_BM_SetbusID(i, 0); |
| MET_BM_SetbusID_En(i, 0); |
| } |
| for (i = 0; i < 4; i++) |
| MET_BM_Set_WsctTsct_id_sel(i, 0); |
| |
| } else if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1)) { |
| MET_BM_SetLatencyCounter(1); |
| |
| for (i = 1; i <= 4; i++) { |
| MET_BM_SetMonitorCounter(i, |
| ttype_master_val[i - 1], |
| ttype_nbeat_val[i - 1] | |
| ttype_nbyte_val[i - 1] | |
| ttype_burst_val[i - 1]); |
| MET_BM_SetbusID(i, ttype_busid_val[i - 1]); |
| MET_BM_SetbusID_En(i, 0); |
| } |
| for (i = 0; i < 4; i++) |
| MET_BM_Set_WsctTsct_id_sel(i, 1); |
| |
| } else if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) { |
| MET_BM_SetLatencyCounter(0); |
| |
| for (i = 1; i <= 16; i++) { |
| MET_BM_SetMonitorCounter(i, |
| ttype_master_val[i - 1], |
| ttype_nbeat_val[i - 1] | |
| ttype_nbyte_val[i - 1] | |
| ttype_burst_val[i - 1]); |
| |
| MET_BM_SetbusID(i, ttype_busid_val[i - 1]); |
| |
| MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1); |
| } |
| for (i = 0; i < 4; i++) |
| MET_BM_Set_WsctTsct_id_sel(i, 0); |
| } else { /* (ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1) */ |
| |
| MET_BM_SetLatencyCounter(0); |
| |
| for (i = 1; i <= 16; i++) { |
| MET_BM_SetMonitorCounter(i, |
| ttype_master_val[i - 1], |
| ttype_nbeat_val[i - 1] | |
| ttype_nbyte_val[i - 1] | |
| ttype_burst_val[i - 1]); |
| |
| MET_BM_SetbusID(i, ttype_busid_val[i - 1]); |
| |
| MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1); |
| } |
| for (i = 0; i < 4; i++) |
| MET_BM_Set_WsctTsct_id_sel(i, 1); |
| } |
| |
| if (ttype17_21_en == BM_TTYPE17_21_ENABLE) { |
| for (i = 17; i <= 21; i++) { |
| MET_BM_SetMonitorCounter(i, |
| ttype_master_val[i - 1], |
| ttype_nbeat_val[i - 1] | |
| ttype_nbyte_val[i - 1] | |
| ttype_burst_val[i - 1]); |
| MET_BM_SetbusID(i, ttype_busid_val[i - 1]); |
| |
| MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1); |
| } |
| } |
| |
| bmrw0_val = ( |
| (ttype_rw_val[0] << 0) | (ttype_rw_val[1] << 2) | |
| (ttype_rw_val[2] << 4) | (ttype_rw_val[3] << 6) | |
| (ttype_rw_val[4] << 8) | (ttype_rw_val[5] << 10) | |
| (ttype_rw_val[6] << 12) | (ttype_rw_val[7] << 14) | |
| (ttype_rw_val[8] << 16) | (ttype_rw_val[9] << 18) | |
| (ttype_rw_val[10] << 20) | (ttype_rw_val[11] << 22) | |
| (ttype_rw_val[12] << 24) | (ttype_rw_val[13] << 26) | |
| (ttype_rw_val[14] << 28) | (ttype_rw_val[15] << 30)); |
| |
| bmrw1_val = ( |
| (ttype_rw_val[16] << 0) | (ttype_rw_val[17] << 2) | |
| (ttype_rw_val[18] << 4) | (ttype_rw_val[19] << 6) | |
| (ttype_rw_val[20] << 8)); |
| |
| MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val); |
| |
| for (i = 0; i < BM_COUNTER_MAX; i++) { |
| if ((high_priority_filter & (1 << i)) == 0) |
| enable = 0; |
| else |
| enable = 1; |
| |
| MET_BM_SetUltraHighFilter(i + 1, enable); |
| } |
| |
| } |
| |
| static inline int do_emi(void) |
| { |
| return met_sspm_emi.mode; |
| } |
| |
| /*======================================================================*/ |
| /* MET Device Operations */ |
| /*======================================================================*/ |
| static int emi_inited; |
| static int met_emi_create(struct kobject *parent) |
| { |
| int ret = 0; |
| int i; |
| |
| for (i = 0; i < 21; i++) { |
| ttype_master_val[i] = _M0; |
| ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT; |
| ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte; |
| ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR; |
| ttype_busid_val[i] = 0xfffff; |
| ttype_rw_val[i] = BM_TRANS_RW_DEFAULT; |
| } |
| ret = MET_BM_Init(); |
| if (ret != 0) { |
| pr_debug("MET_BM_Init failed!!!\n"); |
| ret = 0; |
| } else |
| emi_inited = 1; |
| |
| kobj_emi = parent; |
| |
| #define KOBJ_ATTR_ITEM(attr_name) \ |
| do { \ |
| ret = sysfs_create_file(kobj_emi, &attr_name##_attr.attr); \ |
| if (ret != 0) { \ |
| pr_debug("Failed to create " #attr_name " in sysfs\n"); \ |
| return ret; \ |
| } \ |
| } while (0) |
| KOBJ_ATTR_LIST; |
| #undef KOBJ_ATTR_ITEM |
| |
| return ret; |
| } |
| |
| static void met_emi_delete(void) |
| { |
| #define KOBJ_ATTR_ITEM(attr_name) \ |
| sysfs_remove_file(kobj_emi, &attr_name##_attr.attr) |
| if (kobj_emi != NULL) { |
| KOBJ_ATTR_LIST; |
| kobj_emi = NULL; |
| } |
| #undef KOBJ_ATTR_ITEM |
| |
| if (emi_inited) |
| MET_BM_DeInit(); |
| } |
| |
| |
| static void met_emi_resume(void) |
| { |
| if (!do_emi()) |
| return; |
| |
| emi_init(); |
| } |
| |
| |
| #ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT |
| static const char help[] = " --emi monitor EMI banwidth\n"; |
| |
| #define TTYPE_NAME_STR_LEN 64 |
| static char ttype_name[21][TTYPE_NAME_STR_LEN]; |
| |
| static int emi_print_help(char *buf, int len) |
| { |
| return snprintf(buf, PAGE_SIZE, help); |
| } |
| |
| static int emi_print_header(char *buf, int len) |
| { |
| int ret = 0; |
| int ret_m[21]; |
| int i = 0; |
| |
| |
| for (i = 0; i < 21; i++) { |
| int k; |
| |
| if (ttype_busid_val[i] > 0xffff) { |
| int j; |
| |
| for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) { |
| if (ttype_master_val[i] == ttype_master_list_item[j].key) { |
| ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttyp%d_%s", |
| i + 1, ttype_master_list_item[j].val); |
| break; |
| } |
| } |
| if (j == ARRAY_SIZE(ttype_master_list_item)) |
| ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttyp%d_%s", |
| i + 1, "unknown"); |
| } else { |
| ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttyp%d_%x", |
| i + 1, ttype_busid_val[i]); |
| } |
| |
| for (k = 0; k < ARRAY_SIZE(ttype_nbeat_list_item); k++) { |
| if (ttype_nbeat_val[i] == ttype_nbeat_list_item[k].key) |
| ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%d", |
| ttype_nbeat_list_item[k].val); |
| } |
| |
| for (k = 0; k < ARRAY_SIZE(ttype_nbyte_list_item); k++) { |
| if (ttype_nbyte_val[i] == ttype_nbyte_list_item[k].key) |
| ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "x%d", |
| ttype_nbyte_list_item[k].val); |
| } |
| |
| for (k = 0; k < ARRAY_SIZE(ttype_burst_list_item); k++) { |
| if (ttype_burst_val[i] == ttype_burst_list_item[k].key) |
| ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s", |
| ttype_burst_list_item[k].val); |
| } |
| |
| for (k = 0; k < ARRAY_SIZE(ttype_rw_list_item); k++) { |
| if (ttype_rw_val[i] == ttype_rw_list_item[k].key) |
| ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s", |
| ttype_rw_list_item[k].val); |
| } |
| } |
| if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) { |
| if (msel_enable) { |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n", |
| msel_group1 & _ALL, |
| msel_group2 & _ALL, |
| msel_group3 & _ALL); |
| } else { |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n", |
| _GP_1_Default & _ALL, |
| _GP_2_Default & _ALL, |
| _GP_3_Default & _ALL); |
| } |
| } else { |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| "met-info [000] 0.0: met_emi_ttype_master: %x,%x,%x,%x\n", |
| ttype_master_val[0], ttype_master_val[1], ttype_master_val[2], ttype_master_val[3]); |
| |
| if (emi_TP_busfiltr_enable == 1) { |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| "met-info [000] 0.0: met_emi_ttype_busid: %x,%x,%x,%x\n", |
| ttype_busid_val[0], ttype_busid_val[1], ttype_busid_val[2], ttype_busid_val[3]); |
| } |
| } |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_rw_cfg: "); |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "BOTH"); |
| |
| for (i = 0; i < 21; i++) { |
| if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT) |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, ",DEFAULT"); |
| else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY) |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, ",R"); |
| else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY) |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, ",W"); |
| else |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, ",BOTH"); |
| } |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| "met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter); |
| if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (ttype17_21_en == BM_TTYPE17_21_ENABLE)) { |
| int i; |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,"); |
| for (i = 0; i < 21; i++) |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]); |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x\n"); |
| |
| } else if (ttype17_21_en == BM_TTYPE17_21_ENABLE) { |
| int i; |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,"); |
| |
| for (i = 16; i < 21; i++) |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]); |
| |
| ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x\n"); |
| } |
| |
| return ret; |
| } |
| |
| static int ondiemet_emi_print_header(char *buf, int len) |
| { |
| return emi_print_header(buf, len); |
| } |
| |
| static void MET_BM_IPI_REGISTER_CB(void) |
| { |
| int ret, i; |
| unsigned int rdata; |
| unsigned int ipi_buf[4]; |
| |
| for (i = 0; i < 4; i++) |
| ipi_buf[i] = 0; |
| |
| if (sspm_buf_available == 1) { |
| ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB; |
| ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); |
| } |
| } |
| |
| static void MET_BM_IPI_configs(void) |
| { |
| int ret, i; |
| unsigned int rdata; |
| unsigned int ipi_buf[4]; |
| |
| for (i = 0; i < 4; i++) |
| ipi_buf[i] = 0; |
| |
| if (sspm_buf_available == 1) { |
| ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1; |
| ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); |
| } |
| } |
| |
| static void ondiemet_emi_start(void) |
| { |
| MET_BM_IPI_REGISTER_CB(); |
| if (!emi_inited) { |
| if (MET_BM_Init() != 0) { |
| met_sspm_emi.mode = 0; |
| pr_notice("MET_BM_Init failed!!!\n"); |
| PR_BOOTMSG("MET_BM_Init failed!!!\n"); |
| return; |
| } |
| emi_inited = 1; |
| } |
| MET_BM_IPI_configs(); |
| |
| if (do_emi()) |
| emi_init(); |
| |
| ondiemet_module[ONDIEMET_SSPM] |= ID_EMI; |
| } |
| |
| static void emi_uninit(void) |
| { |
| MET_BM_RestoreCfg(); |
| } |
| |
| static void ondiemet_emi_stop(void) |
| { |
| if (!emi_inited) |
| return; |
| |
| if (do_emi()) |
| emi_uninit(); |
| } |
| #endif |
| |
| struct metdevice met_sspm_emi = { |
| .name = "emi", |
| .owner = THIS_MODULE, |
| .type = MET_TYPE_BUS, |
| .create_subfs = met_emi_create, |
| .delete_subfs = met_emi_delete, |
| .resume = met_emi_resume, |
| #ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT |
| .ondiemet_start = ondiemet_emi_start, |
| .ondiemet_stop = ondiemet_emi_stop, |
| .ondiemet_print_help = emi_print_help, |
| .ondiemet_print_header = ondiemet_emi_print_header, |
| #endif |
| .ondiemet_mode = 1, |
| }; |
| EXPORT_SYMBOL(met_sspm_emi); |