dvfs: add virtual temperature control
Signed-off-by: 陈亮 <cl@rock-chips.com>
This commit is contained in:
parent
e0384471e3
commit
c1a63c40f0
5 changed files with 90 additions and 19 deletions
|
|
@ -829,9 +829,6 @@
|
|||
};
|
||||
|
||||
dvfs {
|
||||
temp-limit-enable = <0>;
|
||||
target-temp = <80>;
|
||||
|
||||
vd_arm: vd_arm {
|
||||
regulator_name = "vdd_arm";
|
||||
pd_core {
|
||||
|
|
@ -843,6 +840,8 @@
|
|||
816000 1100000
|
||||
1008000 1100000
|
||||
>;
|
||||
temp-limit-enable = <0>;
|
||||
target-temp = <80>;
|
||||
temp-channel = <1>;
|
||||
normal-temp-limit = <
|
||||
/*delta-temp delta-freq*/
|
||||
|
|
|
|||
|
|
@ -898,8 +898,6 @@
|
|||
};
|
||||
|
||||
dvfs {
|
||||
temp-limit-enable = <1>;
|
||||
target-temp = <80>;
|
||||
|
||||
vd_arm: vd_arm {
|
||||
regulator_name = "vdd_arm";
|
||||
|
|
@ -913,6 +911,8 @@
|
|||
816000 1100000
|
||||
1008000 1100000
|
||||
>;
|
||||
temp-limit-enable = <1>;
|
||||
target-temp = <80>;
|
||||
temp-channel = <1>;
|
||||
normal-temp-limit = <
|
||||
/*delta-temp delta-freq*/
|
||||
|
|
|
|||
|
|
@ -291,7 +291,6 @@ static noinline long ddrfreq_work(unsigned long sys_status)
|
|||
|
||||
if (ddr.reboot_rate && (s & SYS_STATUS_REBOOT)) {
|
||||
ddrfreq_mode(false, ddr.reboot_rate, "shutdown/reboot");
|
||||
rockchip_cpufreq_reboot_limit_freq();
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
|
@ -769,6 +768,7 @@ CLK_NOTIFIER(pd_vop1, LCDC1)
|
|||
static int ddrfreq_reboot_notifier_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
rockchip_set_system_status(SYS_STATUS_REBOOT);
|
||||
rockchip_cpufreq_reboot_limit_freq();
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#include <linux/rockchip/common.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/rockchip/cpu.h>
|
||||
#include <linux/tick.h>
|
||||
#include <dt-bindings/clock/rk_system_status.h>
|
||||
#include "../../../drivers/clk/rockchip/clk-pd.h"
|
||||
|
||||
extern int rockchip_tsadc_get_temp(int chn);
|
||||
|
|
@ -33,7 +36,7 @@ static DEFINE_MUTEX(rk_dvfs_mutex);
|
|||
static struct workqueue_struct *dvfs_wq;
|
||||
static struct dvfs_node *clk_cpu_dvfs_node;
|
||||
static unsigned int target_temp = 80;
|
||||
static int temp_limit_enable = 1;
|
||||
static int temp_limit_enable;
|
||||
|
||||
static int pd_gpu_off, early_suspend;
|
||||
static DEFINE_MUTEX(switch_vdd_gpu_mutex);
|
||||
|
|
@ -855,6 +858,67 @@ static void dvfs_temp_limit_work_func(struct work_struct *work)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void dvfs_virt_temp_limit_work_func(void)
|
||||
{
|
||||
const struct cpufreq_frequency_table *limits_table = NULL;
|
||||
unsigned int new_temp_limit_rate = -1;
|
||||
unsigned int nr_cpus = num_online_cpus();
|
||||
static bool in_perf;
|
||||
int i;
|
||||
|
||||
if (!soc_is_rk3126() && !soc_is_rk3128())
|
||||
return;
|
||||
|
||||
if (rockchip_get_system_status() & SYS_STATUS_PERFORMANCE) {
|
||||
in_perf = true;
|
||||
} else if (in_perf) {
|
||||
in_perf = false;
|
||||
} else {
|
||||
static u64 last_time_in_idle;
|
||||
static u64 last_time_in_idle_timestamp;
|
||||
u64 time_in_idle = 0, now;
|
||||
u32 delta_idle;
|
||||
u32 delta_time;
|
||||
unsigned cpu, busy_cpus;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
time_in_idle += get_cpu_idle_time_us(cpu, &now);
|
||||
}
|
||||
delta_time = now - last_time_in_idle_timestamp;
|
||||
delta_idle = time_in_idle - last_time_in_idle;
|
||||
last_time_in_idle = time_in_idle;
|
||||
last_time_in_idle_timestamp = now;
|
||||
delta_idle += delta_time >> 4; /* +6.25% */
|
||||
if (delta_idle > (nr_cpus - 1)
|
||||
* delta_time && delta_idle < (nr_cpus + 1) * delta_time)
|
||||
busy_cpus = 1;
|
||||
else if (delta_idle > (nr_cpus - 2) * delta_time)
|
||||
busy_cpus = 2;
|
||||
else if (delta_idle > (nr_cpus - 3) * delta_time)
|
||||
busy_cpus = 3;
|
||||
else
|
||||
busy_cpus = 4;
|
||||
|
||||
limits_table = clk_cpu_dvfs_node->virt_temp_limit_table[busy_cpus-1];
|
||||
DVFS_DBG("delta time %6u us idle %6u us %u cpus select table %d\n",
|
||||
delta_time, delta_idle, nr_cpus, busy_cpus);
|
||||
}
|
||||
|
||||
if (limits_table) {
|
||||
new_temp_limit_rate = limits_table[0].frequency;
|
||||
for (i = 0; limits_table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
if (target_temp >= limits_table[i].index)
|
||||
new_temp_limit_rate = limits_table[i].frequency;
|
||||
}
|
||||
}
|
||||
|
||||
if (clk_cpu_dvfs_node->temp_limit_rate != new_temp_limit_rate) {
|
||||
clk_cpu_dvfs_node->temp_limit_rate = new_temp_limit_rate;
|
||||
dvfs_clk_set_rate(clk_cpu_dvfs_node, clk_cpu_dvfs_node->last_set_rate);
|
||||
DVFS_DBG("temp_limit_rate:%d\n", (int)clk_cpu_dvfs_node->temp_limit_rate);
|
||||
}
|
||||
}
|
||||
|
||||
static void dvfs_temp_limit_work_func(struct work_struct *work)
|
||||
{
|
||||
int temp=0, delta_temp=0;
|
||||
|
|
@ -867,6 +931,9 @@ static void dvfs_temp_limit_work_func(struct work_struct *work)
|
|||
|
||||
temp = rockchip_tsadc_get_temp(1);
|
||||
|
||||
if (temp == INVALID_TEMP)
|
||||
return dvfs_virt_temp_limit_work_func();
|
||||
|
||||
//debounce
|
||||
delta_temp = (old_temp>temp) ? (old_temp-temp) : (temp-old_temp);
|
||||
if (delta_temp <= 1)
|
||||
|
|
@ -1592,16 +1659,6 @@ int of_dvfs_init(void)
|
|||
return PTR_ERR(dvfs_dev_node);
|
||||
}
|
||||
|
||||
val = of_get_property(dvfs_dev_node, "target-temp", NULL);
|
||||
if (val) {
|
||||
target_temp = be32_to_cpup(val);
|
||||
}
|
||||
|
||||
val = of_get_property(dvfs_dev_node, "temp-limit-enable", NULL);
|
||||
if (val) {
|
||||
temp_limit_enable = be32_to_cpup(val);
|
||||
}
|
||||
|
||||
for_each_available_child_of_node(dvfs_dev_node, vd_dev_node) {
|
||||
vd = kzalloc(sizeof(struct vd_node), GFP_KERNEL);
|
||||
if (!vd)
|
||||
|
|
@ -1667,13 +1724,27 @@ int of_dvfs_init(void)
|
|||
else
|
||||
dvfs_node->regu_mode_table = NULL;
|
||||
|
||||
val = of_get_property(clk_dev_node, "temp-limit-enable", NULL);
|
||||
if (val)
|
||||
temp_limit_enable = be32_to_cpup(val);
|
||||
if (temp_limit_enable) {
|
||||
val = of_get_property(clk_dev_node, "target-temp", NULL);
|
||||
if (val)
|
||||
target_temp = be32_to_cpup(val);
|
||||
val = of_get_property(clk_dev_node, "temp-channel", NULL);
|
||||
if (val) {
|
||||
if (val)
|
||||
dvfs_node->temp_channel = be32_to_cpup(val);
|
||||
}
|
||||
|
||||
dvfs_node->nor_temp_limit_table = of_get_temp_limit_table(clk_dev_node, "normal-temp-limit");
|
||||
dvfs_node->per_temp_limit_table = of_get_temp_limit_table(clk_dev_node, "performance-temp-limit");
|
||||
dvfs_node->virt_temp_limit_table[0] =
|
||||
of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-1-cpu-busy");
|
||||
dvfs_node->virt_temp_limit_table[1] =
|
||||
of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-2-cpu-busy");
|
||||
dvfs_node->virt_temp_limit_table[2] =
|
||||
of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-3-cpu-busy");
|
||||
dvfs_node->virt_temp_limit_table[3] =
|
||||
of_get_temp_limit_table(clk_dev_node, "virt-temp-limit-4-cpu-busy");
|
||||
}
|
||||
dvfs_node->temp_limit_rate = -1;
|
||||
dvfs_node->dev.of_node = clk_dev_node;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ struct dvfs_node {
|
|||
struct cpufreq_frequency_table *dvfs_table;
|
||||
struct cpufreq_frequency_table *per_temp_limit_table;
|
||||
struct cpufreq_frequency_table *nor_temp_limit_table;
|
||||
struct cpufreq_frequency_table *virt_temp_limit_table[4];
|
||||
clk_set_rate_callback clk_dvfs_target;
|
||||
struct cpufreq_frequency_table *regu_mode_table;
|
||||
int regu_mode_en;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue