pass-hal: tm2: Remove tm2-specific define statements for cpu
[platform/adaptation/tm2/pass-hal-tm2.git] / src / cpu / cpu.c
1 /*
2  * PASS (Power Aware System Service)
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include <errno.h>
19 #include <limits.h>
20 #include <pass/hal.h>
21 #include <pass/hal-log.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "../shared/sysfs.h"
27
28 /* TODO: Version! */
29 #define HAL_VERSION     MAKE_2B_CODE_4(VER_MAJOR,VER_MINOR,VER_REVISION,VER_RELEASE)
30 #define DEV_VERSION_CPU MAKE_2B_CODE_2(1,0)
31
32 #define CPUFREQ_PATH_PREFIX                     "/sys/devices/system/cpu/"
33 #define CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX       "/cpufreq/scaling_governor"
34 #define CPUFREQ_AVAIL_GOVERNOR_PATH_SUFFIX      "/cpufreq/scaling_available_governors"
35
36 /*
37  * The cpuinfo_cur_freq indicates the actual operating CPU freqeuncy
38  * and scaling_cur_freq is the CPU frequency set by the CPUFREQ policy.
39  */
40 #define CPUFREQ_CURR_FREQ_PATH_SUFFIX           "/cpufreq/cpuinfo_cur_freq"
41 #define CPUFREQ_MIN_FREQ_PATH_SUFFIX            "/cpufreq/scaling_min_freq"
42 #define CPUFREQ_MAX_FREQ_PATH_SUFFIX            "/cpufreq/scaling_max_freq"
43 #define CPUFREQ_UP_THRESHOLD_PATH_SUFFIX        "/cpufreq/ondemand/up_threshold"
44
45 #define LOADTABLE_PATH_PREFIX                   "/sys/kernel/debug/cpufreq/"
46 #define LOADTABLE_PATH_SUFFIX                   "/load_table"
47
48 #define CPU_ONLINE_PATH_PREFIX                  "/sys/devices/system/cpu/cpu"
49 #define CPU_ONLINE_PATH_SUFFIX                  "/online"
50 #define CPU_ONLINE_STATE_ON                     1
51 #define CPU_ONLINE_STATE_OFF                    0
52
53 #define TMU_PATH_PREFIX                         "/sys/class/thermal/"
54 #define TMU_TEMP_PATH_SUFFIX                    "/temp"
55 #define TMU_POLICY_PATH_SUFFIX                  "/policy"
56
57 static int tm2_dvfs_get_curr_governor(char *res_name, char *governor)
58 {
59         char path[PATH_MAX];
60         int ret;
61
62         if ((!res_name) || (!governor))
63                 return -EINVAL;
64
65         snprintf(path, PATH_MAX, "%s%s%s",
66                 CPUFREQ_PATH_PREFIX,
67                 res_name,
68                 CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX);
69
70         ret = sysfs_read_str(path, governor, BUFF_MAX);
71         if (ret < 0)
72                 return ret;
73
74         return 0;
75 }
76
77 static int tm2_dvfs_set_curr_governor(char *res_name, char *governor)
78 {
79         char path[PATH_MAX];
80         int ret;
81
82         if ((!res_name) || (!governor))
83                 return -EINVAL;
84
85         snprintf(path, PATH_MAX, "%s%s%s",
86                 CPUFREQ_PATH_PREFIX,
87                 res_name,
88                 CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX);
89
90         ret = sysfs_write_str(path, governor);
91         if (ret < 0)
92                 return ret;
93
94         return 0;
95 }
96
97 static int tm2_dvfs_get_curr_freq(char *res_name)
98 {
99         char path[PATH_MAX];
100         int freq, ret;
101
102         if (!res_name)
103                 return -EINVAL;
104
105         snprintf(path, PATH_MAX, "%s%s%s",
106                 CPUFREQ_PATH_PREFIX,
107                 res_name,
108                 CPUFREQ_CURR_FREQ_PATH_SUFFIX);
109
110         ret = sysfs_read_int(path, &freq);
111         if (ret < 0)
112                 return ret;
113
114         return freq;
115 }
116
117 static int tm2_dvfs_get_min_freq(char *res_name)
118 {
119         char path[PATH_MAX];
120         int freq, ret;
121
122         if (!res_name)
123                 return -EINVAL;
124
125         snprintf(path, PATH_MAX, "%s%s%s",
126                 CPUFREQ_PATH_PREFIX,
127                 res_name,
128                 CPUFREQ_MIN_FREQ_PATH_SUFFIX);
129
130         ret = sysfs_read_int(path, &freq);
131         if (ret < 0)
132                 return ret;
133
134         return freq;
135 }
136
137 static int tm2_dvfs_set_min_freq(char *res_name, int freq)
138 {
139         char path[PATH_MAX];
140         int ret;
141
142         if ((!res_name) || (freq < 0))
143                 return -EINVAL;
144
145         snprintf(path, PATH_MAX, "%s%s%s",
146                 CPUFREQ_PATH_PREFIX,
147                 res_name,
148                 CPUFREQ_MIN_FREQ_PATH_SUFFIX);
149
150         ret = sysfs_write_int(path, freq);
151         if (ret < 0)
152                 return ret;
153
154         return 0;
155 }
156
157 static int tm2_dvfs_get_max_freq(char *res_name)
158 {
159         char path[PATH_MAX];
160         int freq, ret;
161
162         if (!res_name)
163                 return -EINVAL;
164
165         snprintf(path, PATH_MAX, "%s%s%s",
166                 CPUFREQ_PATH_PREFIX,
167                 res_name,
168                 CPUFREQ_MAX_FREQ_PATH_SUFFIX);
169
170         ret = sysfs_read_int(path, &freq);
171         if (ret < 0)
172                 return ret;
173
174         return freq;
175 }
176
177 static int tm2_dvfs_set_max_freq(char *res_name, int freq)
178 {
179         char path[PATH_MAX];
180         int ret;
181
182         if ((!res_name) || (freq < 0))
183                 return -EINVAL;
184
185         snprintf(path, PATH_MAX, "%s%s%s",
186                 CPUFREQ_PATH_PREFIX,
187                 res_name,
188                 CPUFREQ_MAX_FREQ_PATH_SUFFIX);
189
190         ret = sysfs_write_int(path, freq);
191         if (ret < 0)
192                 return ret;
193         return 0;
194 }
195
196 static int tm2_dvfs_get_up_threshold(char *res_name)
197 {
198         char path[PATH_MAX];
199         int val, ret;
200
201         if (!res_name)
202                 return -EINVAL;
203
204         snprintf(path, PATH_MAX, "%s%s%s",
205                 CPUFREQ_PATH_PREFIX,
206                 res_name,
207                 CPUFREQ_UP_THRESHOLD_PATH_SUFFIX);
208
209         ret = sysfs_read_int(path, &val);
210         if (ret < 0)
211                 return ret;
212
213         return val;
214 }
215
216 static int tm2_dvfs_set_up_threshold(char *res_name, int up_threshold)
217 {
218         char path[PATH_MAX];
219         int ret;
220
221         if ((!res_name) || (up_threshold < 0))
222                 return -EINVAL;
223
224         snprintf(path, PATH_MAX, "%s%s%s",
225                 CPUFREQ_PATH_PREFIX,
226                 res_name,
227                 CPUFREQ_UP_THRESHOLD_PATH_SUFFIX);
228
229         ret = sysfs_write_int(path, up_threshold);
230         if (ret < 0)
231                 return ret;
232
233         return 0;
234 }
235
236 static int tm2_dvfs_get_load_table(char *res_name, void *pass_cpu_load_table)
237 {
238         return 0;
239 }
240
241 static struct pass_resource_dvfs_ops tm2_cpu_dvfs_ops =  {
242         .get_curr_governor = tm2_dvfs_get_curr_governor,
243         .set_curr_governor = tm2_dvfs_set_curr_governor,
244         .get_avail_governor = NULL,
245         .get_curr_freq = tm2_dvfs_get_curr_freq,
246         .get_min_freq = tm2_dvfs_get_min_freq,
247         .set_min_freq = tm2_dvfs_set_min_freq,
248         .get_max_freq = tm2_dvfs_get_max_freq,
249         .set_max_freq = tm2_dvfs_set_max_freq,
250         .get_up_threshold = tm2_dvfs_get_up_threshold,
251         .set_up_threshold = tm2_dvfs_set_up_threshold,
252         .get_load_table = tm2_dvfs_get_load_table,
253 };
254
255 static int tm2_hotplug_get_online_state(char *res_name, int cpu)
256 {
257         char path[PATH_MAX];
258         int ret, online;
259
260         if ((!res_name))
261                 return -EINVAL;
262
263         snprintf(path, PATH_MAX, "%s%d%s",
264                 CPU_ONLINE_PATH_PREFIX,
265                 cpu,
266                 CPU_ONLINE_PATH_SUFFIX);
267
268         ret = sysfs_read_int(path, &online);
269         if (ret < 0)
270                 return ret;
271
272         return online;
273 }
274
275 static int tm2_hotplug_set_online_state(char *res_name, int cpu, int on)
276 {
277         char path[PATH_MAX];
278         int ret;
279
280         if ((!res_name))
281                 return -EINVAL;
282         if ((on != CPU_ONLINE_STATE_ON) && (on != CPU_ONLINE_STATE_OFF))
283                 return -EINVAL;
284
285         /*
286          * NOTE: Exynos SoC series cannot turn off the CPU0
287          * because of h/w design. To prevent the critical problem,
288          * if someone try to turn off the CPU0, just return without any
289          * opertaion.
290          */
291         if (on == 0 && cpu == 0) {
292                 _E("cannot turn off the CPU0");
293                 return 0;
294         }
295
296         snprintf(path, PATH_MAX, "%s%d%s",
297                 CPU_ONLINE_PATH_PREFIX,
298                 cpu,
299                 CPU_ONLINE_PATH_SUFFIX);
300
301         ret = sysfs_write_int(path, on);
302         if (ret < 0)
303                 return ret;
304
305         return 0;
306 }
307
308 static struct pass_resource_hotplug_ops tm2_cpu_hotplus_ops = {
309         .get_online_state = tm2_hotplug_get_online_state,
310         .set_online_state = tm2_hotplug_set_online_state,
311         .get_online_min_num = NULL,
312         .set_online_min_num = NULL,
313         .get_online_max_num = NULL,
314         .set_online_max_num = NULL,
315 };
316
317 static int tm2_tmu_get_temp(char *res_thermal_name)
318 {
319         char path[PATH_MAX];
320         int temp, ret;
321
322         if (!res_thermal_name)
323                 return -EINVAL;
324
325         snprintf(path, PATH_MAX, "%s%s%s",
326                 TMU_PATH_PREFIX,
327                 res_thermal_name,
328                 TMU_TEMP_PATH_SUFFIX);
329
330         ret = sysfs_read_int(path, &temp);
331         if (ret < 0)
332                 return ret;
333
334         return temp;
335 }
336
337 static int tm2_tmu_get_policy(char *res_thermal_name, char *policy)
338 {
339         char path[PATH_MAX];
340         int ret;
341
342         if ((!res_thermal_name) || (!policy))
343                 return -EINVAL;
344
345         snprintf(path, PATH_MAX, "%s%s%s",
346                 TMU_PATH_PREFIX,
347                 res_thermal_name,
348                 TMU_POLICY_PATH_SUFFIX);
349
350         ret = sysfs_read_str(path, policy, BUFF_MAX);
351         if (ret < 0)
352                 return ret;
353
354         return 0;
355 }
356
357 static struct pass_resource_tmu_ops tm2_cpu_tmu_ops = {
358         .get_temp = tm2_tmu_get_temp,
359         .get_policy = tm2_tmu_get_policy,
360 };
361
362 static int tm2_cpu_open(char *res_name, struct pass_resource_info *info,
363                 struct pass_resource_common **common)
364 {
365         struct pass_resource_cpu *cpu_res;
366
367         if (!info)
368                 return -EINVAL;
369
370         /* TODO: Possibility of a memory leak */
371         cpu_res = calloc(1, sizeof(struct pass_resource_cpu));
372         if (!cpu_res)
373                 return -ENOMEM;
374
375         cpu_res->common.info = info;
376         cpu_res->dvfs = tm2_cpu_dvfs_ops;
377         cpu_res->hotplug = tm2_cpu_hotplus_ops;
378         cpu_res->tmu = tm2_cpu_tmu_ops;
379
380         *common = (struct pass_resource_common *) cpu_res;
381
382         return 0;
383 }
384
385 static int tm2_cpu_close(char *res_name, struct pass_resource_common *common)
386 {
387         if (!common)
388                 return -EINVAL;
389
390         free(common);
391
392         return 0;
393 }
394
395 HAL_MODULE_STRUCTURE = {
396         .magic = HAL_INFO_TAG,
397         .hal_version = HAL_VERSION,
398         .device_version = DEV_VERSION_CPU,
399         .id = PASS_RESOURCE_CPU_ID,
400         .name = PASS_RESOURCE_CPU_NAME,
401         .open = tm2_cpu_open,
402         .close = tm2_cpu_close,
403 };