pass-hal: standard: Fix svace warnings
[platform/adaptation/pass-hal-standard.git] / src / hal-backend-power.c
1 /*
2  * HAL backend for hal-api-power which is used for PASS daemon
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 #include <errno.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <hal/hal-power-interface.h>
26
27 #include "sysfs.h"
28
29 #define BUFF_MAX        255
30
31 /*************************
32  * H/W Resource Defintions
33  */
34 #define CPUFREQ_PATH_PREFIX                     "/sys/devices/system/cpu/"
35 #define CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX       "/cpufreq/scaling_governor"
36 #define CPUFREQ_AVAIL_GOVERNOR_PATH_SUFFIX      "/cpufreq/scaling_available_governors"
37
38 /*
39  * The cpuinfo_cur_freq indicates the actual operating CPU freqeuncy
40  * and scaling_cur_freq is the CPU frequency set by the CPUFREQ policy.
41  */
42 #define CPUFREQ_CURR_FREQ_PATH_SUFFIX           "/cpufreq/cpuinfo_cur_freq"
43 #define CPUFREQ_AVAILABLE_MIN_FREQ_PATH_SUFFIX  "/cpufreq/cpuinfo_min_freq"
44 #define CPUFREQ_AVAILABLE_MAX_FREQ_PATH_SUFFIX  "/cpufreq/cpuinfo_max_freq"
45 #define CPUFREQ_MIN_FREQ_PATH_SUFFIX            "/cpufreq/scaling_min_freq"
46 #define CPUFREQ_MAX_FREQ_PATH_SUFFIX            "/cpufreq/scaling_max_freq"
47 #define CPUFREQ_UP_THRESHOLD_PATH_SUFFIX        "/cpufreq/ondemand/up_threshold"
48
49 #define CPU_ONLINE_PATH_PREFIX                  "/sys/devices/system/cpu/cpu"
50 #define CPU_ONLINE_PATH_SUFFIX                  "/online"
51 #define CPU_ONLINE_STATE_ON                     1
52 #define CPU_ONLINE_STATE_OFF                    0
53
54 #define TMU_PATH_PREFIX                         "/sys/class/thermal/"
55 #define TMU_TEMP_PATH_SUFFIX                    "/temp"
56 #define TMU_POLICY_PATH_SUFFIX                  "/policy"
57 #define TMU_MAX_TEMP_MASK                               0xFFFFF
58
59 #define DEVFREQ_BUS_PATH_PREFIX                 "/sys/class/devfreq/"
60 #define DEVFREQ_BUS_CURR_GOVERNOR_PATH_SUFFIX   "/governor"
61 #define DEVFREQ_BUS_CURR_FREQ_PATH_SUFFIX       "/cur_freq"
62 #define DEVFREQ_BUS_MIN_FREQ_PATH_SUFFIX        "/min_freq"
63 #define DEVFREQ_BUS_MAX_FREQ_PATH_SUFFIX        "/max_freq"
64 #define DEVFREQ_BUS_AVAILABLE_FREQ_PATH_SUFFIX  "/available_frequencies"
65
66 #define FAULT_AROUND_BYTES_PATH                 "/sys/kernel/debug/fault_around_bytes"
67
68 /*************************************************
69  * HAL backend implementation for CPU H/W Resource
70  */
71 static int cpufreq_dvfs_get_curr_governor(char *res_name, char *governor)
72 {
73         char path[PATH_MAX];
74         int ret;
75
76         if ((!res_name) || (!governor))
77                 return -EINVAL;
78
79         snprintf(path, PATH_MAX, "%s%s%s",
80                 CPUFREQ_PATH_PREFIX,
81                 res_name,
82                 CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX);
83
84         ret = sysfs_read_str(path, governor, BUFF_MAX);
85         if (ret < 0)
86                 return ret;
87
88         return 0;
89 }
90
91 static int cpufreq_dvfs_set_curr_governor(char *res_name, char *governor)
92 {
93         char path[PATH_MAX];
94         int ret;
95
96         if ((!res_name) || (!governor))
97                 return -EINVAL;
98
99         snprintf(path, PATH_MAX, "%s%s%s",
100                 CPUFREQ_PATH_PREFIX,
101                 res_name,
102                 CPUFREQ_CURR_GOVERNOR_PATH_SUFFIX);
103
104         ret = sysfs_write_str(path, governor);
105         if (ret < 0)
106                 return ret;
107
108         return 0;
109 }
110
111 static int cpufreq_dvfs_get_curr_freq(char *res_name)
112 {
113         char path[PATH_MAX];
114         int freq, ret;
115
116         if (!res_name)
117                 return -EINVAL;
118
119         snprintf(path, PATH_MAX, "%s%s%s",
120                 CPUFREQ_PATH_PREFIX,
121                 res_name,
122                 CPUFREQ_CURR_FREQ_PATH_SUFFIX);
123
124         ret = sysfs_read_int(path, &freq);
125         if (ret < 0)
126                 return ret;
127
128         return freq;
129 }
130
131 static int cpufreq_dvfs_get_min_freq(char *res_name)
132 {
133         char path[PATH_MAX];
134         int freq, ret;
135
136         if (!res_name)
137                 return -EINVAL;
138
139         snprintf(path, PATH_MAX, "%s%s%s",
140                 CPUFREQ_PATH_PREFIX,
141                 res_name,
142                 CPUFREQ_MIN_FREQ_PATH_SUFFIX);
143
144         ret = sysfs_read_int(path, &freq);
145         if (ret < 0)
146                 return ret;
147
148         return freq;
149 }
150
151 static int cpufreq_dvfs_set_min_freq(char *res_name, int freq)
152 {
153         char path[PATH_MAX];
154         int ret;
155
156         if ((!res_name) || (freq < 0))
157                 return -EINVAL;
158
159         snprintf(path, PATH_MAX, "%s%s%s",
160                 CPUFREQ_PATH_PREFIX,
161                 res_name,
162                 CPUFREQ_MIN_FREQ_PATH_SUFFIX);
163
164         ret = sysfs_write_int(path, freq);
165         if (ret < 0)
166                 return ret;
167
168         return 0;
169 }
170
171 static int cpufreq_dvfs_get_max_freq(char *res_name)
172 {
173         char path[PATH_MAX];
174         int freq, ret;
175
176         if (!res_name)
177                 return -EINVAL;
178
179         snprintf(path, PATH_MAX, "%s%s%s",
180                 CPUFREQ_PATH_PREFIX,
181                 res_name,
182                 CPUFREQ_MAX_FREQ_PATH_SUFFIX);
183
184         ret = sysfs_read_int(path, &freq);
185         if (ret < 0)
186                 return ret;
187
188         return freq;
189 }
190
191 static int cpufreq_dvfs_set_max_freq(char *res_name, int freq)
192 {
193         char path[PATH_MAX];
194         int ret;
195
196         if ((!res_name) || (freq < 0))
197                 return -EINVAL;
198
199         snprintf(path, PATH_MAX, "%s%s%s",
200                 CPUFREQ_PATH_PREFIX,
201                 res_name,
202                 CPUFREQ_MAX_FREQ_PATH_SUFFIX);
203
204         ret = sysfs_write_int(path, freq);
205         if (ret < 0)
206                 return ret;
207         return 0;
208 }
209
210 static int cpufreq_dvfs_get_available_min_freq(char *res_name)
211 {
212         char path[PATH_MAX];
213         int val, ret;
214
215         if (!res_name)
216                 return -EINVAL;
217
218         snprintf(path, PATH_MAX, "%s%s%s",
219                 CPUFREQ_PATH_PREFIX,
220                 res_name,
221                 CPUFREQ_AVAILABLE_MIN_FREQ_PATH_SUFFIX);
222
223         ret = sysfs_read_int(path, &val);
224         if (ret < 0)
225                 return ret;
226
227         return val;
228 }
229
230
231 static int cpufreq_dvfs_get_available_max_freq(char *res_name)
232 {
233         char path[PATH_MAX];
234         int val, ret;
235
236         if (!res_name)
237                 return -EINVAL;
238
239         snprintf(path, PATH_MAX, "%s%s%s",
240                 CPUFREQ_PATH_PREFIX,
241                 res_name,
242                 CPUFREQ_AVAILABLE_MAX_FREQ_PATH_SUFFIX);
243
244         ret = sysfs_read_int(path, &val);
245         if (ret < 0)
246                 return ret;
247
248         return val;
249 }
250
251 static int cpufreq_dvfs_get_up_threshold(char *res_name)
252 {
253         char path[PATH_MAX];
254         int val, ret;
255
256         if (!res_name)
257                 return -EINVAL;
258
259         snprintf(path, PATH_MAX, "%s%s%s",
260                 CPUFREQ_PATH_PREFIX,
261                 res_name,
262                 CPUFREQ_UP_THRESHOLD_PATH_SUFFIX);
263
264         ret = sysfs_read_int(path, &val);
265         if (ret < 0)
266                 return ret;
267
268         return val;
269 }
270
271 static int cpufreq_dvfs_set_up_threshold(char *res_name, int up_threshold)
272 {
273         char path[PATH_MAX];
274         int ret;
275
276         if ((!res_name) || (up_threshold < 0))
277                 return -EINVAL;
278
279         snprintf(path, PATH_MAX, "%s%s%s",
280                 CPUFREQ_PATH_PREFIX,
281                 res_name,
282                 CPUFREQ_UP_THRESHOLD_PATH_SUFFIX);
283
284         ret = sysfs_write_int(path, up_threshold);
285         if (ret < 0)
286                 return ret;
287
288         return 0;
289 }
290
291 static struct pass_resource_dvfs_ops cpufreq_dvfs_ops =  {
292         .get_curr_governor = cpufreq_dvfs_get_curr_governor,
293         .set_curr_governor = cpufreq_dvfs_set_curr_governor,
294         .get_curr_freq = cpufreq_dvfs_get_curr_freq,
295         .get_min_freq = cpufreq_dvfs_get_min_freq,
296         .set_min_freq = cpufreq_dvfs_set_min_freq,
297         .get_max_freq = cpufreq_dvfs_get_max_freq,
298         .set_max_freq = cpufreq_dvfs_set_max_freq,
299         .get_available_min_freq = cpufreq_dvfs_get_available_min_freq,
300         .get_available_max_freq = cpufreq_dvfs_get_available_max_freq,
301         .get_up_threshold = cpufreq_dvfs_get_up_threshold,
302         .set_up_threshold = cpufreq_dvfs_set_up_threshold,
303 };
304
305 static int cpu_hotplug_get_online_state(char *res_name, int cpu)
306 {
307         char path[PATH_MAX];
308         int ret, online;
309
310         if ((!res_name))
311                 return -EINVAL;
312
313         snprintf(path, PATH_MAX, "%s%d%s",
314                 CPU_ONLINE_PATH_PREFIX,
315                 cpu,
316                 CPU_ONLINE_PATH_SUFFIX);
317
318         ret = sysfs_read_int(path, &online);
319         if (ret < 0)
320                 return ret;
321
322         return online;
323 }
324
325 static int cpu_hotplug_set_online_state(char *res_name, int cpu, int on)
326 {
327         char path[PATH_MAX];
328         int ret;
329
330         if ((!res_name))
331                 return -EINVAL;
332         if ((on != CPU_ONLINE_STATE_ON) && (on != CPU_ONLINE_STATE_OFF))
333                 return -EINVAL;
334
335         /*
336          * NOTE: Exynos SoC series cannot turn off the CPU0
337          * because of h/w design. To prevent the critical problem,
338          * if someone try to turn off the CPU0, just return without any
339          * opertaion.
340          */
341         if (on == 0 && cpu == 0) {
342                 return 0;
343         }
344
345         snprintf(path, PATH_MAX, "%s%d%s",
346                 CPU_ONLINE_PATH_PREFIX,
347                 cpu,
348                 CPU_ONLINE_PATH_SUFFIX);
349
350         ret = sysfs_write_int(path, on);
351         if (ret < 0)
352                 return ret;
353
354         return 0;
355 }
356
357 static struct pass_resource_hotplug_ops cpu_hotplus_ops = {
358         .get_online_state = cpu_hotplug_get_online_state,
359         .set_online_state = cpu_hotplug_set_online_state,
360         .get_online_min_num = NULL,
361         .set_online_min_num = NULL,
362         .get_online_max_num = NULL,
363         .set_online_max_num = NULL,
364 };
365
366 static int tmu_get_temp(char *res_thermal_name)
367 {
368         char path[PATH_MAX];
369         int temp, ret;
370
371         if (!res_thermal_name)
372                 return -EINVAL;
373
374         snprintf(path, PATH_MAX, "%s%s%s",
375                 TMU_PATH_PREFIX,
376                 res_thermal_name,
377                 TMU_TEMP_PATH_SUFFIX);
378
379         ret = sysfs_read_int(path, &temp);
380         if (ret < 0)
381                 return ret;
382
383         /*
384          * Thermal framework provides the current temperature
385          * as five digits interger like 54430 when temperature is 54.430
386          * degrees centigrade. But, Thermal Monitor in Tizen usually
387          * use two digits interger without decimal point.
388          * So that round temperature value. It constraints the maximume
389          * temperature as 1048 degrees centigrade for preventing integer
390          * overflow. Usually, the embedded device never over 1000 degrees
391          * centigrade.
392          */
393         return (((temp & TMU_MAX_TEMP_MASK) + 500) / 1000);
394 }
395
396 static int tmu_get_policy(char *res_thermal_name, char *policy)
397 {
398         char path[PATH_MAX];
399         int ret;
400
401         if ((!res_thermal_name) || (!policy))
402                 return -EINVAL;
403
404         snprintf(path, PATH_MAX, "%s%s%s",
405                 TMU_PATH_PREFIX,
406                 res_thermal_name,
407                 TMU_POLICY_PATH_SUFFIX);
408
409         ret = sysfs_read_str(path, policy, BUFF_MAX);
410         if (ret < 0)
411                 return ret;
412
413         return 0;
414 }
415
416 static struct pass_resource_tmu_ops tmu_ops = {
417         .get_temp = tmu_get_temp,
418         .get_policy = tmu_get_policy,
419 };
420
421 /*****************************************************
422  * HAL backend implementation for BUS/GPU H/W Resource
423  */
424 static int devfreq_dvfs_get_curr_governor(char *res_name, char *governor)
425 {
426         char path[PATH_MAX];
427         int ret;
428
429         if ((!res_name) || (!governor))
430                 return -EINVAL;
431
432         snprintf(path, PATH_MAX, "%s%s%s",
433                 DEVFREQ_BUS_PATH_PREFIX,
434                 res_name,
435                 DEVFREQ_BUS_CURR_GOVERNOR_PATH_SUFFIX);
436
437         ret = sysfs_read_str(path, governor, BUFF_MAX);
438         if (ret < 0)
439                 return ret;
440
441         return 0;
442 }
443
444 static int devfreq_dvfs_set_curr_governor(char *res_name, char *governor)
445 {
446         char path[PATH_MAX];
447         int ret;
448
449         if ((!res_name) || (!governor))
450                 return -EINVAL;
451
452         snprintf(path, PATH_MAX, "%s%s%s",
453                 DEVFREQ_BUS_PATH_PREFIX,
454                 res_name,
455                 DEVFREQ_BUS_CURR_GOVERNOR_PATH_SUFFIX);
456
457         ret = sysfs_write_str(path, governor);
458         if (ret < 0)
459                 return ret;
460
461         return 0;
462 }
463
464 static int devfreq_dvfs_get_curr_freq(char *res_name)
465 {
466         char path[PATH_MAX];
467         int freq, ret;
468
469         if (!res_name)
470                 return -EINVAL;
471
472         snprintf(path, PATH_MAX, "%s%s%s",
473                 DEVFREQ_BUS_PATH_PREFIX,
474                 res_name,
475                 DEVFREQ_BUS_CURR_FREQ_PATH_SUFFIX);
476
477         ret = sysfs_read_int(path, &freq);
478         if (ret < 0)
479                 return ret;
480
481         return freq;
482 }
483
484 static int devfreq_dvfs_get_min_freq(char *res_name)
485 {
486         char path[PATH_MAX];
487         int freq, ret;
488
489         if (!res_name)
490                 return -EINVAL;
491
492         snprintf(path, PATH_MAX, "%s%s%s",
493                 DEVFREQ_BUS_PATH_PREFIX,
494                 res_name,
495                 DEVFREQ_BUS_MIN_FREQ_PATH_SUFFIX);
496
497         ret = sysfs_read_int(path, &freq);
498         if (ret < 0)
499                 return ret;
500
501         return freq;
502 }
503
504 static int devfreq_dvfs_set_min_freq(char *res_name, int freq)
505 {
506         char path[PATH_MAX];
507         int ret;
508
509         if ((!res_name) || (freq < 0))
510                 return -EINVAL;
511
512         snprintf(path, PATH_MAX, "%s%s%s",
513                 DEVFREQ_BUS_PATH_PREFIX,
514                 res_name,
515                 DEVFREQ_BUS_MIN_FREQ_PATH_SUFFIX);
516
517         ret = sysfs_write_int(path, freq);
518         if (ret < 0)
519                 return ret;
520
521         return 0;
522 }
523
524 static int devfreq_dvfs_get_max_freq(char *res_name)
525 {
526         char path[PATH_MAX];
527         int freq, ret;
528
529         if (!res_name)
530                 return -EINVAL;
531
532         snprintf(path, PATH_MAX, "%s%s%s",
533                 DEVFREQ_BUS_PATH_PREFIX,
534                 res_name,
535                 DEVFREQ_BUS_MAX_FREQ_PATH_SUFFIX);
536
537         ret = sysfs_read_int(path, &freq);
538         if (ret < 0)
539                 return ret;
540
541         return freq;
542 }
543
544 static int devfreq_dvfs_set_max_freq(char *res_name, int freq)
545 {
546         char path[PATH_MAX];
547         int ret;
548
549         if ((!res_name) || (freq < 0))
550                 return -EINVAL;
551
552         snprintf(path, PATH_MAX, "%s%s%s",
553                 DEVFREQ_BUS_PATH_PREFIX,
554                 res_name,
555                 DEVFREQ_BUS_MAX_FREQ_PATH_SUFFIX);
556
557         ret = sysfs_write_int(path, freq);
558         if (ret < 0)
559                 return ret;
560         return 0;
561 }
562
563 static int devfreq_dvfs_get_available_min_freq(char *res_name)
564 {
565         char path[PATH_MAX];
566         char buf[MAX_BUF_SIZE + 1];
567         char *p;
568         int ret;
569
570         if (!res_name)
571                 return -EINVAL;
572
573         snprintf(path, PATH_MAX, "%s%s%s",
574                 DEVFREQ_BUS_PATH_PREFIX,
575                 res_name,
576                 DEVFREQ_BUS_AVAILABLE_FREQ_PATH_SUFFIX);
577
578         ret = sysfs_read_str(path, buf, MAX_BUF_SIZE);
579         if (ret < 0)
580                 return ret;
581
582         p = strchr(buf, ' ');
583         if (p)
584                 *p = '\0';
585
586         ret = strtoul(buf, NULL, 10);
587         if (!ret)
588                 return -EINVAL;
589
590         return ret;
591 }
592
593 static int devfreq_dvfs_get_available_max_freq(char *res_name)
594 {
595         char path[PATH_MAX];
596         char buf[MAX_BUF_SIZE + 1];
597         char *p;
598         int ret;
599
600         if (!res_name)
601                 return -EINVAL;
602
603         snprintf(path, PATH_MAX, "%s%s%s",
604                 DEVFREQ_BUS_PATH_PREFIX,
605                 res_name,
606                 DEVFREQ_BUS_AVAILABLE_FREQ_PATH_SUFFIX);
607
608         ret = sysfs_read_str(path, buf, MAX_BUF_SIZE);
609         if (ret < 0)
610                 return ret;
611
612         p = strrchr(buf, ' ');
613         p = p ? p + 1 : buf;
614
615         ret = strtoul(p, NULL, 10);
616         if (!ret)
617                 return -EINVAL;
618
619         return ret;
620 }
621
622 static struct pass_resource_dvfs_ops devfreq_dvfs_ops =  {
623         .get_curr_governor = devfreq_dvfs_get_curr_governor,
624         .set_curr_governor = devfreq_dvfs_set_curr_governor,
625         .get_curr_freq = devfreq_dvfs_get_curr_freq,
626         .get_min_freq = devfreq_dvfs_get_min_freq,
627         .set_min_freq = devfreq_dvfs_set_min_freq,
628         .get_max_freq = devfreq_dvfs_get_max_freq,
629         .set_max_freq = devfreq_dvfs_set_max_freq,
630         .get_available_min_freq = devfreq_dvfs_get_available_min_freq,
631         .get_available_max_freq = devfreq_dvfs_get_available_max_freq,
632 };
633
634 /****************************************************
635  * HAL backend implementation for Memory H/W Resource
636  */
637 static int memory_get_fault_around_bytes(char *res_name)
638 {
639         int ret, fault_around_bytes;
640
641         if (!res_name)
642                 return -EINVAL;
643
644         ret = sysfs_read_int(FAULT_AROUND_BYTES_PATH, &fault_around_bytes);
645         if (ret < 0)
646                 return ret;
647
648         return fault_around_bytes;
649 }
650
651 static int memory_set_fault_around_bytes(char *res_name,
652                                                 int fault_around_bytes)
653 {
654         int ret;
655
656         if ((!res_name) || (fault_around_bytes <= 0))
657                 return -EINVAL;
658
659         ret = sysfs_write_int(FAULT_AROUND_BYTES_PATH, fault_around_bytes);
660         if (ret < 0)
661                 return ret;
662
663         return 0;
664 }
665
666 /************************
667  * HAL backend power data
668  */
669 static int power_init(void **data)
670 {
671         hal_backend_power_funcs *power_funcs = NULL;
672         struct pass_resource_cpu *cpu = NULL;
673         struct pass_resource_bus *bus = NULL;
674         struct pass_resource_gpu *gpu = NULL;
675         struct pass_resource_memory *memory = NULL;
676         int ret;
677
678         /* Allocate memory */
679         power_funcs = calloc(1, sizeof(hal_backend_power_funcs));
680         if (!power_funcs)
681                 return -ENOMEM;
682
683         cpu = calloc(1, sizeof(struct pass_resource_cpu));
684         if (!cpu) {
685                 ret = -ENOMEM;
686                 goto err_funcs;
687         }
688
689         bus = calloc(1, sizeof(struct pass_resource_bus));
690         if (!bus) {
691                 ret = -ENOMEM;
692                 goto err_cpu;
693         }
694
695         gpu = calloc(1, sizeof(struct pass_resource_gpu));
696         if (!gpu) {
697                 ret = -ENOMEM;
698                 goto err_bus;
699         }
700
701         memory = calloc(1, sizeof(struct pass_resource_memory));
702         if (!memory) {
703                 ret = -ENOMEM;
704                 goto err_gpu;
705         }
706
707         /* Initialize each h/w resource */
708         cpu->dvfs = cpufreq_dvfs_ops;
709         cpu->hotplug = cpu_hotplus_ops;
710         cpu->tmu = tmu_ops;
711
712         bus->dvfs = devfreq_dvfs_ops;
713         bus->tmu = tmu_ops;
714
715         gpu->dvfs = devfreq_dvfs_ops;
716         gpu->tmu = tmu_ops;
717
718         memory->get_fault_around_bytes = memory_get_fault_around_bytes;
719         memory->set_fault_around_bytes = memory_set_fault_around_bytes;
720
721         /* Initialize hal_backend_power_funcs  */
722         power_funcs->cpu = cpu;
723         power_funcs->bus = bus;
724         power_funcs->gpu = gpu;
725         power_funcs->memory = memory;
726
727         *data = (void *)power_funcs;
728
729         return 0;
730
731 err_gpu:
732         if (gpu)
733                 free(gpu);
734 err_bus:
735         if (bus)
736                 free(bus);
737 err_cpu:
738         if (cpu)
739                 free(cpu);
740 err_funcs:
741         free(power_funcs);
742
743         return ret;
744 }
745
746 static int power_exit(void *data)
747 {
748         hal_backend_power_funcs *funcs;
749
750         if (!data)
751                 return -EINVAL;
752
753         funcs = (hal_backend_power_funcs *)data;
754
755         if (funcs->cpu)
756                 free(funcs->cpu);
757         if (funcs->bus)
758                 free(funcs->bus);
759         if (funcs->gpu)
760                 free(funcs->gpu);
761         if (funcs->memory)
762                 free(funcs->memory);
763
764         free(funcs);
765
766         return 0;
767 }
768
769 hal_backend hal_backend_power_data = {
770         .name = "power-cpu",
771         .vendor = "",
772         .abi_version = HAL_ABI_VERSION_TIZEN_6_5,
773         .init = power_init,
774         .exit = power_exit,
775 };