pass-hal: tm2: Add implementation of HAL for GPU
authorWook Song <wook16.song@samsung.com>
Wed, 8 Feb 2017 06:26:18 +0000 (15:26 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 9 Feb 2017 09:55:52 +0000 (18:55 +0900)
This patch adds an implementation of the PASS HAL for GPU.

Change-Id: I1002bcce81c7ff35ef46ab09ceaed27a255a5611
Signed-off-by: Wook Song <wook16.song@samsung.com>
CMakeLists.txt
src/gpu/CMakeLists.txt [new file with mode: 0644]
src/gpu/gpu.c [new file with mode: 0644]

index 92efed1..e9131cf 100644 (file)
@@ -17,3 +17,4 @@ SET(DEST_DIR ${LIB_INSTALL_DIR}/pass)
 
 ADD_SUBDIRECTORY(src/cpu)
 ADD_SUBDIRECTORY(src/bus)
+ADD_SUBDIRECTORY(src/gpu)
diff --git a/src/gpu/CMakeLists.txt b/src/gpu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4425ca0
--- /dev/null
@@ -0,0 +1,24 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(gpu 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/gpu/gpu.c b/src/gpu/gpu.c
new file mode 100644 (file)
index 0000000..28a8ffd
--- /dev/null
@@ -0,0 +1,283 @@
+#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: Version! */
+#define HAL_VERSION    MAKE_2B_CODE_4(VER_MAJOR,VER_MINOR,VER_REVISION,VER_RELEASE)
+#define DEV_VERSION_GPU        MAKE_2B_CODE_2(1,0)
+
+#define DEVFREQ_GPU_PATH_PREFIX                        "/sys/devices/platform/soc/"
+#define DEVFREQ_GPU_PATH_INFIX                 "/devfreq/"
+#define DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX  "/governor"
+#define DEVFREQ_GPU_CURR_FREQ_PATH_SUFFIX      "/cur_freq"
+#define DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX       "/min_freq"
+#define DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX       "/max_freq"
+
+#define TMU_PATH_PREFIX                                "/sys/class/thermal/thermal_zone"
+#define TMU_TEMP_PATH_SUFFIX                   "/temp"
+#define TMU_POLICY_PATH_SUFFIX                 "/policy"
+
+#define TM2_GPU_THERMAL_ZONE_NUM               2
+
+static int tm2_dvfs_get_curr_governor(char *res_name, char *governor)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (!governor))
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX);
+
+       ret = sysfs_read_str(path, governor, BUFF_MAX);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tm2_dvfs_set_curr_governor(char *res_name, char *governor)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (!governor))
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX);
+
+       ret = sysfs_write_str(path, governor);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tm2_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%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_CURR_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_read_int(path, &freq);
+       if (ret < 0)
+               return ret;
+
+       return freq;
+}
+
+static int tm2_dvfs_get_min_freq(char *res_name)
+{
+       char path[PATH_MAX];
+       int freq, ret;
+
+       if (!res_name)
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_read_int(path, &freq);
+       if (ret < 0)
+               return ret;
+
+       return freq;
+}
+
+static int tm2_dvfs_set_min_freq(char *res_name, int freq)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (freq < 0))
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_write_int(path, freq);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int tm2_dvfs_get_max_freq(char *res_name)
+{
+       char path[PATH_MAX];
+       int freq, ret;
+
+       if (!res_name)
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_read_int(path, &freq);
+       if (ret < 0)
+               return ret;
+
+       return freq;
+}
+
+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;
+
+       snprintf(path, PATH_MAX, "%s%s%s%s%s",
+               DEVFREQ_GPU_PATH_PREFIX,
+               res_name,
+               DEVFREQ_GPU_PATH_INFIX,
+               res_name,
+               DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX);
+
+       ret = sysfs_write_int(path, freq);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+
+static struct pass_resource_dvfs_ops tm2_gpu_dvfs_ops =  {
+       .get_curr_governor = tm2_dvfs_get_curr_governor,
+       .set_curr_governor = tm2_dvfs_set_curr_governor,
+       .get_avail_governor = NULL,
+       .get_curr_freq = tm2_dvfs_get_curr_freq,
+       .get_min_freq = tm2_dvfs_get_min_freq,
+       .set_min_freq = tm2_dvfs_set_min_freq,
+       .get_max_freq = tm2_dvfs_get_max_freq,
+       .set_max_freq = tm2_dvfs_set_max_freq,
+       .get_up_threshold = NULL,
+       .set_up_threshold = NULL,
+       .get_load_table = NULL,
+};
+
+static int tm2_tmu_get_temp(char *res_name)
+{
+       char path[PATH_MAX];
+       int temp;
+       int ret;
+
+       if (!res_name)
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%d%s",
+               TMU_PATH_PREFIX,
+               TM2_GPU_THERMAL_ZONE_NUM,
+               TMU_TEMP_PATH_SUFFIX);
+
+       ret = sysfs_read_int(path, &temp);
+       if (ret < 0)
+               return ret;
+
+       return temp;
+}
+
+static int tm2_tmu_get_policy(char *res_name, char *policy)
+{
+       char path[PATH_MAX];
+       int ret;
+
+       if ((!res_name) || (!policy))
+               return -EINVAL;
+
+       snprintf(path, PATH_MAX, "%s%d%s",
+               TMU_PATH_PREFIX,
+               TM2_GPU_THERMAL_ZONE_NUM,
+               TMU_POLICY_PATH_SUFFIX);
+
+       ret = sysfs_read_str(path, policy, BUFF_MAX);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct pass_resource_tmu_ops tm2_gpu_tmu_ops = {
+       .get_temp = tm2_tmu_get_temp,
+       .get_policy = tm2_tmu_get_policy,
+};
+
+static int tm2_gpu_open(struct pass_resource_info *info,
+               struct pass_resource_common **common)
+{
+       struct pass_resource_gpu *gpu_res;
+
+       if (!info)
+               return -EINVAL;
+
+       /* TODO: Possibility of a memory leak */
+       gpu_res = calloc(1, sizeof(struct pass_resource_gpu));
+       if (!gpu_res)
+               return -ENOMEM;
+
+       gpu_res->common.info = info;
+       gpu_res->dvfs = tm2_gpu_dvfs_ops;
+       gpu_res->tmu = tm2_gpu_tmu_ops;
+
+       *common = (struct pass_resource_common *) gpu_res;
+
+       return 0;
+}
+
+static int tm2_gpu_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_GPU,
+       .id = PASS_RESOURCE_GPU_ID,
+       .name = PASS_RESOURCE_GPU_NAME,
+       .author = "Wook Song <wook16.song@samsung.com>",
+       .open = tm2_gpu_open,
+       .close = tm2_gpu_close,
+};