#include #include #include "pmoc_comm.h" #include "drv_svb.h" #define SUPPORT_CORE_COMP typedef enum { TEMP_STATUS_NORMAL, TEMP_STATUS_LOW, TEMP_STATUS_HIGH, TEMP_STATUS_MAX, } lotus_temp_status; #define TEMPERATURE_VALUE_SVB_LOW 30 #define TEMPERATURE_VALUE_QUIT_SVB_LOW 38 #define TEMPERATURE_VALUE_QUIT_HIGH_POWER 88 #define TEMPERATURE_VALUE_POWER_HIGH 90 #define TEMPERATURE_VALUE_POWER_DOWN 120 #define LOW_TEMP_VOLT_COMP 20 #define TEMPERATURE_VALUE_MAX 200 #define TEMPERATURE_VALUE_MIN (-100) #define CPU_SCALING_MAX_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" #define CPU_SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq" #define DEFAULT_INIT_FREQ 1200000 static lotus_temp_status g_t_status = TEMP_STATUS_MAX; xmedia_s32 write_cpufreq_node(const xmedia_char *node, xmedia_s32 value) { struct file *filep = XMEDIA_NULL; xmedia_char name[CPUFREQ_NAME_LEN] = { 0 }; xmedia_u32 write_len; snprintf(name, CPUFREQ_NAME_LEN, "%u\n", value); PM_TRACE(MODULE_DBG_DEBUG, "write_cpufreq_node value=%d\n", value); filep = osal_klib_fopen(node, O_CREAT | O_RDWR, 0); if (IS_ERR(filep)) { PM_TRACE(MODULE_DBG_ERR, "Failed to filp_open %s\n", node); return -1; } write_len = osal_klib_fwrite(name, sizeof(name), filep); if (write_len < 0) { PM_TRACE(MODULE_DBG_ERR, "Failed to write to %s\n", node); return -1; } osal_klib_fclose(filep); return 0; } xmedia_s32 read_cpufreq_node(const xmedia_char *node) { struct file *filep = XMEDIA_NULL; xmedia_char name[CPUFREQ_NAME_LEN] = { 0 }; xmedia_u32 read_len; xmedia_s32 value = 0; xmedia_s32 ret; filep = osal_klib_fopen(node, O_CREAT | O_RDWR, 0); if (IS_ERR(filep)) { PM_TRACE(MODULE_DBG_ERR, "Failed to filp_open %s\n", node); return -1; } read_len = osal_klib_fread(name, sizeof(name), filep); if (read_len < 0) { PM_TRACE(MODULE_DBG_ERR, "Failed to read from %s, read_len 0x%x\n", node, read_len); return -1; } ret = kstrtou32(name, 0, &value); if (ret < 0) { return -1; } PM_TRACE(MODULE_DBG_DEBUG, "read_cpufreq_node value=%d\n", value); osal_klib_fclose(filep); return value; } static xmedia_void temp_enter_normal(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); #ifdef SUPPORT_CORE_COMP set_core_comp(0); svb_control_apply(); #endif } static xmedia_void temp_quit_low(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); #ifdef SUPPORT_CORE_COMP set_core_comp(0); svb_control_apply(); #endif } static xmedia_void temp_enter_low(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); #ifdef SUPPORT_CORE_COMP set_core_comp(LOW_TEMP_VOLT_COMP); svb_control_apply(); #endif } static xmedia_void temp_quit_high(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); } static xmedia_void temp_enter_high(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); } static xmedia_void temp_power_down(xmedia_void) { PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d\n", get_chip_temperature()); } xmedia_void temp_init(xmedia_void) { xmedia_s32 temp = get_chip_temperature(); if (temp <= TEMPERATURE_VALUE_SVB_LOW) { temp_enter_low(); g_t_status = TEMP_STATUS_LOW; } else if (temp > TEMPERATURE_VALUE_SVB_LOW && temp <= TEMPERATURE_VALUE_POWER_HIGH) { temp_enter_normal(); g_t_status = TEMP_STATUS_NORMAL; } else if (temp > TEMPERATURE_VALUE_POWER_HIGH && temp < TEMPERATURE_VALUE_POWER_DOWN) { temp_enter_normal(); // TODO: remove when temp_enter_high() supported temp_enter_high(); g_t_status = TEMP_STATUS_HIGH; } else if (temp >= TEMPERATURE_VALUE_POWER_DOWN) { temp_enter_normal(); // TODO: remove when temp_power_down() supported temp_power_down(); g_t_status = TEMP_STATUS_HIGH; } else { temp_enter_low(); g_t_status = TEMP_STATUS_LOW; } PM_TRACE(MODULE_DBG_DEBUG, "Temperature: %d, g_t_status: %d\n", temp, g_t_status); } xmedia_s32 temp_control_thread(xmedia_void) { xmedia_s32 temp; temp = get_chip_temperature(); if ((temp <= TEMPERATURE_VALUE_MIN) || (temp >= TEMPERATURE_VALUE_MAX)) { PM_TRACE(MODULE_DBG_ERR, "Invalid Temperature: %d\n", temp); return XMEDIA_FAILURE; } switch (g_t_status) { case TEMP_STATUS_LOW: if (temp > TEMPERATURE_VALUE_POWER_HIGH) { PM_TRACE(MODULE_DBG_ERR, "Abnormal rise in temperature: %d, g_t_status: %d\n", temp, g_t_status); } else if (temp > TEMPERATURE_VALUE_QUIT_SVB_LOW) { temp_quit_low(); g_t_status = TEMP_STATUS_NORMAL; break; } break; case TEMP_STATUS_NORMAL: if (temp < TEMPERATURE_VALUE_SVB_LOW) { temp_enter_low(); g_t_status = TEMP_STATUS_LOW; } else if (temp > TEMPERATURE_VALUE_POWER_DOWN) { temp_power_down(); g_t_status = TEMP_STATUS_NORMAL; } else if (temp > TEMPERATURE_VALUE_POWER_HIGH) { temp_enter_high(); g_t_status = TEMP_STATUS_HIGH; } break; case TEMP_STATUS_HIGH: if (temp < TEMPERATURE_VALUE_SVB_LOW) { PM_TRACE(MODULE_DBG_ERR, "Abnormal fall in temperature: %d, g_t_status: %d\n", temp, g_t_status); } else if (temp < TEMPERATURE_VALUE_QUIT_HIGH_POWER) { temp_quit_high(); g_t_status = TEMP_STATUS_NORMAL; } else if (temp > TEMPERATURE_VALUE_POWER_DOWN) { temp_power_down(); g_t_status = TEMP_STATUS_NORMAL; } break; default: PM_TRACE(MODULE_DBG_ERR, "Invalid temperature status: %d, T=%d\n", g_t_status, temp); break; } return XMEDIA_SUCCESS; }