[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/4.4/common/met_ptpod.c b/src/devtools/met-driver/4.4/common/met_ptpod.c
new file mode 100644
index 0000000..19cbed5
--- /dev/null
+++ b/src/devtools/met-driver/4.4/common/met_ptpod.c
@@ -0,0 +1,363 @@
+/*
+ * 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 "core_plf_init.h"
+#include "core_plf_trace.h"
+
+
+static unsigned int MT_GPU_DVFS_IDX = NR_MT_CPU_DVFS;
+static unsigned int g_u4GPUVolt;
+static unsigned int g_u4Volt[NR_MT_CPU_DVFS + 1];
+
+/* g_ap_ptpod: cpu volt from ap or sspm setting
+ * if 1: cpu volt from ap
+ * if 0: cpu volt from sspm */
+static unsigned int g_ap_ptpod = 1;
+
+/* gpu_volt_enable:
+ * if 1: enable gpu volt to output
+ * if 0: disable gpu volt to output */
+static unsigned int gpu_volt_enable = 1;
+
+/* get_volt_by_wq:
+ * if 1: get cpu/gpu volt by workqueue
+ * if 0: get cpu/gpu volt in irq */
+static unsigned int get_volt_by_wq;
+
+static int ptpod_started;
+static struct kobject *kobj_ptpod;
+static struct delayed_work get_volt_dwork;
+
+noinline void ms_ptpod(void)
+{
+ char *SOB, *EOB;
+
+ if (g_ap_ptpod) {
+ MET_TRACE_GETBUF(&SOB, &EOB);
+
+ if (gpu_volt_enable) {
+ g_u4Volt[MT_GPU_DVFS_IDX] = g_u4GPUVolt;
+ EOB = ms_formatD_EOL(EOB, ARRAY_SIZE(g_u4Volt), g_u4Volt);
+ } else
+ EOB = ms_formatD_EOL(EOB, ARRAY_SIZE(g_u4Volt) - 1, g_u4Volt);
+
+ MET_TRACE_PUTBUF(SOB, EOB);
+ } else {
+ if (gpu_volt_enable) {
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatD_EOL(EOB, 1, &g_u4GPUVolt);
+ MET_TRACE_PUTBUF(SOB, EOB);
+ }
+ }
+}
+
+#if 0
+static void ptpod_cpu_voltSampler(enum mt_cpu_dvfs_id id, unsigned int volt)
+{
+ switch (id) {
+ case MT_CPU_DVFS_LL:
+ g_u4CPUVolt_LL = volt;
+ break;
+ case MT_CPU_DVFS_L:
+ g_u4CPUVolt_L = volt;
+ break;
+ case MT_CPU_DVFS_CCI:
+ g_u4CPUVolt_CCI = volt;
+ break;
+ default:
+ return;
+ }
+ ptpod();
+}
+#endif
+
+#if 0
+static void ptpod_gpu_voltSampler(unsigned int a_u4Volt)
+{
+ g_u4GPUVolt = (a_u4Volt+50)/100;
+
+ if (ptpod_started)
+ ptpod();
+}
+#endif
+
+#define PTPOD_CONF_SHOW_IMPLEMENT(var) \
+ do { \
+ int i; \
+ i = snprintf(buf, PAGE_SIZE, "%d\n", var); \
+ return i; \
+ } while (0)
+
+#define PTPOD_CONF_STORE_IMPLEMENT(var) \
+ do { \
+ int value; \
+ if ((n == 0) || (buf == NULL)) \
+ return -EINVAL; \
+ if (kstrtoint(buf, 0, &value) != 0) \
+ return -EINVAL; \
+ if (value == 1) \
+ var = 1; \
+ else \
+ var = 0; \
+ return n; \
+ } while (0)
+
+
+static ssize_t ap_ptpod_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(g_ap_ptpod);
+}
+
+static ssize_t ap_ptpod_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(g_ap_ptpod);
+}
+
+static ssize_t gpu_volt_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(gpu_volt_enable);
+}
+
+static ssize_t gpu_volt_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(gpu_volt_enable);
+}
+
+static ssize_t get_volt_by_wq_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(get_volt_by_wq);
+}
+
+static ssize_t get_volt_by_wq_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(get_volt_by_wq);
+}
+
+static struct kobj_attribute ap_ptpod_enable_attr = __ATTR(ap_ptpod_enable, 0664, ap_ptpod_enable_show, ap_ptpod_enable_store);
+static struct kobj_attribute gpu_volt_enable_attr = __ATTR(gpu_volt_enable, 0664, gpu_volt_enable_show, gpu_volt_enable_store);
+static struct kobj_attribute get_volt_by_wq_attr = __ATTR(get_volt_by_wq, 0664, get_volt_by_wq_show, get_volt_by_wq_store);
+
+/* create ptpod related kobj node */
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(ap_ptpod_enable); \
+ KOBJ_ATTR_ITEM(gpu_volt_enable); \
+ KOBJ_ATTR_ITEM(get_volt_by_wq); \
+ } while (0)
+
+static int ptpod_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_ptpod = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_ptpod, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return 0;
+}
+
+static void ptpod_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_ptpod, &attr_name ## _attr.attr)
+
+ if (kobj_ptpod != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_ptpod = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+}
+
+static void update_volt_value(void)
+{
+ int i;
+
+ if (g_ap_ptpod && mt_cpufreq_get_cur_volt_symbol) {
+ /*
+ g_u4CPUVolt_LL = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_LL)/100;
+ g_u4CPUVolt_L = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_L)/100;
+ g_u4CPUVolt_CCI = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_CCI)/100;
+ */
+ for (i = 0; i < NR_MT_CPU_DVFS; i++)
+ g_u4Volt[i] = mt_cpufreq_get_cur_volt_symbol(i) / 100;
+ }
+
+ if (gpu_volt_enable) {
+ if (mt_gpufreq_get_cur_volt_symbol)
+ g_u4GPUVolt = ((mt_gpufreq_get_cur_volt_symbol() + 50) / 100);
+ }
+}
+
+static void get_volt_notify(unsigned long long stamp, int cpu)
+{
+ schedule_delayed_work(&get_volt_dwork, 0);
+}
+
+static void met_ptpod_polling_by_wq(struct work_struct *work)
+{
+ update_volt_value();
+
+ ms_ptpod();
+}
+
+static void met_ptpod_polling(unsigned long long stamp, int cpu)
+{
+ update_volt_value();
+
+ ms_ptpod();
+}
+
+/*
+ * Called from "met-cmd --start"
+ */
+static void ptpod_start(void)
+{
+#if 0
+ met_gpufreq_setvolt_registerCB(ptpod_gpu_voltSampler, kFOR_MET_PTPOD_USE);
+#endif
+
+ if (get_volt_by_wq) {
+ met_ptpod.timed_polling = get_volt_notify;
+
+ INIT_DELAYED_WORK(&get_volt_dwork, met_ptpod_polling_by_wq);
+ } else
+ met_ptpod.timed_polling = met_ptpod_polling;
+
+ update_volt_value();
+
+ ms_ptpod();
+
+#if 0
+ /* register callback */
+ if (mt_cpufreq_setvolt_registerCB_symbol)
+ mt_cpufreq_setvolt_registerCB_symbol(ptpod_cpu_voltSampler);
+#endif
+
+ ptpod_started = 1;
+}
+
+/*
+ * Called from "met-cmd --stop"
+ */
+static void ptpod_stop(void)
+{
+ ptpod_started = 0;
+
+#if 0
+ /* unregister callback */
+ if (mt_cpufreq_setvolt_registerCB_symbol)
+ mt_cpufreq_setvolt_registerCB_symbol(NULL);
+#endif
+
+ if (get_volt_by_wq)
+ cancel_delayed_work_sync(&get_volt_dwork);
+
+ update_volt_value();
+
+ ms_ptpod();
+
+#if 0
+ met_gpufreq_setvolt_registerCB(NULL, kFOR_MET_PTPOD_USE);
+#endif
+}
+
+static char help[] =
+ " --ptpod Measure CPU/GPU voltage\n";
+static int ptpod_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+/*
+ * It will be called back when run "met-cmd --extract" and mode is 1
+ */
+static int ptpod_print_header(char *buf, int len)
+{
+ int str_len = 0;
+
+ if (g_ap_ptpod) {
+ int i;
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_header: ");
+
+ for (i = 0; i < NR_MT_CPU_DVFS; i++)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "CPUVolt_%d,", i);
+
+ if (gpu_volt_enable)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "GPUVolt\n");
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_version: ap\n");
+ } else {
+ if (gpu_volt_enable) {
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_header: ");
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "GPUVolt\n");
+ }
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_version: sspm\n");
+ }
+
+ if (gpu_volt_enable)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_gpu_volt_enable: YES\n");
+ else
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_gpu_volt_enable: NO\n");
+
+ return str_len;
+}
+
+struct metdevice met_ptpod = {
+ .name = "ptpod",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_PMU,
+ .cpu_related = 0,
+ .create_subfs = ptpod_create,
+ .delete_subfs = ptpod_delete,
+ .start = ptpod_start,
+ .stop = ptpod_stop,
+ .timed_polling = met_ptpod_polling,
+ .print_help = ptpod_print_help,
+ .print_header = ptpod_print_header,
+};
+EXPORT_SYMBOL(met_ptpod);