pass-hal: tm1: Add implementation of HAL for CPU 82/114782/4
authorWook Song <wook16.song@samsung.com>
Tue, 14 Feb 2017 08:37:23 +0000 (17:37 +0900)
committerWook Song <wook16.song@samsung.com>
Wed, 15 Feb 2017 06:51:04 +0000 (15:51 +0900)
This patch adds an implementation of the PASS HAL for CPU.

Change-Id: I7d63c225a64cb6a422e22481c8fb690402eb7a64
Signed-off-by: Wook Song <wook16.song@samsung.com>
CMakeLists.txt
packaging/pass-hal-tm1.spec
src/cpu/CMakeLists.txt [new file with mode: 0644]
src/cpu/cpu.c [new file with mode: 0644]
src/shared/sysfs.c [new file with mode: 0644]
src/shared/sysfs.h [new file with mode: 0644]

index 0e3aec9..bd49b33 100644 (file)
@@ -14,3 +14,5 @@ ENDFOREACH(flag)
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(DEST_DIR ${LIB_INSTALL_DIR}/pass)
+
+ADD_SUBDIRECTORY(src/cpu)
index d2389f2..38ae1cc 100644 (file)
@@ -1,6 +1,5 @@
 %define version 0.0.1
 %define release 1
-%define debug_package  %{nil}
 
 Name:       pass-hal-tm1
 Summary:    PASS hal for TM1
@@ -29,9 +28,14 @@ cp %{SOURCE1} .
 
 make %{?jobs:-j%jobs}
 
+%install
+rm -rf %{buildroot}
+
+%make_install
 %post -p /sbin/ldconfig
 
 %postun -p /sbin/ldconfig
 
 %files
 %manifest %{name}.manifest
