2575ff5830c545e5895cbace92bf003b1d0a0a93
[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/log.h>
31 #include <util/resource.h>
32
33 #include <tmonitor/tmonitor.h>
34
35 struct cpu_context {
36         char *device_name;
37         int index;
38 };
39
40 static int cpu_get_value_from_hal_power(const struct resource *res,
41                                 const struct resource_attribute *attr,
42                                 void *data)
43 {
44         struct cpu_context *ctx;
45         int *val = (int *)data;
46         int _val;
47
48         if (!res || !res->priv || !attr || !data)
49                 return -EINVAL;
50
51         ctx = res->priv;
52
53         if (!ctx->device_name) {
54                 _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name);
55                 return -EINVAL;
56         }
57
58         switch (attr->id) {
59         case CPU_ATTR_CUR_FREQ:
60                 _val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name);
61                 break;
62         case CPU_ATTR_MIN_FREQ:
63                 _val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name);
64                 break;
65         case CPU_ATTR_MAX_FREQ:
66                 _val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name);
67                 break;
68         case CPU_ATTR_AVAILABLE_MIN_FREQ:
69                 _val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name);
70                 break;
71         case CPU_ATTR_AVAILABLE_MAX_FREQ:
72                 _val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name);
73                 break;
74         default:
75                 return -EINVAL;
76         }
77
78         if (_val < 0)
79                 return -EINVAL;
80
81         *val = _val;
82
83         return 0;
84 }
85
86 static int cpu_get_curr_governor(const struct resource *res,
87                                 const struct resource_attribute *attr,
88                                 void *data)
89 {
90         struct cpu_context *ctx;
91         char *buf = (char *)data;
92         int val;
93
94         if (!res || !res->priv || !attr || !data)
95                 return -EINVAL;
96
97         ctx = res->priv;
98
99         if (!ctx->device_name) {
100                 _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name);
101                 return -EINVAL;
102         }
103
104         val = hal_power_dvfs_get_curr_governor(res->type, ctx->device_name, buf);
105         if (val < 0)
106                 return -EINVAL;
107
108         return 0;
109 }
110
111 static const struct resource_attribute cpu_attrs[] = {
112         {
113                 .name   = "CPU_ATTR_CUR_FREQ",
114                 .id     = CPU_ATTR_CUR_FREQ,
115                 .type   = DATA_TYPE_INT,
116                 .ops    = {
117                         .get = cpu_get_value_from_hal_power,
118                 },
119         }, {
120                 .name   = "CPU_ATTR_MIN_FREQ",
121                 .id     = CPU_ATTR_MIN_FREQ,
122                 .type   = DATA_TYPE_INT,
123                 .ops    = {
124                         .get = cpu_get_value_from_hal_power,
125                 },
126         }, {
127                 .name   = "CPU_ATTR_MAX_FREQ",
128                 .id     = CPU_ATTR_MAX_FREQ,
129                 .type   = DATA_TYPE_INT,
130                 .ops    = {
131                         .get = cpu_get_value_from_hal_power,
132                 }
133         }, {
134                 .name   = "CPU_ATTR_AVAILABLE_MIN_FREQ",
135                 .id     = CPU_ATTR_AVAILABLE_MIN_FREQ,
136                 .type   = DATA_TYPE_INT,
137                 .ops    = {
138                         .get = cpu_get_value_from_hal_power,
139                 }
140         }, {
141                 .name   = "CPU_ATTR_AVAILABLE_MAX_FREQ",
142                 .id     = CPU_ATTR_AVAILABLE_MAX_FREQ,
143                 .type   = DATA_TYPE_INT,
144                 .ops    = {
145                         .get = cpu_get_value_from_hal_power,
146                 }
147         }, {
148                 .name   = "CPU_ATTR_CUR_GOVERNOR",
149                 .id     = CPU_ATTR_CUR_GOVERNOR,
150                 .type   = DATA_TYPE_STRING,
151                 .ops    = {
152                         .get = cpu_get_curr_governor,
153                 }
154         },
155 };
156
157 static int cpu_setup_cluster_id(const struct resource *res,
158                                 const struct resource_control *ctrl,
159                                 const void *data)
160 {
161         struct cpu_context *ctx;
162         const struct resource_device *device;
163         int resource_index = (int)(intptr_t)data;
164
165         if (!res || !res->priv || !ctrl)
166                 return -EINVAL;
167
168         device = find_resource_device(res->type, resource_index);
169         if (!device) {
170                 _E("Not available resource: type: %s, index: %d\n",
171                                 res->name, resource_index);
172                 return -EINVAL;
173         }
174
175         ctx = res->priv;
176
177         if (ctx->device_name)
178                 free(ctx->device_name);
179
180         ctx->device_name = g_strdup(device->name);
181         ctx->index = resource_index;
182
183         return 0;
184 }
185
186 static const struct resource_control cpu_ctrls[] = {
187         {
188                 .name = "CPU_CTRL_CLUSTER_ID",
189                 .id = CPU_CTRL_CLUSTER_ID,
190                 .ops = {
191                         .set = cpu_setup_cluster_id,
192                 },
193         },
194 };
195
196 static int cpu_init(struct resource *res)
197 {
198         struct cpu_context *ctx;
199
200         ctx = calloc(1, sizeof(struct cpu_context));
201         if (!ctx)
202                 return -ENOMEM;
203
204         res->priv = ctx;
205
206         return 0;
207 }
208
209 static void cpu_exit(struct resource *res)
210 {
211         struct cpu_context *ctx;
212
213         if (res && res->priv) {
214                 ctx = res->priv;
215                 if (ctx->device_name) {
216                         free(ctx->device_name);
217                         ctx->device_name = NULL;
218                 }
219                 free(ctx);
220                 res->priv = NULL;
221         }
222 }
223
224 static const struct resource_driver cpu_resource_driver = {
225         .name           = "CPU",
226         .type           = RESOURCE_TYPE_CPU,
227         .attrs          = cpu_attrs,
228         .num_attrs      = ARRAY_SIZE(cpu_attrs),
229         .ctrls          = cpu_ctrls,
230         .num_ctrls      = ARRAY_SIZE(cpu_ctrls),
231         .ops            = {
232                 .init = cpu_init,
233                 .exit = cpu_exit,
234         },
235 };
236 RESOURCE_DRIVER_REGISTER(&cpu_resource_driver)
237