--- /dev/null
+#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,
+};
--- /dev/null
+#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;
+}