[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.c b/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.c
new file mode 100644
index 0000000..8c5711b
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.c
@@ -0,0 +1,494 @@
+/*
+ * 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/delay.h>
+#include <linux/module.h> /* symbol_get */
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "ondiemet_sspm.h"
+
+#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#else /* CONFIG_MET_ARM_32BIT */
+#include <linux/dma-mapping.h>
+#endif /* CONFIG_MET_ARM_32BIT */
+#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+#include "sspm_reservedmem.h"
+#include "sspm_reservedmem_define.h"
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+dma_addr_t ondiemet_sspm_log_phy_addr;
+void *ondiemet_sspm_log_virt_addr;
+uint32_t ondiemet_sspm_log_size = 0x400000;
+
+/* SSPM_LOG_FILE 0 */
+/* SSPM_LOG_SRAM 1 */
+/* SSPM_LOG_DRAM 2 */
+int sspm_log_mode;
+/* SSPM_RUN_NORMAL mode 0 */
+/* SSPM_RUN_CONTINUOUS mode 1 */
+int sspm_run_mode;
+int met_sspm_log_discard = -1;
+int sspm_log_size = 500;
+
+int sspm_buffer_size;
+int sspm_buf_available;
+EXPORT_SYMBOL(sspm_buf_available);
+int sspm_buf_mapped = -1; /* get buffer by MET itself */
+
+static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_buffer_size, 0444, sspm_buffer_size_show, NULL);
+
+static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_available, 0444, sspm_available_show, NULL);
+
+static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_log_discard, 0444, sspm_log_discard_show, NULL);
+
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_log_mode, 0664, sspm_log_mode_show, sspm_log_mode_store);
+
+static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_log_size, 0664, sspm_log_size_show, sspm_log_size_store);
+
+
+static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_run_mode, 0664, sspm_run_mode_show, sspm_run_mode_store);
+
+static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_modules, 0664, sspm_modules_show, sspm_modules_store);
+
+static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_op_ctrl, 0220, NULL, sspm_op_ctrl_store);
+
+static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_buffer_size);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", met_sspm_log_discard);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_mode);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_log_mode = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+
+static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_size);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_log_size = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+
+static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_run_mode);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_run_mode = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ if (value == 1)
+ sspm_start();
+ else if (value == 2)
+ sspm_stop();
+ else if (value == 3)
+ sspm_extract();
+ else if (value == 4)
+ sspm_flush();
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%x\n", ondiemet_module[ONDIEMET_SSPM]);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint32_t value;
+
+ if (kstrtouint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ ondiemet_module[ONDIEMET_SSPM] = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+int sspm_attr_init(struct device *dev)
+{
+ int ret;
+
+#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+ struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
+
+ if (ops && ops->alloc) {
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ ondiemet_sspm_log_virt_addr = ops->alloc(dev,
+ ondiemet_sspm_log_size,
+ &ondiemet_sspm_log_phy_addr,
+ GFP_KERNEL,
+ 0);
+ }
+#else /* CONFIG_MET_ARM_32BIT */
+ /* dma_alloc */
+ ondiemet_sspm_log_virt_addr = dma_alloc_coherent(dev,
+ ondiemet_sspm_log_size,
+ &ondiemet_sspm_log_phy_addr,
+ GFP_KERNEL);
+#endif /* CONFIG_MET_ARM_32BIT */
+#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ phys_addr_t (*sspm_reserve_mem_get_phys_sym)(unsigned int id) = NULL;
+ phys_addr_t (*sspm_reserve_mem_get_virt_sym)(unsigned int id) = NULL;
+ phys_addr_t (*sspm_reserve_mem_get_size_sym)(unsigned int id) = NULL;
+
+ sspm_reserve_mem_get_phys_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_virt);
+ sspm_reserve_mem_get_virt_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_phys);
+ sspm_reserve_mem_get_size_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_size);
+ if (sspm_reserve_mem_get_phys_sym)
+ ondiemet_sspm_log_virt_addr = (void*)sspm_reserve_mem_get_virt(MET_MEM_ID);
+ if (sspm_reserve_mem_get_virt_sym)
+ ondiemet_sspm_log_phy_addr = sspm_reserve_mem_get_phys(MET_MEM_ID);
+ if (sspm_reserve_mem_get_size_sym)
+ ondiemet_sspm_log_size = sspm_reserve_mem_get_size(MET_MEM_ID);
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ ret = device_create_file(dev, &dev_attr_sspm_buffer_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_buffer_size\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_available);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_available\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_log_discard);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_discard\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_log_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_mode\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_log_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_size\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_run_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_run_mode\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_op_ctrl);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_op_ctrl\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_modules);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_modules\n");
+ return ret;
+ }
+
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+ start_sspm_ipi_recv_thread();
+ sspm_buf_available = 1;
+ sspm_buffer_size = ondiemet_sspm_log_size;
+ } else {
+ sspm_buf_available = 0;
+ sspm_buffer_size = -1;
+ }
+
+ return 0;
+}
+
+int sspm_attr_uninit(struct device *dev)
+{
+ /* dma_free */
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+#if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) || defined(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+ struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
+
+ if (ops && ops->free) {
+ ops->free(dev,
+ ondiemet_sspm_log_size,
+ ondiemet_sspm_log_virt_addr,
+ ondiemet_sspm_log_phy_addr,
+ 0);
+ }
+#else /* CONFIG_MET_ARM_32BIT */
+ dma_free_coherent(dev,
+ ondiemet_sspm_log_size,
+ ondiemet_sspm_log_virt_addr,
+ ondiemet_sspm_log_phy_addr);
+#endif /* CONFIG_MET_ARM_32BIT */
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+ ondiemet_sspm_log_virt_addr = NULL;
+ stop_sspm_ipi_recv_thread();
+ }
+
+ device_remove_file(dev, &dev_attr_sspm_buffer_size);
+ device_remove_file(dev, &dev_attr_sspm_available);
+ device_remove_file(dev, &dev_attr_sspm_log_discard);
+ device_remove_file(dev, &dev_attr_sspm_log_mode);
+ device_remove_file(dev, &dev_attr_sspm_log_size);
+ device_remove_file(dev, &dev_attr_sspm_run_mode);
+ device_remove_file(dev, &dev_attr_sspm_op_ctrl);
+ device_remove_file(dev, &dev_attr_sspm_modules);
+
+ return 0;
+}
+
+#if 0 /* move to sspm_attr_init() */
+void sspm_get_buffer_info(void)
+{
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+ sspm_buf_available = 1;
+ sspm_buffer_size = ondiemet_sspm_log_size;
+ } else {
+ sspm_buf_available = 0;
+ sspm_buffer_size = -1;
+ }
+}
+#endif
+
+extern const char *met_get_platform_name(void);
+void sspm_start(void)
+{
+ int32_t ret = 0;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+ const char* platform_name = NULL;
+ unsigned int platform_id = 0;
+ met_sspm_log_discard = -1;
+
+ /* clear DRAM buffer */
+ if (ondiemet_sspm_log_virt_addr != NULL)
+ memset_io((void *)ondiemet_sspm_log_virt_addr, 0, ondiemet_sspm_log_size);
+ else
+ return;
+
+ platform_name = met_get_platform_name();
+ if (platform_name) {
+ char buf[5];
+
+ memset(buf, 0x0, 5);
+ memcpy(buf, &platform_name[2], 4);
+ ret = kstrtouint(buf, 10, &platform_id);
+ }
+
+ /* send DRAM physical address */
+ ipi_buf[0] = MET_MAIN_ID | MET_BUFFER_INFO;
+ ipi_buf[1] = (unsigned int)ondiemet_sspm_log_phy_addr; /* address */
+ if (ret == 0)
+ ipi_buf[2] = platform_id;
+ else
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+
+ /* start ondiemet now */
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_START;
+ ipi_buf[1] = ondiemet_module[ONDIEMET_SSPM];
+ ipi_buf[2] = sspm_log_mode;
+ ipi_buf[3] = sspm_run_mode;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+}
+
+void sspm_stop(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_STOP;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+void sspm_extract(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+ int32_t count;
+
+ count = 20;
+ if (sspm_buf_available == 1) {
+ while ((sspm_buffer_dumping == 1) && (count != 0)) {
+ msleep(50);
+ count--;
+ }
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_EXTRACT;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL)
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+}
+
+void sspm_flush(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_FLUSH;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL)
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+}
+#else /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
+int sspm_buffer_size = -1;
+
+int sspm_attr_init(struct device *dev)
+{
+ return 0;
+}
+
+int sspm_attr_uninit(struct device *dev)
+{
+ return 0;
+}
+
+void sspm_start(void)
+{
+}
+
+void sspm_stop(void)
+{
+}
+
+void sspm_extract(void)
+{
+}
+
+void sspm_flush(void)
+{
+}
+
+#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
diff --git a/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.h b/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.h
new file mode 100644
index 0000000..64dfcbd
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/ondiemet_sspm.h
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#ifndef __ONDIEMET_SSPM_H
+#define __ONDIEMET_SSPM_H
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "ondiemet.h"
+#include "sspm_ipi.h"
+#include <linux/dma-mapping.h>
+
+/* we may use IPI_ID_PLATFORM for mt6759 to reduce SRAM */
+#ifndef IPI_ID_MET
+/* #define IPI_ID_MET IPI_ID_TST1 */
+#define IPI_ID_MET IPI_ID_PLATFORM
+#endif
+
+/* MET IPI command definition: mbox 0 */
+/* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0] */
+#define MET_MAIN_ID_MASK 0xff000000 /* bit 31 - 24 */
+#define MET_SUB_ID_MASK 0x00fc0000 /* bit 23 - 18 */
+#define MET_ARGU0_MASK 0x0003ffff /* bit 17 - 0 */
+#define FUNC_BIT_SHIFT 18
+#define MID_BIT_SHIFT 9
+#define MET_MAIN_ID 0x06000000
+/* handle argument and attribute */
+#define PROCESS_ARGU 0x01
+#define PROCESS_ATTR 0x02
+#define MODULE_ID_MASK 0x3fe00 /* bit 9 - 17 */
+#define ARGUMENT_MASK 0x01ff /* bit 0 - 8 */
+
+/* the following command is used for AP to MD32 */
+#define MET_OP (1 << FUNC_BIT_SHIFT)
+/* argu 0: start: 0x01; stop: 0x02; extract: 0x03 */
+#define MET_OP_START 0x00000001
+#define MET_OP_STOP 0x00000002
+#define MET_OP_EXTRACT 0x00000003
+#define MET_OP_FLUSH 0x00000004
+#define MET_SR (2 << FUNC_BIT_SHIFT) /* sample rate */
+#define MET_MODULE (3 << FUNC_BIT_SHIFT) /* module enable/disable */
+#define MET_ARGU (4 << FUNC_BIT_SHIFT) /* argument passing */
+#define MET_ATTR (5 << FUNC_BIT_SHIFT) /* attribute passing */
+/* system memory information for on-die-met log data */
+#define MET_BUFFER_INFO (6 << FUNC_BIT_SHIFT)
+#define MET_TIMESTAMP (7 << FUNC_BIT_SHIFT) /* timestamp info */
+#define MET_GPT (8 << FUNC_BIT_SHIFT) /* GPT counter reading */
+#define MET_REQ_AP2MD (9 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_RESP_AP2MD (10 << FUNC_BIT_SHIFT) /* may no need */
+/* mode: bit 15 - 0: */
+/* Bit 0: MD32 SRAM mode; Bit 1: System DRAM mode */
+/* value: 0: output to next level of storage; 1: loop in its own storage */
+#define MET_DATA_MODE (11 << FUNC_BIT_SHIFT) /* log output mode */
+/* start/stop read data into MD32 SRAM buffer; both DMA and met_printf() */
+#define MET_DATA_OP (12 << FUNC_BIT_SHIFT) /* data read operation */
+/* the following command is used for MD32 to AP */
+#define MET_DUMP_BUFFER (13 << FUNC_BIT_SHIFT)
+#define MET_REQ_MD2AP (14 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_CLOSE_FILE (15 << FUNC_BIT_SHIFT) /* Inform to close the SD file */
+#define MET_RESP_MD2AP (16 << FUNC_BIT_SHIFT)
+#define MET_RUN_MODE (17 << FUNC_BIT_SHIFT)
+
+/* Note: the module ID and its bit pattern should be fixed as below */
+/* DMA based module first */
+enum {
+ MID_PMQOS = 0,
+ MID_VCORE_DVFS,
+ MID_EMI,
+ MID_THERMAL_CPU,
+ MID_WALL_TIME,
+ MID_CPU_DVFS,
+ MID_GPU_DVFS,
+ MID_PTPOD,
+ MID_SPM,
+ MID_PROFILE,
+ MID_MET_TAG,
+ MID_TS,
+ MID_TS_ISR,
+ MID_TS_LAST,
+ MID_TS_ISR_LAST,
+ MID_SRAM_INFO,
+ MID_MET_STOP,
+ MID_IOP_MON,
+ MID_CPU_INFO_MAPPING,
+ MID_SMI,
+
+ MID_COMMON = 0x1F
+};
+
+#define ID_PMQOS (1 << MID_PMQOS)
+#define ID_SMI (1 << MID_SMI)
+#define ID_EMI (1 << MID_EMI)
+#define ID_THERMAL_CPU (1 << MID_THERMAL_CPU)
+#define ID_WALL_TIME (1 << MID_WALL_TIME)
+#define ID_CPU_DVFS (1 << MID_CPU_DVFS)
+#define ID_GPU_DVFS (1 << MID_GPU_DVFS)
+#define ID_VCORE_DVFS (1 << MID_VCORE_DVFS)
+#define ID_PTPOD (1 << MID_PTPOD)
+#define ID_SPM (1 << MID_SPM)
+#define ID_PROFILE (1 << MID_PROFILE)
+#define ID_COMMON (1 << MID_COMMON)
+#define ID_CPU_INFO_MAPPING (1 << MID_CPU_INFO_MAPPING)
+#define ID_SMI (1 << MID_SMI)
+
+extern void ondiemet_extract(void);
+extern void ondiemet_stop(void);
+extern void ondiemet_start(void);
+
+extern void start_sspm_ipi_recv_thread(void);
+extern void stop_sspm_ipi_recv_thread(void);
+
+extern unsigned int ondiemet_ipi_buf[];
+
+/* extern phys_addr_t ondiemet_sspm_log_phy_addr, ondiemet_sspm_log_virt_addr; */
+extern dma_addr_t ondiemet_sspm_log_phy_addr;
+
+extern void *ondiemet_sspm_log_virt_addr;
+extern uint32_t ondiemet_sspm_log_size;
+
+extern int ondiemet_attr_init(struct device *dev);
+extern int ondiemet_attr_uninit(struct device *dev);
+extern int met_sspm_log_discard;
+
+#define SSPM_LOG_FILE 0
+#define SSPM_LOG_SRAM 1
+#define SSPM_LOG_DRAM 2
+extern int sspm_log_mode;
+#define SSPM_RUN_NORMAL 0
+#define SSPM_RUN_CONTINUOUS 1
+extern int sspm_run_mode;
+
+/* extern void sspm_get_buffer_info(void); */
+extern int sspm_buf_available;
+extern int sspm_buffer_dumping;
+
+void sspm_flush(void);
+
+#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
+#endif /* __ONDIEMET_SSPM_H */
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_common.c b/src/devtools/met-driver/4.14/common/sspm/sspm_common.c
new file mode 100644
index 0000000..b3e1066
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_common.c
@@ -0,0 +1,266 @@
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+#include "met_drv.h"
+#include "ondiemet_sspm.h"
+
+
+struct sspm_met_evnet_header {
+ unsigned int rts_event_id;
+ char *rts_event_name;
+ char *chart_line_name;
+ char *key_list;
+};
+
+
+enum {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) rts_event_id,
+ #include "met_sspm_rts_event.h"
+
+ /**********************/
+ CUR_MET_RTS_EVENT_NUM,
+ MAX_MET_RTS_EVENT_NUM = 128
+};
+
+
+struct sspm_met_evnet_header met_evnet_header[MAX_MET_RTS_EVENT_NUM] = {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) {rts_event_id, #rts_event_id, #rts_event_id, key_list},
+ #include "met_sspm_rts_event.h"
+};
+
+
+static void ondiemet_sspm_start(void);
+static void ondiemet_sspm_stop(void);
+static int ondiemet_sspm_print_help(char *buf, int len);
+static int ondiemet_sspm_process_argument(const char *arg, int len);
+static int ondiemet_sspm_print_header(char *buf, int len);
+
+
+static unsigned int event_id_flag0;
+static unsigned int event_id_flag1;
+static unsigned int event_id_flag2;
+static unsigned int event_id_flag3;
+static char *update_rts_event_tbl[MAX_MET_RTS_EVENT_NUM];
+static char sspm_help[] = " --sspm_common=rts_event_name\n";
+static char header[] = "met-info [000] 0.0: sspm_common_header: ";
+
+struct metdevice met_sspm_common = {
+ .name = "sspm_common",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = ondiemet_sspm_start,
+ .ondiemet_stop = ondiemet_sspm_stop,
+ .ondiemet_process_argument = ondiemet_sspm_process_argument,
+ .ondiemet_print_help = ondiemet_sspm_print_help,
+ .ondiemet_print_header = ondiemet_sspm_print_header,
+};
+
+
+static int ondiemet_sspm_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, sspm_help);
+}
+
+
+static int ondiemet_sspm_print_header(char *buf, int len)
+{
+ int i;
+ int write_len;
+ int flag = 0;
+ static int is_dump_header = 0;
+ static int read_idx = 0;
+
+ len = 0;
+ met_sspm_common.header_read_again = 0;
+ if (is_dump_header == 0) {
+ len = snprintf(buf, PAGE_SIZE, "%s", header);
+ is_dump_header = 1;
+ }
+
+ for (i=read_idx; i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (met_evnet_header[i].chart_line_name) {
+ if (i <32) {
+ flag = 1<<i;
+ flag = event_id_flag0 & flag;
+ } else if (i >=32 && i < 64) {
+ flag = 1<<(i-32);
+ flag = event_id_flag1 & flag;
+ } else if (i >=64 && i < 96) {
+ flag = 1<<(i-64);
+ flag = event_id_flag2 & flag;
+ } else if (i >=96 && i < 128) {
+ flag = 1<<(i-96);
+ flag = event_id_flag3 & flag;
+ }
+ if (flag == 0)
+ continue;
+
+ write_len = strlen(met_evnet_header[i].chart_line_name) + strlen(met_evnet_header[i].key_list) + 3;
+ if ((len+write_len) < PAGE_SIZE) {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%u,%s,%s;",
+ met_evnet_header[i].rts_event_id,
+ met_evnet_header[i].chart_line_name,
+ met_evnet_header[i].key_list);
+ } else {
+ met_sspm_common.header_read_again = 1;
+ read_idx = i;
+ return len;
+ }
+ }
+ }
+
+ if (i == MAX_MET_RTS_EVENT_NUM) {
+ is_dump_header = 0;
+ read_idx = 0;
+ buf[len-1] = '\n';
+ for (i=0; i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (update_rts_event_tbl[i]) {
+ kfree(update_rts_event_tbl[i]);
+ update_rts_event_tbl[i] = NULL;
+ }
+ }
+ met_sspm_common.mode = 0;
+ event_id_flag0 = 0;
+ event_id_flag1 = 0;
+ event_id_flag2 = 0;
+ event_id_flag3 = 0;
+ }
+
+ return len;
+}
+
+
+static void ondiemet_sspm_start(void)
+{
+ if (sspm_buf_available == 0)
+ return ;
+
+ /* ID_COMMON = 1<<MID_COMMON */
+ ondiemet_module[ONDIEMET_SSPM] |= ID_COMMON;
+}
+
+
+static void ondiemet_sspm_stop(void)
+{
+ if (sspm_buf_available == 0)
+ return ;
+}
+
+
+static void update_event_id_flag(int event_id)
+{
+ unsigned int ipi_buf[4];
+ unsigned int rdata;
+ unsigned int res;
+
+ if (sspm_buf_available == 0)
+ return ;
+
+ /* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0]
+ #define MET_MAIN_ID_MASK 0xff000000
+ #define FUNC_BIT_SHIFT 18
+ #define MET_ARGU (4 << FUNC_BIT_SHIFT)
+ #define MID_BIT_SHIFT 9
+ */
+ if (event_id <32) {
+ event_id_flag0 |= 1<<event_id;
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = event_id_flag0;
+ ipi_buf[3] = 0;
+ res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=32 && event_id < 64) {
+ event_id_flag1 |= 1<<(event_id-32);
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 1;
+ ipi_buf[2] = event_id_flag1;
+ ipi_buf[3] = 0;
+ res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=64 && event_id < 96) {
+ event_id_flag2 |= 1<<(event_id-64);
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 2;
+ ipi_buf[2] = event_id_flag2;
+ ipi_buf[3] = 0;
+ res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=96 && event_id < 128) {
+ event_id_flag3 = 1<<(event_id-96);
+ ipi_buf[0] |= MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 3;
+ ipi_buf[2] = event_id_flag3;
+ ipi_buf[3] = 0;
+ res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ }
+ met_sspm_common.mode = 1;
+}
+
+
+static char *strdup(const char *s)
+{
+ char *p = kmalloc(strlen(s) + 1, GFP_KERNEL);
+
+ if (p)
+ strcpy(p, s);
+ return p;
+}
+
+
+static int ondiemet_sspm_process_argument(const char *arg, int len)
+{
+ int i;
+ int rts_event_id = -1;
+ int res;
+ char *line;
+ char *token;
+
+ for (i=0; met_evnet_header[i].rts_event_name && i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (strcmp(met_evnet_header[i].rts_event_name, arg) == 0) {
+ rts_event_id = i;
+ break;
+ }
+ }
+ if (strstarts(arg, "update_rts_event_tbl")) {
+ char *ptr;
+
+ /* update_rts_event_tbl=rts_event_id;rts_event_name;chart_line_name;key_list*/
+ line = strdup(arg);
+ if (line == NULL)
+ return -1;
+ ptr = line;
+ token = strsep(&line, "=");
+
+ /* rts_event_id, */
+ token = strsep(&line, ";");
+ res = kstrtoint(token, 10, &rts_event_id);
+ met_evnet_header[rts_event_id].rts_event_id = rts_event_id;
+
+ /* rts_event_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].rts_event_name = token;
+
+ /* chart_line_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].chart_line_name = token;
+
+ /* key_list */
+ token = strsep(&line, ";\n");
+ met_evnet_header[rts_event_id].key_list = token;
+
+ update_rts_event_tbl[rts_event_id] = ptr;
+ }
+
+ if (rts_event_id >=0)
+ update_event_id_flag(rts_event_id);
+
+ return 0;
+}
+EXPORT_SYMBOL(met_sspm_common);
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_ipi_handle.c b/src/devtools/met-driver/4.14/common/sspm/sspm_ipi_handle.c
new file mode 100644
index 0000000..161d752
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_ipi_handle.c
@@ -0,0 +1,156 @@
+/*
+ * 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/kthread.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/signal.h>
+#include <linux/semaphore.h>
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+/* #include <asm/uaccess.h> */
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+
+#include "ondiemet_sspm.h"
+#include "ondiemet_log.h"
+#include "interface.h"
+
+static struct ipi_action ondiemet_sspm_isr;
+static uint32_t log_size;
+static uint32_t recv_buf[4];
+static struct task_struct *ondiemet_sspm_recv_task;
+static int sspm_ipi_thread_started;
+int sspm_buffer_dumping;
+int sspm_recv_thread_comp;
+
+void log_done_cb(const void *p)
+{
+ uint32_t ret;
+ uint32_t rdata = 0;
+ uint32_t ipi_buf[4];
+ uint32_t opt = (p != NULL);
+
+ if (opt == 0) {
+ ipi_buf[0] = MET_MAIN_ID | MET_RESP_AP2MD;
+ ipi_buf[1] = MET_DUMP_BUFFER;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+int ondiemet_sspm_recv_thread(void *data)
+{
+ uint32_t rdata = 0, cmd, ret;
+ uint32_t ridx, widx, wlen;
+
+ ondiemet_sspm_isr.data = (void *)recv_buf;
+ ret = sspm_ipi_recv_registration(IPI_ID_TST1, &ondiemet_sspm_isr);
+ do {
+ sspm_ipi_recv_wait(IPI_ID_TST1);
+ if (sspm_recv_thread_comp == 1) {
+ while (!kthread_should_stop())
+ ;
+ return 0;
+ }
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ sspm_buffer_dumping = 1;
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ log_size = recv_buf[3];
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)0);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)0);
+ }
+ break;
+ case MET_CLOSE_FILE: /* no argument */
+ /* do close file */
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ met_sspm_log_discard = recv_buf[3];
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)1);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ }
+ ret = ondiemet_log_manager_stop();
+ /* pr_debug("MET_CLOSE_FILE: ret=%d log_discard=%d\n", ret, met_sspm_log_discard); */
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ if (sspm_run_mode == SSPM_RUN_CONTINUOUS) {
+ /* clear the memory */
+ memset_io((void *)ondiemet_sspm_log_virt_addr, 0,
+ ondiemet_sspm_log_size);
+ /* re-start ondiemet again */
+ sspm_start();
+ }
+ break;
+ case MET_RESP_MD2AP:
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ sspm_buffer_dumping = 0;
+ break;
+ default:
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ break;
+ }
+ } while (!kthread_should_stop());
+ return 0;
+}
+
+void start_sspm_ipi_recv_thread(void)
+{
+ if (sspm_ipi_thread_started != 1) {
+ sspm_recv_thread_comp = 0;
+ ondiemet_sspm_recv_task =
+ kthread_run(ondiemet_sspm_recv_thread, NULL, "ondiemet_sspm_recv");
+ if (IS_ERR(ondiemet_sspm_recv_task))
+ pr_debug("MET: Can not create ondiemet_sspm_recv\n");
+ else
+ sspm_ipi_thread_started = 1;
+ }
+}
+
+void stop_sspm_ipi_recv_thread(void)
+{
+ if (ondiemet_sspm_recv_task) {
+ sspm_recv_thread_comp = 1;
+ sspm_ipi_recv_complete(IPI_ID_TST1);
+ kthread_stop(ondiemet_sspm_recv_task);
+ ondiemet_sspm_recv_task = NULL;
+ sspm_ipi_thread_started = 0;
+ sspm_ipi_recv_unregistration(IPI_ID_TST1);
+ }
+}
+
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.c b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.c
new file mode 100644
index 0000000..f4e185b
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.c
@@ -0,0 +1,529 @@
+/*
+ * 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/module.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "sspm_mtk_smi.h"
+#include "sspm_met_smi.h"
+#include "sspm_met_smi_name.h"
+#include "core_plf_trace.h"
+#include "core_plf_init.h"
+#include "interface.h"
+#include "sspm/ondiemet_sspm.h"
+
+#define MET_SMI_DEBUG 1
+#define MET_SMI_BUF_SIZE 128
+#define MET_SMI_DEBUGBUF_SIZE 512
+#define NPORT_IN_PM 4
+
+// SMI Encode -- Master
+// bit15~bit16
+#define MET_SMI_BIT_REQ_LARB 15
+// bit13~bit14
+#define MET_SMI_BIT_REQ_COMM 13
+// bit12:Parallel Mode */
+#define MET_SMI_BIT_PM 12
+// bit9~bit8:Destination */
+#define MET_SMI_BIT_DST 8
+/* bit5~bit4:Request Type */
+#define MET_SMI_BIT_REQ 4
+/* bit3~bit0:Master */
+#define MET_SMI_BIT_MASTER 0
+
+// SMI Encode -- Metadata
+/* bit6~bit5:RW */
+#define MET_SMI_BIT_RW 5
+/* bit4~bit0:Port */
+#define MET_SMI_BIT_PORT 0
+
+/*
+*declare smi: larb0-larbn:
+*real define table in met_smi_name.h
+*/
+/*MET_SMI_DESC_DEFINE();*/
+/**/
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+#define MAX_CONFIG_ARRAY_SIZE 20
+struct metdevice met_sspm_smi;
+struct met_smi_conf smi_conf_array[MAX_CONFIG_ARRAY_SIZE];
+int smi_array_index;
+
+//static unsigned int smi_met_larb_number = SMI_LARB_NUMBER;
+static int count = SMI_LARB_NUMBER + SMI_COMM_NUMBER;
+static struct kobject *kobj_smi;
+
+/* Request type */
+static unsigned int larb_req_type = SMI_REQ_ALL;
+static unsigned int comm_req_type = SMI_REQ_ALL;
+
+/* Parallel mode */
+static unsigned int parallel_mode;
+
+/* Read/Write type in parallel mode */
+static int comm_pm_rw_type[SMI_COMM_NUMBER][NPORT_IN_PM];
+/* Error message */
+static char err_msg[MET_SMI_BUF_SIZE];
+static char debug_msg[MET_SMI_DEBUGBUF_SIZE];
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+/* KOBJ: larb_req_type */
+DECLARE_KOBJ_ATTR_INT(larb_req_type, larb_req_type);
+
+/* KOBJ : comm_req_type */
+DECLARE_KOBJ_ATTR_INT(comm_req_type, comm_req_type);
+
+/* KOBJ : enable_parallel_mode */
+DECLARE_KOBJ_ATTR_INT(enable_parallel_mode, parallel_mode);
+
+/* KOBJ : pm_rwtypeX */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ pm_rwtype,
+ KOBJ_ITEM_LIST(
+ {SMI_READ_ONLY, "READ"},
+ {SMI_WRITE_ONLY, "WRITE"}
+ )
+);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype1, comm_pm_rw_type[0][0], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype2, comm_pm_rw_type[0][1], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype3, comm_pm_rw_type[0][2], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype4, comm_pm_rw_type[0][3], pm_rwtype);
+
+/* KOBJ : count */
+DECLARE_KOBJ_ATTR_RO_INT(count, count);
+
+/* KOBJ : err_msg */
+DECLARE_KOBJ_ATTR_RO_STR(err_msg, err_msg);
+
+#define KOBJ_ATTR_LIST \
+do { \
+ KOBJ_ATTR_ITEM(larb_req_type); \
+ KOBJ_ATTR_ITEM(comm_req_type); \
+ KOBJ_ATTR_ITEM(enable_parallel_mode); \
+ KOBJ_ATTR_ITEM(pm_rwtype1); \
+ KOBJ_ATTR_ITEM(pm_rwtype2); \
+ KOBJ_ATTR_ITEM(pm_rwtype3); \
+ KOBJ_ATTR_ITEM(pm_rwtype4); \
+ KOBJ_ATTR_ITEM(count); \
+ KOBJ_ATTR_ITEM(err_msg); \
+} while (0)
+
+/*======================================================================*/
+/* SMI Operations */
+/*======================================================================*/
+static void met_smi_debug(char *debug_log)
+{
+ MET_TRACE("%s", debug_log);
+}
+
+static int do_smi(void)
+{
+ return met_sspm_smi.mode;
+}
+
+static void smi_init_value(void)
+{
+ int i;
+
+ smi_array_index = 0;
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ smi_conf_array[i].master = 0;
+ smi_conf_array[i].port[0] = -1;
+ smi_conf_array[i].port[1] = -1;
+ smi_conf_array[i].port[2] = -1;
+ smi_conf_array[i].port[3] = -1;
+ smi_conf_array[i].rwtype[0] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[1] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[2] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[3] = SMI_RW_ALL;
+ smi_conf_array[i].desttype = SMI_DEST_EMI;
+ smi_conf_array[i].reqtype = SMI_REQ_ALL;
+ }
+}
+
+static int smi_init(void)
+{
+ int i;
+
+ if (smi_array_index < MAX_CONFIG_ARRAY_SIZE) {
+ for (i = 0; i < (smi_array_index + 1); i++) {
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "===SMI config: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ parallel_mode,
+ smi_conf_array[i].master,
+ smi_conf_array[i].port[0],
+ smi_conf_array[i].port[1],
+ smi_conf_array[i].port[2],
+ smi_conf_array[i].port[3],
+ smi_conf_array[i].rwtype[0],
+ smi_conf_array[i].rwtype[1],
+ smi_conf_array[i].rwtype[2],
+ smi_conf_array[i].rwtype[3],
+ smi_conf_array[i].desttype,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_LARB,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_COMM);
+ met_smi_debug(debug_msg);
+ }
+ } else {
+ met_smi_debug("smi_init() FAIL : smi_array_index overflow\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int met_smi_create(struct kobject *parent)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+do { \
+ ret = sysfs_create_file(kobj_smi, &attr_name##_attr.attr); \
+ if (ret != 0) { \
+ pr_debug("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+} while (0)
+
+ int j;
+ int ret = 0;
+
+ pr_debug(" met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n");
+
+ /* Init. */
+
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+ kobj_smi = parent;
+
+ KOBJ_ATTR_LIST;
+
+ return ret;
+
+#undef KOBJ_ATTR_ITEM
+}
+
+void met_smi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_smi, &attr_name##_attr.attr)
+
+
+ if (kobj_smi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_smi = NULL;
+ }
+
+#undef KOBJ_ATTR_ITEM
+}
+
+static void met_smi_start(void)
+{
+ if (do_smi()) {
+ if (smi_init() != 0) {
+ met_sspm_smi.mode = 0;
+ smi_init_value();
+ return;
+ }
+ }
+}
+
+static void met_smi_stop(void)
+{
+ int j;
+
+ if (do_smi()) {
+
+ /* Reset */
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+
+ met_sspm_smi.mode = 0;
+ }
+ return ;
+}
+
+static char help[] =
+" --smi=master:port:rw:dest:bus monitor specified SMI banwidth\n"
+" --smi=master:p1[:p2][:p3][:p4] monitor parallel mode\n";
+
+static int smi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, "%s", help);
+}
+
+static int get_num(const char *__restrict__ dc, int *pValue)
+{
+ int value = 0, digit;
+ int i = 0;
+
+ while (((*dc) >= '0') && ((*dc) <= '9')) {
+ digit = (int)(*dc - '0');
+ value = value * 10 + digit;
+ dc++;
+ i++;
+ }
+
+ if (i == 0)
+ return 0;
+ *pValue = value;
+
+ return i;
+}
+
+/*
+ * There are serveal cases as follows:
+ *
+ * 1. "met-cmd --start --smi=master:port:rwtype:desttype:bustype" => Can assign multiple master
+ * 2. "met-cmd --start --smi=master:port[:port1][:port2][:port3]" ==> parael mode
+ *
+ */
+static int smi_process_argument(const char *__restrict__ arg, int len)
+{
+ int args[5];
+ int i, array_index;
+ int idx;
+ unsigned int smi_conf_index = 0;
+ struct met_smi_conf smi_conf;
+
+ uint32_t ipi_buf[4];
+ uint32_t ret;
+ uint32_t rdata;
+ uint16_t sspm_master = 0;
+ uint32_t sspm_meta = 0;
+
+ if (len < 3)
+ return -1;
+
+ /*reset local config structure*/
+ memset(err_msg, 0, MET_SMI_BUF_SIZE);
+ for (i = 0; i < 4; i++) {
+ smi_conf.port[i] = -1;
+ smi_conf.rwtype[i] = SMI_RW_ALL;
+ }
+ smi_conf.master = 0;
+ smi_conf.reqtype = SMI_REQ_ALL;
+ smi_conf.desttype = SMI_DEST_EMI;
+
+ if (met_sspm_smi.mode != 0 && met_sspm_smi.mode != 1)
+ return -1;
+
+ /*
+ * parse arguments
+ * arg[0] = master
+ * arg[1] = port or port1
+ * arg[2] = rwtype or port2
+ * arg[3] = desttype or port3
+ * arg[4] = bustype or port4
+ */
+ for (i = 0; i < ARRAY_SIZE(args); i++)
+ args[i] = -1;
+ idx = 0;
+ for (i = 0; i < ARRAY_SIZE(args); i++) {
+ ret = get_num(&(arg[idx]), &(args[i]));
+ if (ret == 0)
+ break;
+ idx += ret;
+ if (arg[idx] != ':')
+ break;
+ idx++;
+ }
+
+ pr_debug("===SMI process argu: args[0](%d), args[1](%d), args[2](%d), args[3](%d), args[4](%d)\n",
+ args[0],
+ args[1],
+ args[2],
+ args[3],
+ args[4]);
+
+ /*fill local config structure*/
+ smi_conf.master = args[0];
+ smi_conf.reqtype = (larb_req_type << MET_SMI_BIT_REQ_LARB) | (comm_req_type << MET_SMI_BIT_REQ_COMM);
+ if (parallel_mode == 0) { /*legacy mode*/
+ smi_conf.rwtype[0] = args[2];
+ smi_conf.desttype = args[3];
+ smi_conf.port[0] = args[1];
+ } else { /*parallel mode*/
+ smi_conf.desttype = SMI_DEST_EMI;
+ for (i = 0; i < 4; i++) {
+ if (args[i+1] < 0)
+ break;
+ smi_conf.port[i] = args[i+1];
+ smi_conf.rwtype[i] = comm_pm_rw_type[0][i];
+ }
+ }
+
+/*debug log to ftrace*/
+#ifdef MET_SMI_DEBUG
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "(argu)===SMI process argu Master[%d]: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+ met_smi_debug(debug_msg);
+#endif
+
+ /*find the empty conf_array*/
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ if ((smi_conf_array[i].master == smi_conf.master) && (smi_conf_array[i].port[0] != -1))
+ break;
+ }
+ if (i >= MAX_CONFIG_ARRAY_SIZE) {
+ if (smi_conf_array[0].port[0] == -1) {
+ smi_array_index = 0;
+ array_index = 0;
+ } else {
+ smi_array_index = smi_array_index + 1;
+ array_index = smi_array_index;
+ }
+ } else {
+ array_index = i;
+ }
+
+ if ((smi_array_index >= MAX_CONFIG_ARRAY_SIZE) || (array_index >= MAX_CONFIG_ARRAY_SIZE)) {
+ snprintf(err_msg, MET_SMI_BUF_SIZE,
+ "===Setting Master[%d]: check smi_array_index=%d, array_index=%d overflow (> %d)\n",
+ args[0], smi_array_index, array_index, MAX_CONFIG_ARRAY_SIZE);
+ return -1;
+ }
+
+ smi_conf_array[array_index].master = smi_conf.master;
+
+
+ if (parallel_mode == 0) { /* Legacy mode */
+ smi_conf_array[array_index].port[0] = smi_conf.port[0];
+ } else { /* Parallel mode */
+ for (i = 0; i < NPORT_IN_PM; i++) {
+ if (smi_conf_array[array_index].port[i] == -1)
+ smi_conf_array[array_index].port[i] = smi_conf.port[smi_conf_index++];
+ }
+ }
+ smi_conf_array[array_index].rwtype[0] = smi_conf.rwtype[0];
+ smi_conf_array[array_index].rwtype[1] = smi_conf.rwtype[1];
+ smi_conf_array[array_index].rwtype[2] = smi_conf.rwtype[2];
+ smi_conf_array[array_index].rwtype[3] = smi_conf.rwtype[3];
+ smi_conf_array[array_index].desttype = smi_conf.desttype;
+ smi_conf_array[array_index].reqtype = smi_conf.reqtype;
+
+ pr_debug("===SMI process argu Master[%d]: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+
+ // Encode SMI config: Master (request format from SMI driver)
+ sspm_master = sspm_master | (smi_conf_array[array_index].master << MET_SMI_BIT_MASTER);
+ sspm_master = sspm_master | 0 << MET_SMI_BIT_REQ; //reqtype value will be update in sspm side
+ sspm_master = sspm_master | (smi_conf_array[array_index].desttype << MET_SMI_BIT_DST);
+ sspm_master = sspm_master | (parallel_mode << MET_SMI_BIT_PM);
+ // Extrace info for larb and comm reqestType since of unable to recognize master belong to larb or comm.
+ // BIT13~BIT14: comm reqtype
+ // BIT15~BIT16: larb reqtype
+ sspm_master = sspm_master | smi_conf_array[array_index].reqtype;
+
+
+ // Encode SMI config: Meta (request format from SMI driver)
+ // Encode 4 Metadata into 1 unsigned int
+ // BIT0~BIT4: port
+ // BIT5~BIT6: rwtype
+ if(parallel_mode == 0){
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[0] << MET_SMI_BIT_PORT);
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[0] << MET_SMI_BIT_RW);
+ }
+ else{
+ for(i = 0; i < 4; i++){
+ if(smi_conf_array[array_index].port[i] == 0xFFFFFFFF){
+ smi_conf_array[array_index].port[i] = USHRT_MAX;
+ }
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[i] << (MET_SMI_BIT_PORT+8*i));
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[i] << (MET_SMI_BIT_RW+8*i));
+ }
+ }
+
+ // Transfer to SSPM side
+ if (sspm_buf_available == 1)
+ {
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_SMI << MID_BIT_SHIFT | 1;
+ ipi_buf[1] = sspm_master;
+ ipi_buf[2] = sspm_meta;
+ ipi_buf[3] = 0;
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+
+ /* Set mode */
+ met_sspm_smi.mode = 1;
+ ondiemet_module[ONDIEMET_SSPM] |= ID_CPU_INFO_MAPPING;
+ }
+
+ return 0;
+}
+
+struct metdevice met_sspm_smi = {
+ .name = "smi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_smi_create,
+ .delete_subfs = met_smi_delete,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = met_smi_start,
+ .ondiemet_stop = met_smi_stop,
+ .ondiemet_process_argument = smi_process_argument,
+ .ondiemet_print_help = smi_print_help,
+};
+
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.h b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.h
new file mode 100644
index 0000000..918a5a5
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef _SMI_H_
+#define _SMI_H_
+
+#include <linux/device.h>
+
+struct met_smi {
+ int mode;
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /* 0 for GMC, 1 for AXI */
+ /* unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+ struct kobject *kobj_bus_smi;
+};
+
+struct smi_cfg {
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /*0 for GMC, 1 for AXI */
+ /*unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+struct smi_mon_con {
+ unsigned int requesttype; /* 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+/* ====================== SMI/EMI Interface ================================ */
+
+struct met_smi_conf {
+ unsigned int master; /*Ex : Whitney: 0~8 for larb0~larb8, 9 for common larb*/
+ int port[4]; /* port select : [0] only for legacy mode, [0~3] ports for parallel mode, -1 no select*/
+ unsigned int reqtype; /* Selects request type : 0 for all,1 for ultra,2 for preultra,3 for normal*/
+ unsigned int rwtype[4]; /* Selects read/write: 0 for R+W, 1 for read, 2 for write;*/
+ /* [0] for legacy and parallel larb0~8, [0~3] for parallel mode common*/
+ unsigned int desttype; /* Selects destination: 0 and 3 for all memory, 1 for External,2 for internal*/
+};
+
+#endif /* _SMI_H_ */
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi_name.h b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi_name.h
new file mode 100644
index 0000000..fd9197e
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_met_smi_name.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef _SMI_NAME_H_
+#define _SMI_NAME_H_
+#include "mtk_smi.h"
+
+enum SMI_DEST {
+ SMI_DEST_ALL = 0,
+ SMI_DEST_EMI = 1,
+ SMI_DEST_INTERNAL = 2,
+ SMI_DEST_NONE = 9
+};
+
+enum SMI_RW {
+ SMI_RW_ALL = 0,
+ SMI_READ_ONLY = 1,
+ SMI_WRITE_ONLY = 2,
+ SMI_RW_RESPECTIVE = 3,
+ SMI_RW_NONE = 9
+};
+
+enum SMI_BUS {
+ SMI_BUS_GMC = 0,
+ SMI_BUS_AXI = 1,
+ SMI_BUS_NONE = 9
+};
+
+enum SMI_REQUEST {
+ SMI_REQ_ALL = 0,
+ SMI_REQ_ULTRA = 1,
+ SMI_REQ_PREULTRA = 2,
+ SMI_NORMAL_ULTRA = 3,
+ SMI_REQ_NONE = 9
+};
+
+struct smi_desc {
+ unsigned long port;
+ enum SMI_DEST desttype;
+ enum SMI_RW rwtype;
+ enum SMI_BUS bustype;
+};
+#endif /* _SMI_NAME_H_ */
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_mtk_smi.h b/src/devtools/met-driver/4.14/common/sspm/sspm_mtk_smi.h
new file mode 100644
index 0000000..9e76a0b
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_mtk_smi.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef __MT_SMI_H__
+#define __MT_SMI_H__
+
+/* the default value, but the real number will get from symbol function*/
+#define SMI_LARB_NUMBER 9
+#define SMI_COMM_NUMBER 1
+#define SMI_LARB_MONITOR_NUMBER 1
+#define SMI_COMM_MONITOR_NUMBER 1
+
+#define SMI_REQ_OK (0)
+#define SMI_ERR_WRONG_REQ (-1)
+#define SMI_ERR_OVERRUN (-2)
+
+#define SMI_IOMEM_ADDR(b, off) ((void __iomem *)(((unsigned long)b)+off))
+
+#define SMI_LARB_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x400)
+#define SMI_LARB_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x404)
+#define SMI_LARB_MON_PORT(b) SMI_IOMEM_ADDR((b), 0x408)
+#define SMI_LARB_MON_CON(b) SMI_IOMEM_ADDR((b), 0x40C)
+
+#define SMI_LARB_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x410)
+#define SMI_LARB_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x414)
+#define SMI_LARB_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x418)
+#define SMI_LARB_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x41C)
+#define SMI_LARB_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x420)
+#define SMI_LARB_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x424)
+#define SMI_LARB_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x428)
+#define SMI_LARB_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x430)
+#define SMI_LARB_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x434)
+
+#define SMI_COMM_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x1A0)
+#define SMI_COMM_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x1A4)
+#define SMI_COMM_MON_TYPE(b) SMI_IOMEM_ADDR((b), 0x1AC)
+#define SMI_COMM_MON_CON(b) SMI_IOMEM_ADDR((b), 0x1B0)
+#define SMI_COMM_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x1C0)
+#define SMI_COMM_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x1C4)
+#define SMI_COMM_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x1C8)
+#define SMI_COMM_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x1CC)
+#define SMI_COMM_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x1D0)
+#define SMI_COMM_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D4)
+#define SMI_COMM_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D8)
+#define SMI_COMM_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x1DC)
+#define SMI_COMM_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x1E0)
+
+
+/*ondiemet smi ipi command*/
+enum MET_SMI_IPI_Type {
+ SMI_DRIVER_INITIAL_VALUE = 0x0,
+ SMI_DRIVER_RESET_VALUE,
+ SET_BASE_SMI,
+ SMI_ASSIGN_PORT_START,
+ SMI_ASSIGN_PORT_I,
+ SMI_ASSIGN_PORT_II,
+ SMI_ASSIGN_PORT_III,
+ SMI_ASSIGN_PORT_END,
+};
+
+
+
+
+void MET_SMI_IPI_baseaddr(void);
+int MET_SMI_Init(void);
+void MET_SMI_Fini(void);
+void MET_SMI_Enable(int larbno);
+void MET_SMI_Disable(int larbno);
+void MET_SMI_Pause(int larbno);
+void MET_SMI_Clear(int larbno);
+int MET_SMI_PowerOn(unsigned int master);
+void MET_SMI_PowerOff(unsigned int master);
+int MET_SMI_LARB_SetCfg(int larbno,
+ unsigned int pm,
+ unsigned int reqtype, unsigned int rwtype, unsigned int dsttype);
+int MET_SMI_LARB_SetPortNo(int larbno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetCfg(int commonno, unsigned int pm, unsigned int reqtype);
+int MET_SMI_COMM_SetPortNo(int commonno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetRWType(int commonno, unsigned int idx, unsigned int rw);
+
+/* config */
+int MET_SMI_GetEna(int larbno);
+int MET_SMI_GetClr(int larbno);
+int MET_SMI_GetPortNo(int larbno);
+int MET_SMI_GetCon(int larbno);
+
+/* cnt */
+int MET_SMI_GetActiveCnt(int larbno);
+int MET_SMI_GetRequestCnt(int larbno);
+int MET_SMI_GetBeatCnt(int larbno);
+int MET_SMI_GetByteCnt(int larbno);
+int MET_SMI_GetCPCnt(int larbno);
+int MET_SMI_GetDPCnt(int larbno);
+int MET_SMI_GetOSTDCnt(int larbno);
+int MET_SMI_GetCP_MAX(int larbno);
+int MET_SMI_GetOSTD_MAX(int larbno);
+
+/* common */
+void MET_SMI_Comm_Init(void);
+void MET_SMI_Comm_Enable(int commonno);
+void MET_SMI_Comm_Disable(int commonno);
+void MET_SMI_Pause(int commonno);
+void MET_SMI_Comm_Clear(int commonno);
+
+/* common config */
+int MET_SMI_Comm_GetEna(int commonno);
+int MET_SMI_Comm_GetClr(int commonno);
+int MET_SMI_Comm_GetType(int commonno);
+int MET_SMI_Comm_GetCon(int commonno);
+
+/* cnt */
+int MET_SMI_Comm_GetPortNo(int commonno);
+int MET_SMI_Comm_GetActiveCnt(int commonno);
+int MET_SMI_Comm_GetRequestCnt(int commonno);
+int MET_SMI_Comm_GetBeatCnt(int commonno);
+int MET_SMI_Comm_GetByteCnt(int commonno);
+int MET_SMI_Comm_GetCPCnt(int commonno);
+int MET_SMI_Comm_GetDPCnt(int commonno);
+int MET_SMI_Comm_GetOSTDCnt(int commonno);
+int MET_SMI_Comm_GetCP_MAX(int commonno);
+int MET_SMI_Comm_GetOSTD_MAX(int commonno);
+
+#endif /* __MT_SMI_H__ */
diff --git a/src/devtools/met-driver/4.14/common/sspm/sspm_walltime.c b/src/devtools/met-driver/4.14/common/sspm/sspm_walltime.c
new file mode 100644
index 0000000..cc12b8b
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/sspm/sspm_walltime.c
@@ -0,0 +1,52 @@
+/*
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/fs.h>
+
+#include "met_drv.h"
+#include "trace.h"
+/* #include "plf_init.h" */
+#include "sspm/ondiemet_sspm.h"
+
+static void sspm_walltime_start(void)
+{
+ ondiemet_module[ONDIEMET_SSPM] |= ID_WALL_TIME;
+}
+
+static void sspm_walltime_stop(void)
+{
+}
+
+static const char sspm_walltime_header[] = "met-info [000] 0.0: sspm WCLK: freq\n";
+
+static int sspm_walltime_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, sspm_walltime_header);
+}
+
+struct metdevice met_sspm_walltime = {
+ .name = "sspm_wall_time",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .ondiemet_mode = 0,
+ .print_header = sspm_walltime_print_header,
+ .ondiemet_start = sspm_walltime_start,
+ .ondiemet_stop = sspm_walltime_stop,
+ .ondiemet_print_header = sspm_walltime_print_header,
+};
+EXPORT_SYMBOL(met_sspm_walltime);