pass-hal: tm2: Add implementation of HAL for GPU
[platform/adaptation/tm2/pass-hal-tm2.git] / src / gpu / gpu.c
1 #include <errno.h>
2 #include <limits.h>
3 #include <pass/hal.h>
4 #include <pass/hal-log.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "../shared/sysfs.h"
10
11 /* TODO: Version! */
12 #define HAL_VERSION     MAKE_2B_CODE_4(VER_MAJOR,VER_MINOR,VER_REVISION,VER_RELEASE)
13 #define DEV_VERSION_GPU MAKE_2B_CODE_2(1,0)
14
15 #define DEVFREQ_GPU_PATH_PREFIX                 "/sys/devices/platform/soc/"
16 #define DEVFREQ_GPU_PATH_INFIX                  "/devfreq/"
17 #define DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX   "/governor"
18 #define DEVFREQ_GPU_CURR_FREQ_PATH_SUFFIX       "/cur_freq"
19 #define DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX        "/min_freq"
20 #define DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX        "/max_freq"
21
22 #define TMU_PATH_PREFIX                         "/sys/class/thermal/thermal_zone"
23 #define TMU_TEMP_PATH_SUFFIX                    "/temp"
24 #define TMU_POLICY_PATH_SUFFIX                  "/policy"
25
26 #define TM2_GPU_THERMAL_ZONE_NUM                2
27
28 static int tm2_dvfs_get_curr_governor(char *res_name, char *governor)
29 {
30         char path[PATH_MAX];
31         int ret;
32
33         if ((!res_name) || (!governor))
34                 return -EINVAL;
35
36         snprintf(path, PATH_MAX, "%s%s%s%s%s",
37                 DEVFREQ_GPU_PATH_PREFIX,
38                 res_name,
39                 DEVFREQ_GPU_PATH_INFIX,
40                 res_name,
41                 DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX);
42
43         ret = sysfs_read_str(path, governor, BUFF_MAX);
44         if (ret < 0)
45                 return ret;
46
47         return 0;
48 }
49
50 static int tm2_dvfs_set_curr_governor(char *res_name, char *governor)
51 {
52         char path[PATH_MAX];
53         int ret;
54
55         if ((!res_name) || (!governor))
56                 return -EINVAL;
57
58         snprintf(path, PATH_MAX, "%s%s%s%s%s",
59                 DEVFREQ_GPU_PATH_PREFIX,
60                 res_name,
61                 DEVFREQ_GPU_PATH_INFIX,
62                 res_name,
63                 DEVFREQ_GPU_CURR_GOVERNOR_PATH_SUFFIX);
64
65         ret = sysfs_write_str(path, governor);
66         if (ret < 0)
67                 return ret;
68
69         return 0;
70 }
71
72 static int tm2_dvfs_get_curr_freq(char *res_name)
73 {
74         char path[PATH_MAX];
75         int freq, ret;
76
77         if (!res_name)
78                 return -EINVAL;
79
80         snprintf(path, PATH_MAX, "%s%s%s%s%s",
81                 DEVFREQ_GPU_PATH_PREFIX,
82                 res_name,
83                 DEVFREQ_GPU_PATH_INFIX,
84                 res_name,
85                 DEVFREQ_GPU_CURR_FREQ_PATH_SUFFIX);
86
87         ret = sysfs_read_int(path, &freq);
88         if (ret < 0)
89                 return ret;
90
91         return freq;
92 }
93
94 static int tm2_dvfs_get_min_freq(char *res_name)
95 {
96         char path[PATH_MAX];
97         int freq, ret;
98
99         if (!res_name)
100                 return -EINVAL;
101
102         snprintf(path, PATH_MAX, "%s%s%s%s%s",
103                 DEVFREQ_GPU_PATH_PREFIX,
104                 res_name,
105                 DEVFREQ_GPU_PATH_INFIX,
106                 res_name,
107                 DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX);
108
109         ret = sysfs_read_int(path, &freq);
110         if (ret < 0)
111                 return ret;
112
113         return freq;
114 }
115
116 static int tm2_dvfs_set_min_freq(char *res_name, int freq)
117 {
118         char path[PATH_MAX];
119         int ret;
120
121         if ((!res_name) || (freq < 0))
122                 return -EINVAL;
123
124         snprintf(path, PATH_MAX, "%s%s%s%s%s",
125                 DEVFREQ_GPU_PATH_PREFIX,
126                 res_name,
127                 DEVFREQ_GPU_PATH_INFIX,
128                 res_name,
129                 DEVFREQ_GPU_MIN_FREQ_PATH_SUFFIX);
130
131         ret = sysfs_write_int(path, freq);
132         if (ret < 0)
133                 return ret;
134
135         return 0;
136 }
137
138 static int tm2_dvfs_get_max_freq(char *res_name)
139 {
140         char path[PATH_MAX];
141         int freq, ret;
142
143         if (!res_name)
144                 return -EINVAL;
145
146         snprintf(path, PATH_MAX, "%s%s%s%s%s",
147                 DEVFREQ_GPU_PATH_PREFIX,
148                 res_name,
149                 DEVFREQ_GPU_PATH_INFIX,
150                 res_name,
151                 DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX);
152
153         ret = sysfs_read_int(path, &freq);
154         if (ret < 0)
155                 return ret;
156
157         return freq;
158 }
159
160 static int tm2_dvfs_set_max_freq(char *res_name, int freq)
161 {
162         char path[PATH_MAX];
163         int ret;
164
165         if ((!res_name) || (freq < 0))
166                 return -EINVAL;
167
168         snprintf(path, PATH_MAX, "%s%s%s%s%s",
169                 DEVFREQ_GPU_PATH_PREFIX,
170                 res_name,
171                 DEVFREQ_GPU_PATH_INFIX,
172                 res_name,
173                 DEVFREQ_GPU_MAX_FREQ_PATH_SUFFIX);
174
175         ret = sysfs_write_int(path, freq);
176         if (ret < 0)
177                 return ret;
178         return 0;
179 }
180
181
182 static struct pass_resource_dvfs_ops tm2_gpu_dvfs_ops =  {
183         .get_curr_governor = tm2_dvfs_get_curr_governor,
184         .set_curr_governor = tm2_dvfs_set_curr_governor,
185         .get_avail_governor = NULL,
186         .get_curr_freq = tm2_dvfs_get_curr_freq,
187         .get_min_freq = tm2_dvfs_get_min_freq,
188         .set_min_freq = tm2_dvfs_set_min_freq,
189         .get_max_freq = tm2_dvfs_get_max_freq,
190         .set_max_freq = tm2_dvfs_set_max_freq,
191         .get_up_threshold = NULL,
192         .set_up_threshold = NULL,
193         .get_load_table = NULL,
194 };
195
196 static int tm2_tmu_get_temp(char *res_name)
197 {
198         char path[PATH_MAX];
199         int temp;
200         int ret;
201
202         if (!res_name)
203                 return -EINVAL;
204
205         snprintf(path, PATH_MAX, "%s%d%s",
206                 TMU_PATH_PREFIX,
207                 TM2_GPU_THERMAL_ZONE_NUM,
208                 TMU_TEMP_PATH_SUFFIX);
209
210         ret = sysfs_read_int(path, &temp);
211         if (ret < 0)
212                 return ret;
213
214         return temp;
215 }
216
217 static int tm2_tmu_get_policy(char *res_name, char *policy)
218 {
219         char path[PATH_MAX];
220         int ret;
221
222         if ((!res_name) || (!policy))
223                 return -EINVAL;
224
225         snprintf(path, PATH_MAX, "%s%d%s",
226                 TMU_PATH_PREFIX,
227                 TM2_GPU_THERMAL_ZONE_NUM,
228                 TMU_POLICY_PATH_SUFFIX);
229
230         ret = sysfs_read_str(path, policy, BUFF_MAX);
231         if (ret < 0)
232                 return ret;
233
234         return 0;
235 }
236
237 static struct pass_resource_tmu_ops tm2_gpu_tmu_ops = {
238         .get_temp = tm2_tmu_get_temp,
239         .get_policy = tm2_tmu_get_policy,
240 };
241
242 static int tm2_gpu_open(struct pass_resource_info *info,
243                 struct pass_resource_common **common)
244 {
245         struct pass_resource_gpu *gpu_res;
246
247         if (!info)
248                 return -EINVAL;
249
250         /* TODO: Possibility of a memory leak */
251         gpu_res = calloc(1, sizeof(struct pass_resource_gpu));
252         if (!gpu_res)
253                 return -ENOMEM;
254
255         gpu_res->common.info = info;
256         gpu_res->dvfs = tm2_gpu_dvfs_ops;
257         gpu_res->tmu = tm2_gpu_tmu_ops;
258
259         *common = (struct pass_resource_common *) gpu_res;
260
261         return 0;
262 }
263
264 static int tm2_gpu_close(struct pass_resource_common *common)
265 {
266         if (!common)
267                 return -EINVAL;
268
269         free(common);
270
271         return 0;
272 }
273
274 HAL_MODULE_STRUCTURE = {
275         .magic = HAL_INFO_TAG,
276         .hal_version = HAL_VERSION,
277         .device_version = DEV_VERSION_GPU,
278         .id = PASS_RESOURCE_GPU_ID,
279         .name = PASS_RESOURCE_GPU_NAME,
280         .author = "Wook Song <wook16.song@samsung.com>",
281         .open = tm2_gpu_open,
282         .close = tm2_gpu_close,
283 };