+%{_libdir}/pass/*.so
diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3cd62b8
--- /dev/null
@@ -0,0 +1,24 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(cpu C)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED dlog glib-2.0)
+
+#HAL version
+string(REPLACE "." ";" HAL_VERSION_LIST ${HAL_VERSION})
+list(GET HAL_VERSION_LIST 0 HAL_VERSION_MAJOR)
+list(GET HAL_VERSION_LIST 1 HAL_VERSION_MINOR)
+list(GET HAL_VERSION_LIST 2 HAL_VERSION_REVISION)
+list(GET HAL_VERSION_LIST 3 HAL_VERSION_RELEASE)
+add_definitions(-DVER_MAJOR=${HAL_VERSION_MAJOR} -DVER_MINOR=${HAL_VERSION_MINOR})
+add_definitions(-DVER_REVISION=${HAL_VERSION_REVISION} -DVER_RELEASE=${HAL_VERSION_RELEASE})
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+SET(SRCS ${PROJECT_NAME}.c
+       ../shared/sysfs.c)
+
+ADD_LIBRARY(${PROJECT_NAME} MODULE ${SRCS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "")
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${DEST_DIR} COMPONENT RuntimeLibraries)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
new file mode 100644 (file)
index 0000000..74adcd5
--- /dev/null
@@ -0,0 +1,208 @@
+#include <errno.h>
+#include <limits.h>
+#include <pass/hal.h>
+#include <pass/hal-log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../shared/sysfs.h"
+
+/* TODO: Should be in alphabetical order? */
+/* TODO: Version! */
+#define HAL_VERSION    MAKE_2B_CODE_4(VER_MAJOR,VER_MINOR,VER_REVISION,VER_RELEASE)
+#define DEV_VERSION_CPU        MAKE_2B_CODE_2(1,0)
+
+#define CPUFREQ_PMQOS_PATH_PREFIX              "/sys/devices/system/cpu/cpufreq/pmqos"
+#define CPUFREQ_PATH_PREFIX                    "/sys/devices/system/cpu/"
+
+#define CPUFREQ_CPU_ONLINE_MIN_NUM_PATH_SUFFIX "/cpu_online_min"
+#define CPUFREQ_CPU_ONLINE_MAX_NUM_PATH_SUFFIX "/cpu_online_max"
+#define CPUFREQ_MAX_FREQ_PATH_SUFFIX           "/cpufreq_max"
+#define CPUFREQ_MIN_FREQ_PATH_SUFFIX           "/cpufreq_min"
+#define CPUFREQ_CURR_FREQ_PATH_SUFFIX          "/cpufreq/cpuinfo_cur_freq"
+
+#define CPUFREQ_AVAILABLE_FREQ_MAX             1300000
+#define CPUFREQ_AVAILABLE_FREQ_MIN             768000
+#define CPUFREQ_PMQOS_ONLINE_MIN_NUM_UNLOCK    -1
+#define CPUFREQ_PMQOS_ONLINE_MAX_NUM_UNLOCK    -1
+
+static int tm1_dvfs_get_curr_freq(char *res_name)
+{
+       char path[PATH_MAX];
+       int freq, ret;
+
+       if (!res_name)
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s",
+               CPUFREQ_PATH_PREFIX,
+               res_name,
+               CPUFREQ_CURR_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_read_int(path, &freq);
+       if (ret < 0)
+               return ret;
+
+       return freq;
+}
+
+static int tm1_dvfs_set_min_freq(char *res_name, int freq)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (freq < 0))
+               return -EINVAL;
+
+       if (freq == CPUFREQ_AVAILABLE_FREQ_MIN)
+               freq = -1;
+
+       ret = snprintf(path, PATH_MAX, "%s%s",
+               CPUFREQ_PMQOS_PATH_PREFIX,
+               CPUFREQ_MIN_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_write_int(path, freq);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tm2_dvfs_set_max_freq(char *res_name, int freq)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (freq < 0))
+               return -EINVAL;
+
+       if (freq == CPUFREQ_AVAILABLE_FREQ_MAX)
+               freq = -1;
+
+       snprintf(path, PATH_MAX, "%s%s",
+               CPUFREQ_PMQOS_PATH_PREFIX,
+               CPUFREQ_MAX_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_write_int(path, freq);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct pass_resource_dvfs_ops tm1_cpu_dvfs_ops =  {
+       .get_curr_governor = NULL,
+       .set_curr_governor = NULL,
+       .get_avail_governor = NULL,
+       .get_curr_freq = tm1_dvfs_get_curr_freq,
+       .get_min_freq = NULL,
+       .set_min_freq = tm1_dvfs_set_min_freq,
+       .get_max_freq = NULL,
+       .set_max_freq = tm2_dvfs_set_max_freq,
+       .get_up_threshold = NULL,
+       .set_up_threshold = NULL,
+       .get_load_table = NULL,
+};
+
+static int tm1_hotplug_set_online_min_num(char *res_name, int num)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name))
+               return -EINVAL;
+
+       /* TODO: Can we turn off CPU0? */
+       snprintf(path, PATH_MAX, "%s%s",
+               CPUFREQ_PMQOS_PATH_PREFIX,
+               CPUFREQ_CPU_ONLINE_MIN_NUM_PATH_SUFFIX);
+
+       if (num == 0)
+               num = CPUFREQ_PMQOS_ONLINE_MIN_NUM_UNLOCK;
+
+       ret = sysfs_write_int(path, num);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tm1_hotplug_set_online_max_num(char *res_name, int num)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name))
+               return -EINVAL;
+
+       /* TODO: Can we turn off CPU0? */
+       snprintf(path, PATH_MAX, "%s%s",
+               CPUFREQ_PMQOS_PATH_PREFIX,
+               CPUFREQ_CPU_ONLINE_MAX_NUM_PATH_SUFFIX);
+       if (num == 0)
+               num = CPUFREQ_PMQOS_ONLINE_MAX_NUM_UNLOCK;
+
+       ret = sysfs_write_int(path, num);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+static struct pass_resource_hotplug_ops tm1_cpu_hotplug_ops = {
+       .get_online_state = NULL,
+       .set_online_state = NULL,
+       .get_online_min_num = NULL,
+       .set_online_min_num = tm1_hotplug_set_online_min_num,
+       .get_online_max_num = NULL,
+       .set_online_max_num = tm1_hotplug_set_online_max_num,
+};
+
+static struct pass_resource_tmu_ops tm1_cpu_tmu_ops = {
+       .get_temp = NULL,
+       .get_policy = NULL,
+};
+
+static int tm1_cpu_open(struct pass_resource_info *info,
+               struct pass_resource_common **common)
+{
+       struct pass_resource_cpu *cpu_res;
+
+       if (!info)
+               return -EINVAL;
+
+       /* TODO: Possibility of a memory leak */
+       cpu_res = calloc(1, sizeof(struct pass_resource_cpu));
+       if (!cpu_res)
+               return -ENOMEM;
+
+       cpu_res->common.info = info;
+       cpu_res->dvfs = tm1_cpu_dvfs_ops;
+       cpu_res->hotplug = tm1_cpu_hotplug_ops;
+       cpu_res->tmu = tm1_cpu_tmu_ops;
+
+       *common = (struct pass_resource_common *) cpu_res;
+
+       return 0;
+}
+
+static int tm1_cpu_close(struct pass_resource_common *common)
+{
+       if (!common)
+               return -EINVAL;
+
+       free(common);
+
+       return 0;
+}
+
+HAL_MODULE_STRUCTURE = {
+       .magic = HAL_INFO_TAG,
+       .hal_version = HAL_VERSION,
+       .device_version = DEV_VERSION_CPU,
+       .id = PASS_RESOURCE_CPU_ID,
+       .name = PASS_RESOURCE_CPU_NAME,
+       .author = "Wook Song <wook16.song@samsung.com>",
+       .open = tm1_cpu_open,
+       .close = tm1_cpu_close,
+};
diff --git a/src/shared/sysfs.c b/src/shared/sysfs.c
new file mode 100644 (file)
index 0000000..9217b40
--- /dev/null
@@ -0,0 +1,110 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sysfs.h"
+
+static int sysfs_read_buf(char *path, char *buf, int len)
+{
+       int r, fd;
+
+       if ((!path) || (!buf) || (len < 0))
+               return -EINVAL;
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -ENOENT;
+
+       r = read(fd, buf, len + 1);
+       close(fd);
+
+       if ((r < 0) || (r > len))
+               return -EIO;
+
+       buf[r] = '\0';
+
+       return 0;
+}
+
+static int sysfs_write_buf(char *path, char *buf)
+{
+       int w, fd;
+
+       if ((!path) || (!buf))
+               return -EINVAL;
+
+       fd = open(path, O_WRONLY);
+       if (fd == -1)
+               return -ENOENT;
+
+       w = write(fd, buf, strlen(buf));
+       close(fd);
+
+       if (w < 0)
+               return -EIO;
+
+       return 0;
+}
+
+int sysfs_read_int(char *path, int *val)
+{
+       char buf[MAX_BUF_SIZE];
+       int r;
+
+       if ((!path) || (!val))
+               return -EINVAL;
+
+       r = sysfs_read_buf(path, buf, MAX_BUF_SIZE);
+       if (r < 0)
+               return r;
+
+       *val = atoi(buf);
+       return 0;
+}
+
+int sysfs_read_str(char *path, char *str, int len)
+{
+       int r;
+
+       if ((!path) || (!str) || (len <= 0))
+               return -EINVAL;
+
+       r = sysfs_read_buf(path, str, len);
+       if (r < 0)
+               return r;
+
+       return 0;
+}
+
+int sysfs_write_int(char *path, int val)
+{
+       char buf[MAX_BUF_SIZE];
+       int w;
+
+       if (!path)
+               return -EINVAL;
+
+       snprintf(buf, MAX_BUF_SIZE, "%d", val);
+       w = sysfs_write_buf(path, buf);
+       if (w < 0)
+               return w;
+
+       return 0;
+}
+
+int sysfs_write_str(char *path, char *str)
+{
+       int w;
+
+       if ((!path) || (!str))
+               return -EINVAL;
+
+       w = sysfs_write_buf(path, str);
+       if (w < 0)
+               return w;
+
+       return 0;
+}
diff --git a/src/shared/sysfs.h b/src/shared/sysfs.h
new file mode 100644 (file)
index 0000000..174804f
--- /dev/null
@@ -0,0 +1,6 @@
+#define MAX_BUF_SIZE   255
+
+int sysfs_read_int(char *path, int *val);
+int sysfs_read_str(char *path, char *str, int len);
+int sysfs_write_int(char *path, int val);
+int sysfs_write_str(char *path, char *str);