1*4a06806eSHuang Rui // SPDX-License-Identifier: GPL-2.0-only
2*4a06806eSHuang Rui 
3*4a06806eSHuang Rui #include <stdio.h>
4*4a06806eSHuang Rui #include <errno.h>
5*4a06806eSHuang Rui #include <stdlib.h>
6*4a06806eSHuang Rui #include <string.h>
7*4a06806eSHuang Rui #include <sys/types.h>
8*4a06806eSHuang Rui #include <sys/stat.h>
9*4a06806eSHuang Rui #include <fcntl.h>
10*4a06806eSHuang Rui #include <unistd.h>
11*4a06806eSHuang Rui 
12*4a06806eSHuang Rui #include "cpupower_intern.h"
13*4a06806eSHuang Rui #include "acpi_cppc.h"
14*4a06806eSHuang Rui 
15*4a06806eSHuang Rui /* ACPI CPPC sysfs access ***********************************************/
16*4a06806eSHuang Rui 
acpi_cppc_read_file(unsigned int cpu,const char * fname,char * buf,size_t buflen)17*4a06806eSHuang Rui static int acpi_cppc_read_file(unsigned int cpu, const char *fname,
18*4a06806eSHuang Rui 			       char *buf, size_t buflen)
19*4a06806eSHuang Rui {
20*4a06806eSHuang Rui 	char path[SYSFS_PATH_MAX];
21*4a06806eSHuang Rui 
22*4a06806eSHuang Rui 	snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/acpi_cppc/%s",
23*4a06806eSHuang Rui 		 cpu, fname);
24*4a06806eSHuang Rui 	return cpupower_read_sysfs(path, buf, buflen);
25*4a06806eSHuang Rui }
26*4a06806eSHuang Rui 
27*4a06806eSHuang Rui static const char * const acpi_cppc_value_files[] = {
28*4a06806eSHuang Rui 	[HIGHEST_PERF] = "highest_perf",
29*4a06806eSHuang Rui 	[LOWEST_PERF] = "lowest_perf",
30*4a06806eSHuang Rui 	[NOMINAL_PERF] = "nominal_perf",
31*4a06806eSHuang Rui 	[LOWEST_NONLINEAR_PERF] = "lowest_nonlinear_perf",
32*4a06806eSHuang Rui 	[LOWEST_FREQ] = "lowest_freq",
33*4a06806eSHuang Rui 	[NOMINAL_FREQ] = "nominal_freq",
34*4a06806eSHuang Rui 	[REFERENCE_PERF] = "reference_perf",
35*4a06806eSHuang Rui 	[WRAPAROUND_TIME] = "wraparound_time"
36*4a06806eSHuang Rui };
37*4a06806eSHuang Rui 
acpi_cppc_get_data(unsigned int cpu,enum acpi_cppc_value which)38*4a06806eSHuang Rui unsigned long acpi_cppc_get_data(unsigned int cpu, enum acpi_cppc_value which)
39*4a06806eSHuang Rui {
40*4a06806eSHuang Rui 	unsigned long long value;
41*4a06806eSHuang Rui 	unsigned int len;
42*4a06806eSHuang Rui 	char linebuf[MAX_LINE_LEN];
43*4a06806eSHuang Rui 	char *endp;
44*4a06806eSHuang Rui 
45*4a06806eSHuang Rui 	if (which >= MAX_CPPC_VALUE_FILES)
46*4a06806eSHuang Rui 		return 0;
47*4a06806eSHuang Rui 
48*4a06806eSHuang Rui 	len = acpi_cppc_read_file(cpu, acpi_cppc_value_files[which],
49*4a06806eSHuang Rui 				  linebuf, sizeof(linebuf));
50*4a06806eSHuang Rui 	if (len == 0)
51*4a06806eSHuang Rui 		return 0;
52*4a06806eSHuang Rui 
53*4a06806eSHuang Rui 	value = strtoull(linebuf, &endp, 0);
54*4a06806eSHuang Rui 
55*4a06806eSHuang Rui 	if (endp == linebuf || errno == ERANGE)
56*4a06806eSHuang Rui 		return 0;
57*4a06806eSHuang Rui 
58*4a06806eSHuang Rui 	return value;
59*4a06806eSHuang Rui }
60