diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 75e23b3945..e602b713c3 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -244,6 +244,23 @@ static const char* get_cpuinfo(int selected_item, void *data, { int cpu = (selected_item - 5) / (state_count + 1); int cpu_line = (selected_item - 5) % (state_count + 1); +#if defined(DX50) || defined(DX90) + int min_freq = min_scaling_frequency(cpu); + int cur_freq = current_scaling_frequency(cpu); + int max_freq = max_scaling_frequency(cpu); + char governor[20]; + bool have_governor = current_scaling_governor(cpu, governor, sizeof(governor)); + if(cpu_line == 0) + { + sprintf(buffer, + " CPU%d: %s: %d/%d/%d MHz", + cpu, + have_governor ? governor : "Min/Cur/Max freq", + min_freq > 0 ? min_freq/1000 : -1, + cur_freq > 0 ? cur_freq/1000 : -1, + max_freq > 0 ? max_freq/1000 : -1); + } +#else int freq1 = frequency_linux(cpu, false); int freq2 = frequency_linux(cpu, true); if (cpu_line == 0) @@ -252,6 +269,7 @@ static const char* get_cpuinfo(int selected_item, void *data, freq1 > 0 ? freq1/1000 : -1, freq2 > 0 ? freq2/1000 : -1); } +#endif else { cpustatetimes_linux(cpu, states, ARRAYLEN(states)); diff --git a/firmware/target/hosted/cpuinfo-linux.c b/firmware/target/hosted/cpuinfo-linux.c index e0a6bd76da..8158673349 100644 --- a/firmware/target/hosted/cpuinfo-linux.c +++ b/firmware/target/hosted/cpuinfo-linux.c @@ -35,8 +35,14 @@ #include "cpuinfo-linux.h" #include "gcc_extensions.h" +#if defined(DX50) || defined(DX90) +#include +#include +#include "debug.h" +#endif + #undef open /* want the *real* open here, not sim_open or the like */ -#if (CONFIG_PLATFORM & PLATFORM_ANDROID) +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) || defined(DX50) || defined(DX90) #include "cpu-features.h" #define get_nprocs android_getCpuCount #endif @@ -154,6 +160,132 @@ int frequency_linux(int cpu, bool scaling) return ret; } +#if defined(DX50) || defined(DX90) +bool current_scaling_governor(int cpu, char* governor, int governor_size) +{ + if((cpu < 0) || (governor == NULL) || (governor_size <= 0)) + { + return false; + } + + char path[PATH_MAX]; + snprintf(path, + sizeof(path), + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", + cpu); + FILE *f = fopen(path, "r"); + if(f == NULL) + { + DEBUGF("ERROR %s: Can not open %s for reading.", __func__, path); + return false; + } + + if(fgets(governor, governor_size, f) == NULL) + { + DEBUGF("ERROR %s: Read failed for %s.", __func__, path); + fclose(f); + return false; + } + + if(strlen(governor) > 0) + { + governor[strlen(governor) - 1] = '\0'; + } + + fclose(f); + return true; +} + + +enum cpu_frequency_options +{ + SCALING_MIN_FREQ = 0, + SCALING_CUR_FREQ, + SCALING_MAX_FREQ +}; + + +static int read_cpu_frequency(int cpu, enum cpu_frequency_options freqOpt) +{ + if(cpu < 0) + { + return -1; + } + + char path[PATH_MAX]; + switch(freqOpt) + { + case SCALING_MIN_FREQ: + { + snprintf(path, + PATH_MAX, + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", + cpu); + break; + } + + case SCALING_CUR_FREQ: + { + snprintf(path, + PATH_MAX, + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", + cpu); + break; + } + + case SCALING_MAX_FREQ: + { + snprintf(path, + PATH_MAX, + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", + cpu); + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown CpuFrequencyOptions: %d.", __func__, freqOpt); + return -1; + } + } + + FILE *f = fopen(path, "r"); + if(f == NULL) + { + DEBUGF("ERROR %s: Can not open %s for reading.", __func__, path); + return -1; + } + + int freq; + if(fscanf(f, "%d", &freq) == EOF) + { + DEBUGF("ERROR %s: Read failed for %s.", __func__, path); + freq = -1; + } + + fclose(f); + return(freq); +} + + +int min_scaling_frequency(int cpu) +{ + return(read_cpu_frequency(cpu, SCALING_MIN_FREQ)); +} + + +int current_scaling_frequency(int cpu) +{ + return(read_cpu_frequency(cpu, SCALING_CUR_FREQ)); +} + + +int max_scaling_frequency(int cpu) +{ + return(read_cpu_frequency(cpu, SCALING_MAX_FREQ)); +} +#endif + int cpustatetimes_linux(int cpu, struct time_state* data, int max_elements) { int elements_left = max_elements, cpu_dev; diff --git a/firmware/target/hosted/cpuinfo-linux.h b/firmware/target/hosted/cpuinfo-linux.h index ebc05d5c43..0483a3a9aa 100644 --- a/firmware/target/hosted/cpuinfo-linux.h +++ b/firmware/target/hosted/cpuinfo-linux.h @@ -40,6 +40,28 @@ struct time_state { int cpuusage_linux(struct cpuusage* u); int frequency_linux(int cpu, bool scaling); + +#if defined(DX50) || defined(DX90) +/* + Get the current cpufreq scaling governor. + cpu [in]: The number of the cpu to query. + governor [out]: Buffer for the governor. + governor_size [in]: Size of the buffer for the governor. + Returns true on success, false else. +*/ +bool current_scaling_governor(int cpu, char* governor, int governor_size); + + +/* + Get the minimum, current or maximum cpufreq scaling frequency. + cpu [in]: The number of the cpu to query. + Returns -1 failure. +*/ +int min_scaling_frequency(int cpu); +int current_scaling_frequency(int cpu); +int max_scaling_frequency(int cpu); +#endif + int cpustatetimes_linux(int cpu, struct time_state* data, int max_elements); int cpucount_linux(void);