Files

209 lines
5.4 KiB
C

#include <linux/cpufreq.h>
#include <linux/fs.h>
#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;
}