89e318083fea1a7ca4857335c8c70e6e80a2432a
[platform/core/system/pass.git] / src / resource / resource-cpu.c
1 /*
2  * PASS (Power Aware System Service) - CPU Resource Driver
3  *
4  * Copyright (c) 2021 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
19 /**
20  * @file        resource-cpu.c
21  * @brief       TBD
22  * @ingroup     TBD
23  */
24
25 #include <glib.h>
26
27 #include <hal/hal-power.h>
28
29 #include <util/common.h>
30 #include <util/devices.h>
31 #include <util/log.h>
32
33 #include <libsyscommon/resource-manager.h>
34 #include <libsyscommon/resource-type.h>
35 #include <libsyscommon/resource-device.h>
36
37 #include <resource-monitor/resource-monitor.h>
38
39 struct cpu_context {
40         char *device_name;
41         int index;
42 };
43
44 static int cpu_get_value_from_hal_power(struct syscommon_resman_resource *res,
45                                 const struct syscommon_resman_resource_attribute *attr,
46                                 void *data)
47 {
48         struct cpu_context *ctx;
49         int *val = (int *)data;
50         int _val, type;
51
52         if (!res || !attr || !data)
53                 return -EINVAL;
54
55         ctx = syscommon_resman_get_resource_privdata(res);
56         if (!ctx)
57                 return -EINVAL;
58
59         if (!ctx->device_name) {
60                 _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n",
61                                 syscommon_resman_get_resource_name(res));
62                 return -EINVAL;
63         }
64
65         type = syscommon_resman_get_resource_type(res);
66
67         switch (attr->id) {
68         case CPU_ATTR_CUR_FREQ:
69                 _val = hal_power_dvfs_get_curr_freq(type, ctx->device_name);
70                 break;
71         case CPU_ATTR_MIN_FREQ:
72                 _val = hal_power_dvfs_get_min_freq(type, ctx->device_name);
73                 break;
74         case CPU_ATTR_MAX_FREQ:
75                 _val = hal_power_dvfs_get_max_freq(type, ctx->device_name);
76                 break;
77         case CPU_ATTR_AVAILABLE_MIN_FREQ:
78                 _val = hal_power_dvfs_get_available_min_freq(type, ctx->device_name);
79                 break;
80         case CPU_ATTR_AVAILABLE_MAX_FREQ:
81                 _val = hal_power_dvfs_get_available_max_freq(type, ctx->device_name);
82                 break;
83         default:
84                 return -EINVAL;
85         }
86
87         if (_val < 0)
88                 return -EINVAL;
89
90         *val = _val;
91
92         return 0;
93 }
94
95 static int cpu_get_string_value(struct syscommon_resman_resource *res,
96                                 const struct syscommon_resman_resource_attribute *attr,
97                                 void *data)
98 {
99         struct cpu_context *ctx;
100         char *buf = (char *)data;
101         int val;
102
103         if (!res || !attr || !data)
104                 return -EINVAL;
105
106         ctx = syscommon_resman_get_resource_privdata(res);
107         if (!ctx)
108                 return -EINVAL;
109
110         if (!ctx->device_name) {
111                 _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n",
112                                 syscommon_resman_get_resource_name(res));
113                 return -EINVAL;
114         }
115
116         switch (attr->id) {
117         case CPU_ATTR_CUR_GOVERNOR:
118                 val = hal_power_dvfs_get_curr_governor(syscommon_resman_get_resource_type(res),
119                                                         ctx->device_name, buf);
120                 if (val < 0)
121                         return -EINVAL;
122                 break;
123         case CPU_ATTR_NAME:
124                 strncpy(buf, ctx->device_name, BUFF_MAX);
125                 break;
126         }
127
128         return 0;
129 }
130
131 static const struct syscommon_resman_resource_attribute cpu_attrs[] = {
132         {
133                 .name   = "CPU_ATTR_CUR_FREQ",
134                 .id     = CPU_ATTR_CUR_FREQ,
135                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_INT,
136                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
137                 .ops    = {
138                         .get = cpu_get_value_from_hal_power,
139                 },
140         }, {
141                 .name   = "CPU_ATTR_MIN_FREQ",
142                 .id     = CPU_ATTR_MIN_FREQ,
143                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_INT,
144                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
145                 .ops    = {
146                         .get = cpu_get_value_from_hal_power,
147                 },
148         }, {
149                 .name   = "CPU_ATTR_MAX_FREQ",
150                 .id     = CPU_ATTR_MAX_FREQ,
151                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_INT,
152                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
153                 .ops    = {
154                         .get = cpu_get_value_from_hal_power,
155                 }
156         }, {
157                 .name   = "CPU_ATTR_AVAILABLE_MIN_FREQ",
158                 .id     = CPU_ATTR_AVAILABLE_MIN_FREQ,
159                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_INT,
160                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
161                 .ops    = {
162                         .get = cpu_get_value_from_hal_power,
163                 }
164         }, {
165                 .name   = "CPU_ATTR_AVAILABLE_MAX_FREQ",
166                 .id     = CPU_ATTR_AVAILABLE_MAX_FREQ,
167                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_INT,
168                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
169                 .ops    = {
170                         .get = cpu_get_value_from_hal_power,
171                 }
172         }, {
173                 .name   = "CPU_ATTR_CUR_GOVERNOR",
174                 .id     = CPU_ATTR_CUR_GOVERNOR,
175                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_STRING,
176                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
177                 .ops    = {
178                         .get = cpu_get_string_value,
179                 }
180         }, {
181                 .name   = "CPU_ATTR_NAME",
182                 .id     = CPU_ATTR_NAME,
183                 .type   = SYSCOMMON_RESMAN_DATA_TYPE_STRING,
184                 .flag   = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
185                 .ops    = {
186                         .get = cpu_get_string_value,
187                 }
188         },
189 };
190
191 static int cpu_setup_cluster_id(struct syscommon_resman_resource *res,
192                                 const struct syscommon_resman_resource_control *ctrl,
193                                 const void *data)
194 {
195         struct cpu_context *ctx;
196         const struct syscommon_resman_resource_device *device;
197         int resource_index = (int)(intptr_t)data;
198
199         if (!res || !ctrl)
200                 return -EINVAL;
201
202         ctx = syscommon_resman_get_resource_privdata(res);
203         if (!ctx)
204                 return -EINVAL;
205
206         device = syscommon_resman_find_resource_device(syscommon_resman_get_resource_type(res), resource_index);
207         if (!device) {
208                 _E("Not available resource: type: %s, index: %d\n",
209                                 syscommon_resman_get_resource_name(res), resource_index);
210                 return -EINVAL;
211         }
212
213         if (ctx->device_name)
214                 free(ctx->device_name);
215
216         ctx->device_name = g_strdup(device->name);
217         ctx->index = resource_index;
218
219         return 0;
220 }
221
222 static const struct syscommon_resman_resource_control cpu_ctrls[] = {
223         {
224                 .name = "CPU_CTRL_CLUSTER_ID",
225                 .id = CPU_CTRL_CLUSTER_ID,
226                 .ops = {
227                         .set = cpu_setup_cluster_id,
228                 },
229         },
230 };
231
232 static int cpu_create(struct syscommon_resman_resource *res)
233 {
234         struct cpu_context *ctx = syscommon_resman_get_resource_privdata(res);
235
236         ctx = calloc(1, sizeof(struct cpu_context));
237         if (!ctx)
238                 return -ENOMEM;
239
240         syscommon_resman_set_resource_privdata(res, ctx);
241
242         return 0;
243 }
244
245 static void cpu_delete(struct syscommon_resman_resource *res)
246 {
247         struct cpu_context *ctx;
248
249         if (!res)
250                 return;
251
252         ctx = syscommon_resman_get_resource_privdata(res);
253         if (!ctx)
254                 return;
255
256         if (ctx->device_name) {
257                 free(ctx->device_name);
258                 ctx->device_name = NULL;
259         }
260
261         free(ctx);
262         syscommon_resman_set_resource_privdata(res, NULL);
263 }
264
265 static const struct syscommon_resman_resource_driver cpu_resource_driver = {
266         .name           = "CPU",
267         .type           = RESOURCE_TYPE_CPU,
268         .attrs          = cpu_attrs,
269         .num_attrs      = ARRAY_SIZE(cpu_attrs),
270         .ctrls          = cpu_ctrls,
271         .num_ctrls      = ARRAY_SIZE(cpu_ctrls),
272         .ops            = {
273                 .create = cpu_create,
274                 .delete = cpu_delete,
275         },
276 };
277 SYSCOMMON_RESMAN_RESOURCE_DRIVER_REGISTER(&cpu_resource_driver)
278