209 lines
5.4 KiB
C
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;
|
|
}
|