3972 lines
102 KiB
C
3972 lines
102 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/version.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/thermal.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/types.h>
|
|
#include <linux/proc_fs.h>
|
|
#include "mt-plat/mtk_thermal_monitor.h"
|
|
#include "mach/mtk_thermal.h"
|
|
#include "mt-plat/mtk_thermal_platform.h"
|
|
#if defined(CONFIG_MTK_CLKMGR)
|
|
#include <mach/mtk_clkmgr.h>
|
|
#else
|
|
#include <linux/clk.h>
|
|
#endif
|
|
#include <linux/slab.h>
|
|
#include <linux/seq_file.h>
|
|
#include <tscpu_settings.h>
|
|
#include <mt-plat/aee.h>
|
|
#include <linux/uidgid.h>
|
|
#include <ap_thermal_limit.h>
|
|
#ifndef CLATM_USE_MIN_CPU_OPP
|
|
#define CLATM_USE_MIN_CPU_OPP (0)
|
|
#endif
|
|
#ifdef ATM_USES_PPM
|
|
//#if defined(CONFIG_MTK_PPM) || defined(CONFIG_MACH_MT6781)
|
|
#include "mtk_ppm_api.h"
|
|
#include "mtk_ppm_platform.h"
|
|
#else
|
|
#include "mt_cpufreq.h"
|
|
#endif
|
|
|
|
#ifdef FAST_RESPONSE_ATM
|
|
#include <linux/time.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/kthread.h>
|
|
#endif
|
|
#include "clatm_initcfg.h"
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#include "mtk_thermal_ipi.h"
|
|
#include "linux/delay.h"
|
|
#endif
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
#if defined(CONFIG_MTK_APUSYS_SUPPORT)
|
|
#include "apu_power_table.h"
|
|
#else
|
|
#include "vpu_dvfs.h"
|
|
#endif
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
#if defined(CONFIG_MTK_APUSYS_SUPPORT)
|
|
#include "apu_power_table.h"
|
|
#else
|
|
#include "mdla_dvfs.h"
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
#include <mt-plat/mtk_devinfo.h>
|
|
#endif
|
|
|
|
#define CREATE_TRACE_POINTS
|
|
#include "mtk_cooler_atm_events.h"
|
|
|
|
/*****************************************************************************
|
|
* Local switches
|
|
*****************************************************************************/
|
|
/* Define ATM_CFG_PROFILING to compile the code segments for profiling. It
|
|
* depends on ostimer which is wrapped by CFG_TIMER_SUPPORT.
|
|
* Only tested with FAST_RESPONSE_ATM is turned on.
|
|
* ! Must not define this in official release branches. Only for local tests.
|
|
*/
|
|
/* #define ATM_CFG_PROFILING (1) */
|
|
|
|
/*=============================================================
|
|
*Local variable definition
|
|
*=============================================================
|
|
*/
|
|
static int print_cunt;
|
|
static int adaptive_limit[5][2];
|
|
static struct apthermolmt_user ap_atm;
|
|
static char *ap_atm_log = "ap_atm";
|
|
|
|
static kuid_t uid = KUIDT_INIT(0);
|
|
static kgid_t gid = KGIDT_INIT(1000);
|
|
unsigned int adaptive_cpu_power_limit = 0x7FFFFFFF;
|
|
unsigned int adaptive_gpu_power_limit = 0x7FFFFFFF;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
unsigned int adaptive_vpu_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
unsigned int adaptive_mdla_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
static unsigned int prv_adp_cpu_pwr_lim;
|
|
static unsigned int prv_adp_gpu_pwr_lim;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
static unsigned int prv_adp_vpu_pwr_lim;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
static unsigned int prv_adp_mdla_pwr_lim;
|
|
#endif
|
|
unsigned int gv_cpu_power_limit = 0x7FFFFFFF;
|
|
unsigned int gv_gpu_power_limit = 0x7FFFFFFF;
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static int TARGET_TJ = CLATM_INIT_CFG_0_TARGET_TJ;
|
|
static int cpu_target_tj = 65000;/*not use*/
|
|
static int cpu_target_offset = 10000;/*not use*/
|
|
/*not used when tscpu_atm = 3*/
|
|
static int TARGET_TJ_HIGH = 66000;
|
|
/*not used when tscpu_atm = 3*/
|
|
static int TARGET_TJ_LOW = 64000;
|
|
static int PACKAGE_THETA_JA_RISE = 10;
|
|
static int PACKAGE_THETA_JA_FALL = 10;
|
|
static int MINIMUM_CPU_POWER = CLATM_INIT_CFG_0_MIN_CPU_PWR;
|
|
static int MAXIMUM_CPU_POWER = CLATM_INIT_CFG_0_MAX_CPU_PWR;
|
|
static int MINIMUM_GPU_POWER = CLATM_INIT_CFG_0_MIN_GPU_PWR;
|
|
static int MAXIMUM_GPU_POWER = CLATM_INIT_CFG_0_MAX_GPU_PWR;
|
|
static int MINIMUM_TOTAL_POWER = CLATM_INIT_CFG_0_MIN_CPU_PWR +
|
|
CLATM_INIT_CFG_0_MIN_GPU_PWR;
|
|
static int MAXIMUM_TOTAL_POWER = CLATM_INIT_CFG_0_MAX_CPU_PWR +
|
|
CLATM_INIT_CFG_0_MAX_GPU_PWR;
|
|
static int FIRST_STEP_TOTAL_POWER_BUDGET = CLATM_INIT_CFG_0_FIRST_STEP;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
static int MINIMUM_VPU_POWER = 300;
|
|
static int MAXIMUM_VPU_POWER = 1000;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
static int MINIMUM_MDLA_POWER = 300;
|
|
static int MAXIMUM_MDLA_POWER = 1000;
|
|
#endif
|
|
|
|
/* 1. MINIMUM_BUDGET_CHANGE = 0 ==> thermal equilibrium
|
|
* maybe at higher than TARGET_TJ_HIGH
|
|
*/
|
|
/* 2. Set MINIMUM_BUDGET_CHANGE > 0 if to keep Tj at TARGET_TJ */
|
|
static int MINIMUM_BUDGET_CHANGE = 50;
|
|
static int g_total_power;
|
|
#if defined(THERMAL_VPU_SUPPORT) || defined(THERMAL_MDLA_SUPPORT)
|
|
static int g_delta_power;
|
|
#endif
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static struct thermal_cooling_device
|
|
*cl_dev_adp_cpu[MAX_CPT_ADAPTIVE_COOLERS] = { NULL };
|
|
static unsigned int cl_dev_adp_cpu_state[MAX_CPT_ADAPTIVE_COOLERS] = { 0 };
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
int TARGET_TJS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_TARGET_TJ,
|
|
CLATM_INIT_CFG_1_TARGET_TJ,
|
|
CLATM_INIT_CFG_2_TARGET_TJ };
|
|
#else
|
|
int TARGET_TJS[MAX_CPT_ADAPTIVE_COOLERS] = { 85000, 0 };
|
|
#endif
|
|
|
|
static unsigned int cl_dev_adp_cpu_state_active;
|
|
#endif /* end of CPT_ADAPTIVE_AP_COOLER */
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
char *adaptive_cooler_name = "cpu_adaptive_";
|
|
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
static int FIRST_STEP_TOTAL_POWER_BUDGETS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_FIRST_STEP,
|
|
CLATM_INIT_CFG_1_FIRST_STEP,
|
|
CLATM_INIT_CFG_2_FIRST_STEP };
|
|
|
|
static int PACKAGE_THETA_JA_RISES[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_THETA_RISE,
|
|
CLATM_INIT_CFG_1_THETA_RISE,
|
|
CLATM_INIT_CFG_2_THETA_RISE };
|
|
|
|
static int PACKAGE_THETA_JA_FALLS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_THETA_FALL,
|
|
CLATM_INIT_CFG_1_THETA_FALL,
|
|
CLATM_INIT_CFG_2_THETA_FALL };
|
|
|
|
static int MINIMUM_BUDGET_CHANGES[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_MIN_BUDGET_CHG,
|
|
CLATM_INIT_CFG_1_MIN_BUDGET_CHG,
|
|
CLATM_INIT_CFG_2_MIN_BUDGET_CHG };
|
|
|
|
static int MINIMUM_CPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_MIN_CPU_PWR,
|
|
CLATM_INIT_CFG_1_MIN_CPU_PWR,
|
|
CLATM_INIT_CFG_2_MIN_CPU_PWR };
|
|
|
|
static int MAXIMUM_CPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_MAX_CPU_PWR,
|
|
CLATM_INIT_CFG_1_MAX_CPU_PWR,
|
|
CLATM_INIT_CFG_2_MAX_CPU_PWR };
|
|
|
|
static int MINIMUM_GPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_MIN_GPU_PWR,
|
|
CLATM_INIT_CFG_1_MIN_GPU_PWR,
|
|
CLATM_INIT_CFG_2_MIN_GPU_PWR };
|
|
|
|
static int MAXIMUM_GPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
CLATM_INIT_CFG_0_MAX_GPU_PWR,
|
|
CLATM_INIT_CFG_1_MAX_GPU_PWR,
|
|
CLATM_INIT_CFG_2_MAX_GPU_PWR };
|
|
#else
|
|
static int FIRST_STEP_TOTAL_POWER_BUDGETS[MAX_CPT_ADAPTIVE_COOLERS] = {
|
|
3300, 0 };
|
|
|
|
static int PACKAGE_THETA_JA_RISES[MAX_CPT_ADAPTIVE_COOLERS] = { 35, 0 };
|
|
static int PACKAGE_THETA_JA_FALLS[MAX_CPT_ADAPTIVE_COOLERS] = { 25, 0 };
|
|
static int MINIMUM_BUDGET_CHANGES[MAX_CPT_ADAPTIVE_COOLERS] = { 50, 0 };
|
|
static int MINIMUM_CPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = { 1200, 0 };
|
|
static int MAXIMUM_CPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = { 4400, 0 };
|
|
static int MINIMUM_GPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = { 350, 0 };
|
|
static int MAXIMUM_GPU_POWERS[MAX_CPT_ADAPTIVE_COOLERS] = { 960, 0 };
|
|
#endif
|
|
static int is_max_gpu_power_specified[MAX_CPT_ADAPTIVE_COOLERS] = { 0, 0 };
|
|
|
|
#if CLATM_USE_MIN_CPU_OPP
|
|
struct atm_cpu_min_opp {
|
|
/* mode is
|
|
* 0: Didn't initialize or Some errors occurred
|
|
* 1: Use a min CPU power budget to guarantee minimum performance
|
|
* 2: Use a set of CPU OPPs to gurantee minimum performance
|
|
*/
|
|
int mode[MAX_CPT_ADAPTIVE_COOLERS];
|
|
/* To keep original min CPU power budgets */
|
|
int min_CPU_power[MAX_CPT_ADAPTIVE_COOLERS];
|
|
/* To keep min CPU power budgets calculated from a set of CPU OPP */
|
|
int min_CPU_power_from_opp[MAX_CPT_ADAPTIVE_COOLERS];
|
|
struct ppm_cluster_status
|
|
cpu_opp_set[MAX_CPT_ADAPTIVE_COOLERS][NR_PPM_CLUSTERS];
|
|
};
|
|
static struct atm_cpu_min_opp g_c_min_opp;
|
|
#endif
|
|
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
static int active_adp_cooler = CLATM_INIT_CFG_ACTIVE_ATM_COOLER;
|
|
#else
|
|
static int active_adp_cooler;
|
|
#endif
|
|
|
|
static int GPU_L_H_TRIP = 80, GPU_L_L_TRIP = 40;
|
|
|
|
/* tscpu_atm
|
|
* 0: ATMv1 (default)
|
|
* 1: ATMv2 (FTL)
|
|
* 2: CPU_GPU_Weight ATM v2
|
|
* 3: Precise Power Budgeting + Hybrid Power Budgeting
|
|
*/
|
|
#ifdef PHPB_DEFAULT_ON
|
|
static int tscpu_atm = 3;
|
|
#else
|
|
static int tscpu_atm = 1;
|
|
#endif
|
|
static int tt_ratio_high_rise = 1;
|
|
static int tt_ratio_high_fall = 1;
|
|
static int tt_ratio_low_rise = 1;
|
|
static int tt_ratio_low_fall = 1;
|
|
static int tp_ratio_high_rise = 1;
|
|
static int tp_ratio_high_fall;
|
|
static int tp_ratio_low_rise;
|
|
static int tp_ratio_low_fall;
|
|
/* static int cpu_loading = 0; */
|
|
|
|
static int (*_adaptive_power_calc)
|
|
(long prev_temp, long curr_temp, unsigned int gpu_loading);
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
/* initial value: assume 1 degreeC for temp.
|
|
* <=> 1 unit for total_power(0~100)
|
|
*/
|
|
struct phpb_param {
|
|
int tt, tp;
|
|
char type[8];
|
|
};
|
|
|
|
enum {
|
|
PHPB_PARAM_CPU = 0,
|
|
PHPB_PARAM_GPU,
|
|
NR_PHPB_PARAMS
|
|
};
|
|
|
|
static struct phpb_param phpb_params[NR_PHPB_PARAMS];
|
|
static const int phpb_theta_min = 1;
|
|
static int phpb_theta_max = 4;
|
|
static int tj_stable_range = 1000;
|
|
|
|
#if 0
|
|
#define MAX_GPU_POWER_SMA_LEN (32)
|
|
static unsigned int gpu_power_sma_len = 1;
|
|
static unsigned int gpu_power_history[MAX_GPU_POWER_SMA_LEN];
|
|
static unsigned int gpu_power_history_idx;
|
|
#endif
|
|
#endif
|
|
|
|
#if THERMAL_HEADROOM
|
|
static int p_Tpcb_correlation;
|
|
static int Tpcb_trip_point;
|
|
static int thp_max_cpu_power;
|
|
static int thp_p_tj_correlation;
|
|
static int thp_threshold_tj;
|
|
#endif
|
|
|
|
#if CONTINUOUS_TM
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
static int ctm_on = CLATM_INIT_CFG_CATM; /* 2: cATM+, 1: cATMv1, 0: off */
|
|
#else
|
|
static int ctm_on = -1; /* 2: cATM+, 1: cATMv1, 0: off */
|
|
#endif
|
|
static int MAX_TARGET_TJ = -1;
|
|
static int STEADY_TARGET_TJ = -1;
|
|
static int TRIP_TPCB = -1;
|
|
static int STEADY_TARGET_TPCB = -1;
|
|
static int MAX_EXIT_TJ = -1;
|
|
static int STEADY_EXIT_TJ = -1;
|
|
static int COEF_AE = -1;
|
|
static int COEF_BE = -1;
|
|
static int COEF_AX = -1;
|
|
static int COEF_BX = -1;
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
static int TPCB_EXTEND = -1;
|
|
static int g_turbo_bin;
|
|
#endif
|
|
|
|
/* static int current_TTJ = -1; */
|
|
static int current_ETJ = -1;
|
|
|
|
/* +++ cATM+ parameters +++ */
|
|
/* slope of base_ttj, automatically calculated */
|
|
static int K_TT = 4000;
|
|
#define MAX_K_SUM_TT (K_TT * 10)
|
|
/* for ATM polling delay 50ms, increase this based on polling delay */
|
|
static int K_SUM_TT_LOW = 10;
|
|
/* for ATM polling delay 50ms, increase this based on polling delay */
|
|
static int K_SUM_TT_HIGH = 10;
|
|
/* clamp sum_tt (err_integral) between MIN_SUM_TT ~ MAX_SUM_TT,
|
|
* automatically calculated
|
|
*/
|
|
static int MIN_SUM_TT = -800000;
|
|
static int MAX_SUM_TT = 800000;
|
|
static int MIN_TTJ = 65000;
|
|
|
|
/* magic number decided by experience */
|
|
static int CATMP_STEADY_TTJ_DELTA = 10000;
|
|
/* --- cATM+ parameters --- */
|
|
#endif
|
|
#endif /* end of CPT_ADAPTIVE_AP_COOLER */
|
|
|
|
#ifdef FAST_RESPONSE_ATM
|
|
#define KRTATM_HR (1)
|
|
#define KRTATM_NORMAL (2)
|
|
#define KRTATM_TIMER KRTATM_NORMAL
|
|
|
|
#define TS_MS_TO_NS(x) (x * 1000 * 1000)
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
static struct hrtimer atm_hrtimer;
|
|
static unsigned long atm_hrtimer_polling_delay =
|
|
TS_MS_TO_NS(CLATM_INIT_HRTIMER_POLLING_DELAY);
|
|
|
|
#elif KRTATM_TIMER == KRTATM_NORMAL
|
|
static struct timer_list atm_timer;
|
|
static unsigned long atm_timer_polling_delay =
|
|
CLATM_INIT_HRTIMER_POLLING_DELAY;
|
|
/**
|
|
* If curr_temp >= polling_trip_temp0, use interval/polling_factor0
|
|
* else If curr_temp >= polling_trip_temp1, use interval
|
|
* else if cur_temp >= polling_trip_temp2 &&
|
|
* curr_temp < polling_trip_temp1,
|
|
* use interval*polling_factor1
|
|
* else, use interval*polling_factor2
|
|
*/
|
|
#ifdef CLATM_CONFIGURABLE_TIMER
|
|
static int polling_trip_temp0 = POLLING_TRIP_TEMP0;
|
|
static int polling_trip_temp1 = POLLING_TRIP_TEMP1;
|
|
static int polling_trip_temp2 = POLLING_TRIP_TEMP2;
|
|
static int polling_factor0 = POLLING_FACTOR0;
|
|
static int polling_factor1 = POLLING_FACTOR1;
|
|
static int polling_factor2 = POLLING_FACTOR2;
|
|
#else
|
|
static int polling_trip_temp0 = 75000;
|
|
static int polling_trip_temp1 = 65000;
|
|
static int polling_trip_temp2 = 40000;
|
|
static int polling_factor0 = 10;
|
|
static int polling_factor1 = 2;
|
|
static int polling_factor2 = 4;
|
|
#endif
|
|
#endif
|
|
static int atm_curr_maxtj;
|
|
static int atm_prev_maxtj;
|
|
static int krtatm_curr_maxtj;
|
|
static int krtatm_prev_maxtj;
|
|
static u64 atm_curr_maxtj_time;
|
|
static u64 atm_prev_maxtj_time;
|
|
static struct task_struct *krtatm_thread_handle;
|
|
#endif
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
int atm_resumed = 1;
|
|
|
|
s64 atm_period_min_delay = 0xFFFFFFF;
|
|
s64 atm_period_max_delay;
|
|
s64 atm_period_avg_delay;
|
|
unsigned int atm_period_cnt = 1;
|
|
|
|
s64 atm_exec_min_delay = 0xFFFFFFF;
|
|
s64 atm_exec_max_delay;
|
|
s64 atm_exec_avg_delay;
|
|
unsigned int atm_exec_cnt = 1;
|
|
|
|
s64 cpu_pwr_lmt_min_delay = 0xFFFFFFF;
|
|
s64 cpu_pwr_lmt_max_delay;
|
|
s64 cpu_pwr_lmt_avg_delay;
|
|
s64 cpu_pwr_lmt_latest_delay;
|
|
unsigned int cpu_pwr_lmt_cnt = 1;
|
|
|
|
s64 gpu_pwr_lmt_min_delay = 0xFFFFFFF;
|
|
s64 gpu_pwr_lmt_max_delay;
|
|
s64 gpu_pwr_lmt_avg_delay;
|
|
s64 gpu_pwr_lmt_latest_delay;
|
|
unsigned int gpu_pwr_lmt_cnt = 1;
|
|
#endif
|
|
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
static unsigned long total_apu_polling_time;
|
|
#endif
|
|
#if defined(EARA_THERMAL_SUPPORT)
|
|
static int is_EARA_handled;
|
|
#endif
|
|
|
|
/*=============================================================
|
|
*Local function prototype
|
|
*=============================================================
|
|
*/
|
|
static void set_adaptive_gpu_power_limit(unsigned int limit);
|
|
/*=============================================================
|
|
*Weak functions
|
|
*=============================================================
|
|
*/
|
|
int __attribute__((weak))
|
|
mtk_eara_thermal_pb_handle(int total_pwr_budget,
|
|
int max_cpu_power, int max_gpu_power,
|
|
int max_vpu_power, int max_mdla_power)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool __attribute__((weak))
|
|
mtk_get_gpu_loading(unsigned int *pLoading)
|
|
{
|
|
#ifdef CONFIG_MTK_GPU_SUPPORT
|
|
pr_notice("E_WF: %s doesn't exist\n", __func__);
|
|
#endif
|
|
return 0;
|
|
}
|
|
unsigned int __attribute__((weak))
|
|
mt_gpufreq_get_min_power(void)
|
|
{
|
|
pr_notice("E_WF: %s doesn't exist\n", __func__);
|
|
return 0;
|
|
}
|
|
unsigned int __attribute__((weak))
|
|
mt_gpufreq_get_max_power(void)
|
|
{
|
|
pr_notice("E_WF: %s doesn't exist\n", __func__);
|
|
return 0;
|
|
}
|
|
void __attribute__ ((weak))
|
|
print_risky_temps(char *prefix, int offset, int printLevel)
|
|
{
|
|
|
|
}
|
|
|
|
unsigned int __attribute__ ((weak))
|
|
mt_gpufreq_get_cur_freq(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned int __attribute__ ((weak))
|
|
mt_ppm_thermal_get_cur_power(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned int __attribute__ ((weak))
|
|
mt_ppm_thermal_get_min_power(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
void __attribute__ ((weak))
|
|
set_uartlog_status(bool value)
|
|
{
|
|
}
|
|
|
|
bool __attribute__ ((weak))
|
|
mt_get_uartlog_status(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#if CLATM_USE_MIN_CPU_OPP
|
|
int __attribute__ ((weak))
|
|
ppm_find_pwr_idx(struct ppm_cluster_status *cluster_status)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*=============================================================*/
|
|
|
|
/*
|
|
* static int step0_mask[11] = {1,1,1,1,1,1,1,1,1,1,1};
|
|
* static int step1_mask[11] = {0,1,1,1,1,1,1,1,1,1,1};
|
|
* static int step2_mask[11] = {0,0,1,1,1,1,1,1,1,1,1};
|
|
* static int step3_mask[11] = {0,0,0,1,1,1,1,1,1,1,1};
|
|
* static int step4_mask[11] = {0,0,0,0,1,1,1,1,1,1,1};
|
|
* static int step5_mask[11] = {0,0,0,0,0,1,1,1,1,1,1};
|
|
* static int step6_mask[11] = {0,0,0,0,0,0,1,1,1,1,1};
|
|
* static int step7_mask[11] = {0,0,0,0,0,0,0,1,1,1,1};
|
|
* static int step8_mask[11] = {0,0,0,0,0,0,0,0,1,1,1};
|
|
* static int step9_mask[11] = {0,0,0,0,0,0,0,0,0,1,1};
|
|
* static int step10_mask[11]= {0,0,0,0,0,0,0,0,0,0,1};
|
|
*/
|
|
|
|
int tsatm_thermal_get_catm_type(void)
|
|
{
|
|
tscpu_dprintk("%s ctm_on = %d\n", __func__, ctm_on);
|
|
return ctm_on;
|
|
}
|
|
|
|
int mtk_thermal_get_tpcb_target(void)
|
|
{
|
|
return STEADY_TARGET_TPCB;
|
|
}
|
|
EXPORT_SYMBOL(mtk_thermal_get_tpcb_target);
|
|
|
|
/**
|
|
* TODO: What's the diff from get_cpu_target_tj?
|
|
*/
|
|
int get_target_tj(void)
|
|
{
|
|
return TARGET_TJ;
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && \
|
|
CPT_ADAPTIVE_AP_COOLER && PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
/* ATM in SSPM requires ATM, PPB, CATM */
|
|
static int atm_sspm_enabled;
|
|
static int atm_prev_active_atm_cl_id = -100;
|
|
|
|
static DEFINE_MUTEX(atm_cpu_lmt_mutex);
|
|
static DEFINE_MUTEX(atm_gpu_lmt_mutex);
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
static DEFINE_MUTEX(atm_vpu_lmt_mutex);
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
static DEFINE_MUTEX(atm_mdla_lmt_mutex);
|
|
#endif
|
|
|
|
static int atm_update_atm_param_to_sspm(void)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
/* ATM, modified in decide_ttj(). */
|
|
thermal_data.u.data.arg[0] = MINIMUM_CPU_POWER;
|
|
thermal_data.u.data.arg[1] = MAXIMUM_CPU_POWER;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP1, 2,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
/* ATM, modified in decide_ttj(). */
|
|
thermal_data.u.data.arg[0] = MINIMUM_GPU_POWER;
|
|
thermal_data.u.data.arg[1] = MAXIMUM_GPU_POWER;
|
|
|
|
/* modified in mtk_ts_cpu*::tscpu_write(). */
|
|
thermal_data.u.data.arg[2] = TARGET_TJS[0];
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP2, 3,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
return ackData;
|
|
}
|
|
|
|
static int atm_update_ppb_param_to_sspm(void)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
/* PPB, modified in tscpu_write_phpb(), and phpb_params_init(). */
|
|
thermal_data.u.data.arg[0] = phpb_params[PHPB_PARAM_CPU].tt;
|
|
thermal_data.u.data.arg[1] = phpb_params[PHPB_PARAM_CPU].tp;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP3, 2,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
/* PPB, modified in tscpu_write_phpb(), and phpb_params_init(). */
|
|
thermal_data.u.data.arg[0] = phpb_params[PHPB_PARAM_GPU].tt;
|
|
thermal_data.u.data.arg[1] = phpb_params[PHPB_PARAM_GPU].tp;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP4, 2,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
/* PPB, modified in tscpu_write_phpb(), or not modified at all. */
|
|
thermal_data.u.data.arg[0] = tj_stable_range; /* Not modified. */
|
|
thermal_data.u.data.arg[1] = phpb_theta_min; /* Not modified. */
|
|
thermal_data.u.data.arg[2] = phpb_theta_max;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP5, 3,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
return ackData;
|
|
}
|
|
|
|
static int atm_update_catm_param_to_sspm(void)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
/* CATM, modified in mtk_cooler_atm::tscpu_write_ctm(). */
|
|
thermal_data.u.data.arg[0] = MAX_TARGET_TJ;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP6, 1,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
return ackData;
|
|
}
|
|
|
|
static int atm_update_cg_alloc_param_to_sspm(void)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
/* CG Allocation,
|
|
* modified in mtk_cooler_atm::tscpu_write_gpu_threshold().
|
|
*/
|
|
thermal_data.u.data.arg[0] = GPU_L_H_TRIP;
|
|
thermal_data.u.data.arg[1] = GPU_L_L_TRIP;
|
|
while ((ret = atm_to_sspm(THERMAL_IPI_SET_ATM_CFG_GRP7, 2,
|
|
&thermal_data, &ackData)) && ret < 0)
|
|
mdelay(1);
|
|
|
|
return ackData;
|
|
}
|
|
|
|
static int atm_update_ttj_to_sspm(void)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
thermal_data.u.data.arg[0] = TARGET_TJ;
|
|
|
|
ret = atm_to_sspm(THERMAL_IPI_SET_ATM_TTJ, 1, &thermal_data, &ackData);
|
|
if (ret < 0) {
|
|
/* Retry one time. */
|
|
mdelay(1);
|
|
ret = atm_to_sspm(THERMAL_IPI_SET_ATM_TTJ, 1,
|
|
&thermal_data, &ackData);
|
|
if (ret < 0)
|
|
tscpu_printk("%s ret %d ack %d\n", __func__,
|
|
ret, ackData);
|
|
}
|
|
|
|
return ackData;
|
|
}
|
|
|
|
static int atm_enable_atm_in_sspm(int enable)
|
|
{
|
|
int ret = 0;
|
|
struct thermal_ipi_data thermal_data;
|
|
int ackData = 0;
|
|
|
|
if (enable == 0 || enable == 1) {
|
|
thermal_data.u.data.arg[0] = enable;
|
|
ret = atm_to_sspm(THERMAL_IPI_SET_ATM_EN, 1,
|
|
&thermal_data, &ackData);
|
|
if (ret < 0) {
|
|
/* Retry one time. */
|
|
mdelay(1);
|
|
ret = atm_to_sspm(THERMAL_IPI_SET_ATM_EN, 1,
|
|
&thermal_data, &ackData);
|
|
if (ret < 0)
|
|
tscpu_printk("%s ret %d ack %d\n", __func__,
|
|
ret, ackData);
|
|
}
|
|
}
|
|
|
|
return ackData;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
static void atm_profile_atm_period(s64 latest_latency)
|
|
{
|
|
atm_period_max_delay = MAX(latest_latency, atm_period_max_delay);
|
|
atm_period_min_delay = MIN(latest_latency, atm_period_min_delay);
|
|
/* for 20ms ATM polling period,
|
|
* rolling avg of 2^14 roughly catchs 5min of data.
|
|
* 50 (Hz) * 60 (s) * 5 (min) = 15000.
|
|
*/
|
|
if (atm_period_cnt < 16384) {
|
|
atm_period_avg_delay =
|
|
(latest_latency + atm_period_avg_delay *
|
|
(atm_period_cnt-1))/atm_period_cnt;
|
|
|
|
atm_period_cnt++;
|
|
} else {
|
|
atm_period_avg_delay =
|
|
(latest_latency + (atm_period_avg_delay<<14) -
|
|
atm_period_avg_delay)>>14;
|
|
}
|
|
tscpu_warn("atm period M %lld m %lld a %lld l %lld\n"
|
|
, atm_period_max_delay
|
|
, atm_period_min_delay
|
|
, atm_period_avg_delay
|
|
, latest_latency);
|
|
}
|
|
|
|
static void atm_profile_atm_exec(s64 latest_latency)
|
|
{
|
|
atm_exec_max_delay = MAX(latest_latency, atm_exec_max_delay);
|
|
atm_exec_min_delay = MIN(latest_latency, atm_exec_min_delay);
|
|
if (atm_exec_cnt < 16384) {
|
|
atm_exec_avg_delay =
|
|
(latest_latency + atm_exec_avg_delay *
|
|
(atm_exec_cnt-1))/atm_exec_cnt;
|
|
|
|
atm_exec_cnt++;
|
|
} else {
|
|
atm_exec_avg_delay =
|
|
(latest_latency + (atm_exec_avg_delay<<14) -
|
|
atm_exec_avg_delay)>>14;
|
|
}
|
|
tscpu_warn("atm exec delay M %lld m %lld a %lld l %lld\n"
|
|
, atm_exec_max_delay
|
|
, atm_exec_min_delay
|
|
, atm_exec_avg_delay
|
|
, latest_latency);
|
|
}
|
|
|
|
static void atm_profile_cpu_power_limit(s64 latest_latency)
|
|
{
|
|
cpu_pwr_lmt_max_delay = MAX(latest_latency, cpu_pwr_lmt_max_delay);
|
|
cpu_pwr_lmt_min_delay = MIN(latest_latency, cpu_pwr_lmt_min_delay);
|
|
if (cpu_pwr_lmt_cnt < 16384) {
|
|
cpu_pwr_lmt_avg_delay =
|
|
(latest_latency + cpu_pwr_lmt_avg_delay *
|
|
(cpu_pwr_lmt_cnt-1))/cpu_pwr_lmt_cnt;
|
|
|
|
cpu_pwr_lmt_cnt++;
|
|
} else {
|
|
cpu_pwr_lmt_avg_delay =
|
|
(latest_latency + (cpu_pwr_lmt_avg_delay<<14) -
|
|
cpu_pwr_lmt_avg_delay)>>14;
|
|
}
|
|
tscpu_warn("cpu lmt delay M %lld m %lld a %lld l %lld\n"
|
|
, cpu_pwr_lmt_max_delay
|
|
, cpu_pwr_lmt_min_delay
|
|
, cpu_pwr_lmt_avg_delay
|
|
, latest_latency);
|
|
}
|
|
|
|
static void atm_profile_gpu_power_limit(s64 latest_latency)
|
|
{
|
|
gpu_pwr_lmt_max_delay = MAX(latest_latency, gpu_pwr_lmt_max_delay);
|
|
gpu_pwr_lmt_min_delay = MIN(latest_latency, gpu_pwr_lmt_min_delay);
|
|
if (gpu_pwr_lmt_cnt < 16384) {
|
|
gpu_pwr_lmt_avg_delay =
|
|
(latest_latency + gpu_pwr_lmt_avg_delay *
|
|
(gpu_pwr_lmt_cnt-1))/gpu_pwr_lmt_cnt;
|
|
|
|
gpu_pwr_lmt_cnt++;
|
|
} else {
|
|
gpu_pwr_lmt_avg_delay =
|
|
(latest_latency + (gpu_pwr_lmt_avg_delay<<14) -
|
|
gpu_pwr_lmt_avg_delay)/1024;
|
|
}
|
|
tscpu_warn("gpu lmt delay M %lld m %lld a %lld l %lld\n"
|
|
, gpu_pwr_lmt_max_delay
|
|
, gpu_pwr_lmt_min_delay
|
|
, gpu_pwr_lmt_avg_delay
|
|
, latest_latency);
|
|
}
|
|
#endif
|
|
|
|
static void set_adaptive_cpu_power_limit(unsigned int limit)
|
|
{
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_lock(&atm_cpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
|
|
prv_adp_cpu_pwr_lim = adaptive_cpu_power_limit;
|
|
adaptive_cpu_power_limit = (limit != 0) ? limit : 0x7FFFFFFF;
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled)
|
|
adaptive_cpu_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
#endif
|
|
|
|
if (prv_adp_cpu_pwr_lim != adaptive_cpu_power_limit) {
|
|
#ifdef ATM_CFG_PROFILING
|
|
ktime_t now, delta;
|
|
#endif
|
|
|
|
/* print debug log */
|
|
adaptive_limit[print_cunt][0] =
|
|
(int) (adaptive_cpu_power_limit != 0x7FFFFFFF) ?
|
|
adaptive_cpu_power_limit : 0;
|
|
|
|
#ifdef FAST_RESPONSE_ATM
|
|
adaptive_limit[print_cunt][1] = krtatm_curr_maxtj;
|
|
#else
|
|
adaptive_limit[print_cunt][1] = tscpu_get_curr_temp();
|
|
#endif
|
|
print_cunt++;
|
|
if (print_cunt == 5) {
|
|
tscpu_warn(
|
|
"%s (0x%x) %d T=%d, %d T=%d, %d T=%d, %d T=%d, %d T=%d\n",
|
|
__func__,
|
|
tscpu_get_temperature_range(),
|
|
adaptive_limit[4][0], adaptive_limit[4][1],
|
|
adaptive_limit[3][0], adaptive_limit[3][1],
|
|
adaptive_limit[2][0], adaptive_limit[2][1],
|
|
adaptive_limit[1][0], adaptive_limit[1][1],
|
|
adaptive_limit[0][0], adaptive_limit[0][1]);
|
|
|
|
print_cunt = 0;
|
|
} else {
|
|
#ifdef FAST_RESPONSE_ATM
|
|
if ((prv_adp_cpu_pwr_lim != 0x7FFFFFFF) &&
|
|
((adaptive_cpu_power_limit + 1000)
|
|
< prv_adp_cpu_pwr_lim))
|
|
tscpu_warn(
|
|
"%s Big delta power %u curr_T=%d, %u prev_T=%d\n",
|
|
__func__, adaptive_cpu_power_limit,
|
|
krtatm_curr_maxtj, prv_adp_cpu_pwr_lim,
|
|
krtatm_prev_maxtj);
|
|
#endif
|
|
}
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
now = ktime_get();
|
|
#endif
|
|
apthermolmt_set_cpu_power_limit(&ap_atm,
|
|
adaptive_cpu_power_limit);
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
delta = ktime_get();
|
|
if (ktime_after(delta, now)) {
|
|
cpu_pwr_lmt_latest_delay =
|
|
ktime_to_us(ktime_sub(delta, now));
|
|
|
|
atm_profile_cpu_power_limit(cpu_pwr_lmt_latest_delay);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_unlock(&atm_cpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static void set_adaptive_gpu_power_limit(unsigned int limit)
|
|
{
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_lock(&atm_gpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
|
|
prv_adp_gpu_pwr_lim = adaptive_gpu_power_limit;
|
|
adaptive_gpu_power_limit = (limit != 0) ? limit : 0x7FFFFFFF;
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled)
|
|
adaptive_gpu_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
#endif
|
|
|
|
if (prv_adp_gpu_pwr_lim != adaptive_gpu_power_limit) {
|
|
#ifdef ATM_CFG_PROFILING
|
|
ktime_t now, delta;
|
|
#endif
|
|
|
|
tscpu_dprintk("%s %d\n", __func__,
|
|
(adaptive_gpu_power_limit != 0x7FFFFFFF) ?
|
|
adaptive_gpu_power_limit : 0);
|
|
#ifdef ATM_CFG_PROFILING
|
|
now = ktime_get();
|
|
#endif
|
|
apthermolmt_set_gpu_power_limit(&ap_atm,
|
|
adaptive_gpu_power_limit);
|
|
#ifdef ATM_CFG_PROFILING
|
|
delta = ktime_get();
|
|
if (ktime_after(delta, now)) {
|
|
gpu_pwr_lmt_latest_delay =
|
|
ktime_to_us(ktime_sub(delta, now));
|
|
|
|
atm_profile_gpu_power_limit(gpu_pwr_lmt_latest_delay);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_unlock(&atm_gpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
static void set_adaptive_vpu_power_limit(unsigned int limit)
|
|
{
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_lock(&atm_vpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
|
|
prv_adp_vpu_pwr_lim = adaptive_vpu_power_limit;
|
|
adaptive_vpu_power_limit = (limit != 0) ? limit : 0x7FFFFFFF;
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled)
|
|
adaptive_vpu_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
#endif
|
|
|
|
if (prv_adp_vpu_pwr_lim != adaptive_vpu_power_limit) {
|
|
tscpu_dprintk("%s %d\n", __func__,
|
|
(adaptive_vpu_power_limit != 0x7FFFFFFF) ?
|
|
adaptive_vpu_power_limit : 0);
|
|
apthermolmt_set_vpu_power_limit(&ap_atm,
|
|
adaptive_vpu_power_limit);
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_unlock(&atm_vpu_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
static void set_adaptive_mdla_power_limit(unsigned int limit)
|
|
{
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_lock(&atm_mdla_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
|
|
prv_adp_mdla_pwr_lim = adaptive_mdla_power_limit;
|
|
adaptive_mdla_power_limit = (limit != 0) ? limit : 0x7FFFFFFF;
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled)
|
|
adaptive_mdla_power_limit = 0x7FFFFFFF;
|
|
#endif
|
|
#endif
|
|
|
|
if (prv_adp_mdla_pwr_lim != adaptive_mdla_power_limit) {
|
|
tscpu_dprintk("%s %d\n", __func__,
|
|
(adaptive_mdla_power_limit != 0x7FFFFFFF) ?
|
|
adaptive_mdla_power_limit : 0);
|
|
apthermolmt_set_mdla_power_limit(&ap_atm,
|
|
adaptive_mdla_power_limit);
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
mutex_unlock(&atm_mdla_lmt_mutex);
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
int is_cpu_power_unlimit(void)
|
|
{
|
|
return (g_total_power == 0
|
|
|| g_total_power >= MAXIMUM_TOTAL_POWER) ? 1 : 0;
|
|
|
|
}
|
|
EXPORT_SYMBOL(is_cpu_power_unlimit);
|
|
|
|
int is_cpu_power_min(void)
|
|
{
|
|
return (g_total_power <= MINIMUM_TOTAL_POWER) ? 1 : 0;
|
|
}
|
|
EXPORT_SYMBOL(is_cpu_power_min);
|
|
|
|
/**
|
|
* TODO: What's the diff from get_target_tj?
|
|
*/
|
|
int get_cpu_target_tj(void)
|
|
{
|
|
return cpu_target_tj;
|
|
}
|
|
EXPORT_SYMBOL(get_cpu_target_tj);
|
|
|
|
int get_cpu_target_offset(void)
|
|
{
|
|
return cpu_target_offset;
|
|
}
|
|
EXPORT_SYMBOL(get_cpu_target_offset);
|
|
|
|
/*add for DLPT*/
|
|
int tscpu_get_min_cpu_pwr(void)
|
|
{
|
|
return MINIMUM_CPU_POWER;
|
|
}
|
|
EXPORT_SYMBOL(tscpu_get_min_cpu_pwr);
|
|
|
|
int tscpu_get_min_gpu_pwr(void)
|
|
{
|
|
return MINIMUM_GPU_POWER;
|
|
}
|
|
EXPORT_SYMBOL(tscpu_get_min_gpu_pwr);
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
int tscpu_get_min_vpu_pwr(void)
|
|
{
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1)
|
|
return MAXIMUM_VPU_POWER;
|
|
else
|
|
return MINIMUM_VPU_POWER;
|
|
#else
|
|
return MINIMUM_VPU_POWER;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(tscpu_get_min_vpu_pwr);
|
|
#endif
|
|
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
int tscpu_get_min_mdla_pwr(void)
|
|
{
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1)
|
|
return MAXIMUM_MDLA_POWER;
|
|
else
|
|
return MINIMUM_MDLA_POWER;
|
|
#else
|
|
return MINIMUM_MDLA_POWER;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(tscpu_get_min_mdla_pwr);
|
|
#endif
|
|
|
|
#if CONTINUOUS_TM
|
|
/**
|
|
* @brief update cATM+ ttj control loop parameters
|
|
* everytime related parameters are changed, we need to recalculate.
|
|
* from thermal config: MAX_TARGET_TJ, STEADY_TARGET_TJ,
|
|
* MIN_TTJ, TRIP_TPCB...etc
|
|
* cATM+'s parameters: K_SUM_TT_HIGH, K_SUM_TT_LOW
|
|
*/
|
|
|
|
struct CATM_T thermal_atm_t;
|
|
|
|
static void catmplus_update_params(void)
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
thermal_atm_t.t_catm_par.CATM_ON = ctm_on;
|
|
thermal_atm_t.t_catm_par.K_TT = K_TT;
|
|
thermal_atm_t.t_catm_par.K_SUM_TT_LOW = K_SUM_TT_LOW;
|
|
thermal_atm_t.t_catm_par.K_SUM_TT_HIGH = K_SUM_TT_HIGH;
|
|
thermal_atm_t.t_catm_par.MIN_SUM_TT = MIN_SUM_TT;
|
|
thermal_atm_t.t_catm_par.MAX_SUM_TT = MAX_SUM_TT;
|
|
thermal_atm_t.t_catm_par.MIN_TTJ = MIN_TTJ;
|
|
thermal_atm_t.t_catm_par.CATMP_STEADY_TTJ_DELTA =
|
|
CATMP_STEADY_TTJ_DELTA;
|
|
|
|
|
|
thermal_atm_t.t_continuetm_par.STEADY_TARGET_TJ = STEADY_TARGET_TJ;
|
|
thermal_atm_t.t_continuetm_par.MAX_TARGET_TJ = MAX_TARGET_TJ;
|
|
thermal_atm_t.t_continuetm_par.TRIP_TPCB = TRIP_TPCB;
|
|
thermal_atm_t.t_continuetm_par.STEADY_TARGET_TPCB =
|
|
STEADY_TARGET_TPCB;
|
|
|
|
ret = wakeup_ta_algo(TA_CATMPLUS);
|
|
/*tscpu_warn("catmplus_update_params : ret %d\n" , ret);*/
|
|
}
|
|
|
|
#endif
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
static int _get_current_gpu_power(void)
|
|
{
|
|
unsigned int cur_gpu_freq = mt_gpufreq_get_cur_freq();
|
|
unsigned int cur_gpu_power = 0;
|
|
int i = gpu_max_opp;
|
|
|
|
if (mtk_gpu_power != NULL) {
|
|
for (; i < Num_of_GPU_OPP; i++)
|
|
if (mtk_gpu_power[i].gpufreq_khz == cur_gpu_freq)
|
|
cur_gpu_power = mtk_gpu_power[i].gpufreq_power;
|
|
}
|
|
|
|
return (int) cur_gpu_power;
|
|
}
|
|
|
|
#if 0
|
|
static void reset_gpu_power_history(void)
|
|
{
|
|
int i = 0;
|
|
/* Be careful when this can be invoked and error values. */
|
|
unsigned int max_gpu_power = mt_gpufreq_get_max_power();
|
|
|
|
if (gpu_power_sma_len > MAX_GPU_POWER_SMA_LEN)
|
|
gpu_power_sma_len = MAX_GPU_POWER_SMA_LEN;
|
|
|
|
for (i = 0; i < MAX_GPU_POWER_SMA_LEN; i++)
|
|
gpu_power_history[i] = max_gpu_power;
|
|
|
|
gpu_power_history_idx = 0;
|
|
}
|
|
|
|
/* we'll calculate SMA for gpu power,
|
|
* but the output will still be aligned to OPP
|
|
*/
|
|
static int adjust_gpu_power(int power)
|
|
{
|
|
int i, total = 0, sma_power;
|
|
|
|
/* FIXME: debug only, this check should be
|
|
* moved to some setter functions.
|
|
* or deleted if we don't want sma_len is changeable during runtime
|
|
*/
|
|
/*
|
|
*if (gpu_power_sma_len > MAX_GPU_POWER_SMA_LEN)
|
|
* gpu_power_sma_len = MAX_GPU_POWER_SMA_LEN;
|
|
*/
|
|
|
|
if (power == 0)
|
|
power = MAXIMUM_GPU_POWER;
|
|
|
|
gpu_power_history[gpu_power_history_idx] = power;
|
|
for (i = 0; i < gpu_power_sma_len; i++)
|
|
total += gpu_power_history[i];
|
|
|
|
gpu_power_history_idx = (gpu_power_history_idx + 1) % gpu_power_sma_len;
|
|
sma_power = total / gpu_power_sma_len;
|
|
|
|
for (i = gpu_max_opp; i < Num_of_GPU_OPP; i++) {
|
|
if (mtk_gpu_power[i].gpufreq_power <= sma_power)
|
|
break;
|
|
}
|
|
|
|
if (i >= Num_of_GPU_OPP)
|
|
power = MINIMUM_GPU_POWER;
|
|
else
|
|
power = MAX(MINIMUM_GPU_POWER,
|
|
(int)mtk_gpu_power[i].gpufreq_power);
|
|
|
|
return power;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
*Pass ATM total power budget to EARA for C/G/... allocation
|
|
*ATM follow up if ERAR bypass
|
|
*/
|
|
static int EARA_handled(int total_power)
|
|
{
|
|
#if defined(EARA_THERMAL_SUPPORT)
|
|
int total_power_eara;
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
if (!g_turbo_bin)
|
|
return 0;
|
|
#endif
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1) {/*APU hint*/
|
|
total_power = 0;/*let EARA unlimit VPU/MDLA freq*/
|
|
}
|
|
#endif
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT) && defined(THERMAL_MDLA_SUPPORT)
|
|
if (total_power == 0)
|
|
total_power_eara = 0;
|
|
else if (is_cpu_power_unlimit())
|
|
total_power_eara = total_power +
|
|
MAXIMUM_VPU_POWER + MAXIMUM_MDLA_POWER;
|
|
else
|
|
total_power_eara = total_power +
|
|
MINIMUM_VPU_POWER + MINIMUM_MDLA_POWER;
|
|
is_EARA_handled = mtk_eara_thermal_pb_handle(total_power_eara,
|
|
MAXIMUM_CPU_POWER, MAXIMUM_GPU_POWER,
|
|
MAXIMUM_VPU_POWER, MAXIMUM_MDLA_POWER);
|
|
#else
|
|
total_power_eara = total_power;
|
|
is_EARA_handled = mtk_eara_thermal_pb_handle(total_power_eara,
|
|
MAXIMUM_CPU_POWER, MAXIMUM_GPU_POWER, -1, -1);
|
|
#endif
|
|
return is_EARA_handled;
|
|
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int P_adaptive(int total_power, unsigned int gpu_loading)
|
|
{
|
|
/*
|
|
*Here the gpu_power is the gpu power limit for the next interval,
|
|
*not exactly what gpu power selected by GPU DVFS
|
|
* But the ground rule is real gpu power should always
|
|
* under gpu_power for the same time interval
|
|
*/
|
|
static int cpu_power = 0, gpu_power;
|
|
static int last_cpu_power = 0, last_gpu_power;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
static int vpu_power, last_vpu_power;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
static int mdla_power, last_mdla_power;
|
|
#endif
|
|
#if defined(DDR_STRESS_WORKAROUND)
|
|
static int opp0_cool;
|
|
#endif
|
|
|
|
last_cpu_power = cpu_power;
|
|
last_gpu_power = gpu_power;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
last_vpu_power = vpu_power;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
last_mdla_power = mdla_power;
|
|
#endif
|
|
g_total_power = total_power;
|
|
|
|
if (EARA_handled(total_power) || (total_power == 0)) {
|
|
cpu_power = gpu_power = 0;
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
vpu_power = 0;
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
mdla_power = 0;
|
|
#endif
|
|
|
|
#if THERMAL_HEADROOM
|
|
if (thp_max_cpu_power != 0)
|
|
set_adaptive_cpu_power_limit(
|
|
(unsigned int)MAX(
|
|
thp_max_cpu_power, MINIMUM_CPU_POWER));
|
|
else
|
|
set_adaptive_cpu_power_limit(0);
|
|
#else
|
|
set_adaptive_cpu_power_limit(0);
|
|
#endif
|
|
set_adaptive_gpu_power_limit(0);
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
set_adaptive_vpu_power_limit(0);
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
set_adaptive_mdla_power_limit(0);
|
|
#endif
|
|
#if (CONFIG_THERMAL_AEE_RR_REC == 1)
|
|
aee_rr_rec_thermal_ATM_status(ATM_DONE);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if (total_power <= MINIMUM_TOTAL_POWER) {
|
|
cpu_power = MINIMUM_CPU_POWER;
|
|
gpu_power = MINIMUM_GPU_POWER;
|
|
} else if (total_power >= MAXIMUM_TOTAL_POWER) {
|
|
cpu_power = MAXIMUM_CPU_POWER;
|
|
gpu_power = MAXIMUM_GPU_POWER;
|
|
} else {
|
|
if (mtk_gpu_power != NULL) {
|
|
int max_allowed_gpu_power =
|
|
MIN((total_power - MINIMUM_CPU_POWER),
|
|
MAXIMUM_GPU_POWER);
|
|
|
|
int max_gpu_power = (int) mt_gpufreq_get_max_power();
|
|
int highest_possible_gpu_power =
|
|
(max_allowed_gpu_power > max_gpu_power) ?
|
|
(max_gpu_power+1) : -1;
|
|
|
|
/* int highest_possible_gpu_power_idx = 0; */
|
|
int i = gpu_max_opp;
|
|
|
|
unsigned int cur_gpu_freq = mt_gpufreq_get_cur_freq();
|
|
/* int cur_idx = 0; */
|
|
unsigned int cur_gpu_power = 0;
|
|
unsigned int next_lower_gpu_power = 0;
|
|
|
|
/* get GPU highest possible power and index and
|
|
* current power and index and next lower power
|
|
*/
|
|
for (; i < Num_of_GPU_OPP; i++) {
|
|
if ((mtk_gpu_power[i].gpufreq_power <=
|
|
max_allowed_gpu_power) &&
|
|
(-1 == highest_possible_gpu_power)) {
|
|
/* choose OPP with power "<=" limit */
|
|
highest_possible_gpu_power =
|
|
mtk_gpu_power[i].gpufreq_power + 1;
|
|
/* highest_possible_gpu_power_idx = i;*/
|
|
}
|
|
|
|
if (mtk_gpu_power[i].gpufreq_khz ==
|
|
cur_gpu_freq) {
|
|
/* choose OPP with power "<=" limit */
|
|
next_lower_gpu_power = cur_gpu_power
|
|
= (mtk_gpu_power[i].gpufreq_power + 1);
|
|
/* cur_idx = i; */
|
|
|
|
if ((i != Num_of_GPU_OPP - 1) &&
|
|
(mtk_gpu_power[i + 1].gpufreq_power
|
|
>= MINIMUM_GPU_POWER)) {
|
|
/* choose OPP with power "<=" limit */
|
|
next_lower_gpu_power =
|
|
mtk_gpu_power[i + 1]
|
|
.gpufreq_power + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* decide GPU power limit by loading */
|
|
if (gpu_loading > GPU_L_H_TRIP) {
|
|
gpu_power = highest_possible_gpu_power;
|
|
} else if (gpu_loading <= GPU_L_L_TRIP) {
|
|
gpu_power = MIN(next_lower_gpu_power,
|
|
highest_possible_gpu_power);
|
|
|
|
gpu_power = MAX(gpu_power, MINIMUM_GPU_POWER);
|
|
} else {
|
|
gpu_power = MIN(highest_possible_gpu_power,
|
|
cur_gpu_power);
|
|
|
|
gpu_power = MAX(gpu_power, MINIMUM_GPU_POWER);
|
|
}
|
|
} else {
|
|
gpu_power = 0;
|
|
}
|
|
|
|
cpu_power = MIN((total_power - gpu_power), MAXIMUM_CPU_POWER);
|
|
}
|
|
|
|
#if defined(DDR_STRESS_WORKAROUND)
|
|
if (tscpu_g_curr_temp > 70000) {
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
if ((mt_ppm_thermal_get_cur_power() >=
|
|
mt_ppm_thermal_get_max_power()) ||
|
|
(g_turbo_bin &&
|
|
(mt_ppm_thermal_get_cur_power() >=
|
|
mt_ppm_thermal_get_power_big_max_opp(1))))
|
|
#else
|
|
if (mt_ppm_thermal_get_cur_power() >=
|
|
mt_ppm_thermal_get_max_power())
|
|
#endif
|
|
opp0_cool = 1;
|
|
} else if (tscpu_g_curr_temp < 65000)
|
|
opp0_cool = 0;
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
if ((g_turbo_bin) && (STEADY_TARGET_TPCB >= 58000))
|
|
opp0_cool = 0;
|
|
|
|
if (g_turbo_bin && (opp0_cool)) {
|
|
if (cpu_power > mt_ppm_thermal_get_power_big_max_opp(1))
|
|
cpu_power = mt_ppm_thermal_get_power_big_max_opp(1) - 5;
|
|
} else if (opp0_cool)
|
|
cpu_power -= 5;
|
|
|
|
#else
|
|
if (opp0_cool)
|
|
cpu_power -= 5;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT) && defined(THERMAL_MDLA_SUPPORT)
|
|
g_delta_power = g_delta_power / 2;
|
|
#endif
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
if (total_power <= MINIMUM_TOTAL_POWER)
|
|
vpu_power = MAX(last_vpu_power + g_delta_power,
|
|
MINIMUM_VPU_POWER);
|
|
else
|
|
vpu_power = MAXIMUM_VPU_POWER;
|
|
#endif
|
|
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
if (total_power <= MINIMUM_TOTAL_POWER)
|
|
mdla_power = MAX(last_mdla_power + g_delta_power,
|
|
MINIMUM_MDLA_POWER);
|
|
else
|
|
mdla_power = MAXIMUM_MDLA_POWER;
|
|
#endif
|
|
|
|
#if 0
|
|
/* TODO: check if this segment can be used in original design
|
|
* GPU SMA
|
|
*/
|
|
if ((gpu_power_sma_len > 1) && (tscpu_atm == 3)) {
|
|
total_power = gpu_power + cpu_power;
|
|
gpu_power = adjust_gpu_power(gpu_power);
|
|
cpu_power = total_power - gpu_power;
|
|
}
|
|
#endif
|
|
|
|
if (cpu_power != last_cpu_power)
|
|
set_adaptive_cpu_power_limit(cpu_power);
|
|
|
|
if ((gpu_power != last_gpu_power) && (mtk_gpu_power != NULL)) {
|
|
/* Work-around for unsync GPU power table problem 1. */
|
|
if (gpu_power >= mtk_gpu_power[gpu_max_opp].gpufreq_power)
|
|
set_adaptive_gpu_power_limit(0);
|
|
else
|
|
set_adaptive_gpu_power_limit(gpu_power);
|
|
}
|
|
|
|
tscpu_dprintk("%s cpu %d, gpu %d\n", __func__, cpu_power, gpu_power);
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
/*APU hint*/
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1) {
|
|
set_adaptive_vpu_power_limit(0);
|
|
} else {
|
|
if (vpu_power != last_vpu_power) {
|
|
if (vpu_power >= MAXIMUM_VPU_POWER)
|
|
set_adaptive_vpu_power_limit(0);
|
|
else
|
|
set_adaptive_vpu_power_limit(vpu_power);
|
|
}
|
|
}
|
|
#else
|
|
if (vpu_power != last_vpu_power) {
|
|
if (vpu_power >= MAXIMUM_VPU_POWER)
|
|
set_adaptive_vpu_power_limit(0);
|
|
else
|
|
set_adaptive_vpu_power_limit(vpu_power);
|
|
}
|
|
#endif
|
|
tscpu_dprintk("%s vpu %d\n",
|
|
__func__, vpu_power);
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
/*APU hint*/
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1) {
|
|
set_adaptive_mdla_power_limit(0);
|
|
} else {
|
|
if (mdla_power != last_mdla_power) {
|
|
if (mdla_power >= MAXIMUM_MDLA_POWER)
|
|
set_adaptive_mdla_power_limit(0);
|
|
else
|
|
set_adaptive_mdla_power_limit(mdla_power);
|
|
}
|
|
}
|
|
#else
|
|
if (mdla_power != last_mdla_power) {
|
|
if (mdla_power >= MAXIMUM_MDLA_POWER)
|
|
set_adaptive_mdla_power_limit(0);
|
|
else
|
|
set_adaptive_mdla_power_limit(mdla_power);
|
|
}
|
|
#endif
|
|
tscpu_dprintk("%s mdla %d\n",
|
|
__func__, mdla_power);
|
|
#endif
|
|
|
|
#if (CONFIG_THERMAL_AEE_RR_REC == 1)
|
|
aee_rr_rec_thermal_ATM_status(ATM_DONE);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
static int g_theta;
|
|
static int g_delta_power_tt;
|
|
static int g_delta_power_tp;
|
|
static int g_tt;
|
|
static int g_tp;
|
|
|
|
static int __phpb_dynamic_theta(int max_theta)
|
|
{
|
|
int theta;
|
|
/* temp solution as CATM
|
|
* FIXME: API? how to get tj trip?
|
|
*/
|
|
int tj_trip = TARGET_TJS[0];
|
|
|
|
if (tj_trip >= TARGET_TJ)
|
|
theta = max_theta;
|
|
else if (TARGET_TJ >= MAX_TARGET_TJ)
|
|
theta = phpb_theta_min;
|
|
else {
|
|
theta = max_theta - (TARGET_TJ - tj_trip) *
|
|
(max_theta - phpb_theta_min) /
|
|
(MAX_TARGET_TJ - tj_trip);
|
|
}
|
|
|
|
g_theta = theta;
|
|
return theta;
|
|
}
|
|
|
|
/**
|
|
* TODO: target_tj is adjusted by catmv2, therefore dynamic_theta would not
|
|
* changed frequently.
|
|
*/
|
|
static int __phpb_calc_delta(int curr_temp, int prev_temp, int phpb_param_idx)
|
|
{
|
|
struct phpb_param *p = &phpb_params[phpb_param_idx];
|
|
int tt = TARGET_TJ - curr_temp;
|
|
int tp = prev_temp - curr_temp;
|
|
int delta_power = 0, delta_power_tt = 0, delta_power_tp = 0;
|
|
|
|
/* *2 is to cover Tj jump betwen [TTJ-tj_stable_range,
|
|
* TTJ+tj_stable_range]
|
|
*/
|
|
if ((abs(tt) > tj_stable_range) || (abs(tp) > (tj_stable_range * 2))) {
|
|
/* use theta_t = 10 when Tj < TTJ to avoid throttling by mistake */
|
|
delta_power_tt = (curr_temp < TARGET_TJ) ? (tt / 10) : (tt / p->tt);
|
|
delta_power_tp = tp / p->tp;
|
|
/* When Tj is rising, double power cut. */
|
|
if (delta_power_tp < 0)
|
|
delta_power_tp *= 2;
|
|
delta_power = (delta_power_tt + delta_power_tp) /
|
|
__phpb_dynamic_theta(phpb_theta_max);
|
|
}
|
|
if ((tt < 0) && (curr_temp < TARGET_TJ)) {
|
|
delta_power = 0;
|
|
tscpu_dprintk("%s Wrong TARGET_TJ\n", __func__);
|
|
}
|
|
|
|
g_tt = tt;
|
|
g_tp = tp;
|
|
g_delta_power_tt = delta_power_tt;
|
|
g_delta_power_tp = delta_power_tp;
|
|
|
|
return delta_power;
|
|
}
|
|
|
|
static int phpb_calc_delta(int curr_temp, int prev_temp)
|
|
{
|
|
int delta, param_idx;
|
|
|
|
if (tscpu_curr_cpu_temp >= tscpu_curr_gpu_temp)
|
|
param_idx = PHPB_PARAM_CPU;
|
|
else
|
|
param_idx = PHPB_PARAM_GPU;
|
|
|
|
delta = __phpb_calc_delta(curr_temp, prev_temp, param_idx);
|
|
|
|
return delta;
|
|
}
|
|
|
|
/* get current power from current opp, real value, does not set minimum */
|
|
int clatm_get_curr_opp_power(void)
|
|
{
|
|
int cpu_power = 0, gpu_power = 0;
|
|
|
|
cpu_power = (int) mt_ppm_thermal_get_cur_power();
|
|
gpu_power = _get_current_gpu_power();
|
|
|
|
tscpu_dprintk("%s cpu power=%d gpu power=%d\n",
|
|
__func__, cpu_power, gpu_power);
|
|
|
|
return cpu_power + gpu_power;
|
|
}
|
|
|
|
/* calculated total power based on current opp */
|
|
static int get_total_curr_power(void)
|
|
{
|
|
int cpu_power = 0, gpu_power = 0;
|
|
|
|
#ifdef ATM_USES_PPM
|
|
/* choose OPP with power "<=" limit */
|
|
cpu_power = (int) mt_ppm_thermal_get_cur_power() + 1;
|
|
#else
|
|
/* maybe you should disable PRECISE_HYBRID_POWER_BUDGET
|
|
* if current cpu power unavailable .
|
|
*/
|
|
cpu_power = 0;
|
|
#endif
|
|
/* avoid idle power too small to hurt another unit performance */
|
|
if (cpu_power < MINIMUM_CPU_POWER)
|
|
cpu_power = MINIMUM_CPU_POWER;
|
|
|
|
/* choose OPP with power "<=" limit */
|
|
gpu_power = _get_current_gpu_power() + 1;
|
|
if (gpu_power < MINIMUM_GPU_POWER)
|
|
gpu_power = MINIMUM_GPU_POWER;
|
|
|
|
return cpu_power + gpu_power;
|
|
}
|
|
|
|
static int phpb_calc_total(int prev_total_power, long curr_temp, long prev_temp)
|
|
{
|
|
/* total_power is new power limit, which curr_power is current power
|
|
* calculated based on current opp
|
|
*/
|
|
int delta_power, total_power, curr_power;
|
|
#if 0 /* Just use previous total power to avoid conflict with fpsgo */
|
|
int tt = TARGET_TJ - curr_temp;
|
|
int tp = prev_temp - curr_temp;
|
|
#endif
|
|
|
|
delta_power = phpb_calc_delta(curr_temp, prev_temp);
|
|
#if defined(THERMAL_VPU_SUPPORT) || defined(THERMAL_MDLA_SUPPORT)
|
|
g_delta_power = delta_power;
|
|
#endif
|
|
if (delta_power == 0) {
|
|
#if defined(THERMAL_VPU_SUPPORT) || defined(THERMAL_MDLA_SUPPORT)
|
|
trace_ATM__pid(curr_temp, prev_temp, g_tt, g_tp, g_theta, g_delta_power_tt,
|
|
g_delta_power_tp, g_delta_power, prev_total_power);
|
|
#else
|
|
trace_ATM__pid(curr_temp, prev_temp, g_tt, g_tp, g_theta, g_delta_power_tt,
|
|
g_delta_power_tp, 0, prev_total_power);
|
|
#endif
|
|
return prev_total_power;
|
|
}
|
|
|
|
curr_power = get_total_curr_power();
|
|
|
|
#if 0 /* Just use previous total power to avoid conflict with fpsgo */
|
|
/* In some conditions, we will consider using current request power to
|
|
* avoid giving unlimit power budget.
|
|
* Temp. rising is large, requset power is of course less than power
|
|
* limit (but it sometime goes over...)
|
|
*/
|
|
if (curr_power < prev_total_power
|
|
&& ((-tt) >= tj_stable_range * 2
|
|
|| (-tp) >= tj_stable_range * 4)) {
|
|
tscpu_dprintk(
|
|
"%s prev_temp %ld, curr_temp %ld, curr %d, delta %d\n",
|
|
__func__, prev_temp, curr_temp, curr_power,
|
|
delta_power);
|
|
|
|
total_power = curr_power + delta_power;
|
|
} else {
|
|
tscpu_dprintk(
|
|
"%s prev_temp %ld, curr_temp %ld, prev %d, delta %d\n",
|
|
__func__, prev_temp, curr_temp, prev_total_power,
|
|
delta_power);
|
|
|
|
total_power = prev_total_power + delta_power;
|
|
}
|
|
#else
|
|
tscpu_dprintk(
|
|
"%s prev_temp %ld, curr_temp %ld, prev %d, delta %d, curr %d\n",
|
|
__func__, prev_temp, curr_temp, prev_total_power,
|
|
delta_power, curr_power);
|
|
|
|
total_power = prev_total_power + delta_power;
|
|
#endif
|
|
|
|
total_power = clamp(total_power, MINIMUM_TOTAL_POWER,
|
|
MAXIMUM_TOTAL_POWER);
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT) || defined(THERMAL_MDLA_SUPPORT)
|
|
trace_ATM__pid(curr_temp, prev_temp, g_tt, g_tp, g_theta, g_delta_power_tt,
|
|
g_delta_power_tp, g_delta_power, total_power);
|
|
#else
|
|
trace_ATM__pid(curr_temp, prev_temp, g_tt, g_tp, g_theta, g_delta_power_tt,
|
|
g_delta_power_tp, 0, total_power);
|
|
#endif
|
|
|
|
return total_power;
|
|
}
|
|
|
|
static int _adaptive_power_ppb
|
|
(long prev_temp, long curr_temp, unsigned int gpu_loading)
|
|
{
|
|
static int triggered, total_power;
|
|
int delta_power = 0;
|
|
|
|
if (curr_temp > TARGET_TJS[0] || cl_dev_adp_cpu_state_active == 1) {
|
|
tscpu_dprintk("%s %d %d %d %d %d %d %d\n", __func__,
|
|
PACKAGE_THETA_JA_RISE, PACKAGE_THETA_JA_FALL,
|
|
MINIMUM_BUDGET_CHANGE, MINIMUM_CPU_POWER,
|
|
MAXIMUM_CPU_POWER, MINIMUM_GPU_POWER,
|
|
MAXIMUM_GPU_POWER);
|
|
|
|
/* Check if it is triggered */
|
|
if (!triggered) {
|
|
triggered = 1;
|
|
total_power = phpb_calc_total(get_total_curr_power(),
|
|
curr_temp, prev_temp);
|
|
|
|
tscpu_dprintk(
|
|
"%s triggered:0->1 Tp %ld, Tc %ld, TARGET_TJ %d, Pt %d\n",
|
|
__func__, prev_temp, curr_temp, TARGET_TJ,
|
|
total_power);
|
|
|
|
return P_adaptive(total_power, gpu_loading);
|
|
}
|
|
|
|
/* Adjust total power budget if necessary */
|
|
total_power = phpb_calc_total(total_power,
|
|
curr_temp, prev_temp);
|
|
/* TODO: delta_power is not changed but printed. */
|
|
tscpu_dprintk(
|
|
"%s TARGET_TJ %d, delta_power %d, total_power %d\n",
|
|
__func__, TARGET_TJ, delta_power, total_power);
|
|
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp, total_power);
|
|
|
|
return P_adaptive(total_power, gpu_loading);
|
|
/* end of cl_dev_adp_cpu_state_active == 1 */
|
|
} else {
|
|
if (triggered) {
|
|
triggered = 0;
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp, total_power);
|
|
|
|
if (curr_temp > current_ETJ)
|
|
tscpu_printk("exit but Tc(%ld) > cetj(%d)\n",
|
|
curr_temp, current_ETJ);
|
|
|
|
return P_adaptive(0, 0);
|
|
#if THERMAL_HEADROOM
|
|
} else {
|
|
if (thp_max_cpu_power != 0)
|
|
set_adaptive_cpu_power_limit(
|
|
(unsigned int) MAX(thp_max_cpu_power,
|
|
MINIMUM_CPU_POWER));
|
|
else
|
|
set_adaptive_cpu_power_limit(0);
|
|
}
|
|
#else
|
|
}
|
|
#endif
|
|
/* reset_gpu_power_history(); */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int _adaptive_power
|
|
(long prev_temp, long curr_temp, unsigned int gpu_loading)
|
|
{
|
|
static int triggered = 0, total_power;
|
|
int delta_power = 0;
|
|
|
|
if (cl_dev_adp_cpu_state_active == 1) {
|
|
tscpu_dprintk("%s %d %d %d %d %d %d %d %d\n", __func__,
|
|
FIRST_STEP_TOTAL_POWER_BUDGET,
|
|
PACKAGE_THETA_JA_RISE, PACKAGE_THETA_JA_FALL,
|
|
MINIMUM_BUDGET_CHANGE, MINIMUM_CPU_POWER,
|
|
MAXIMUM_CPU_POWER, MINIMUM_GPU_POWER,
|
|
MAXIMUM_GPU_POWER);
|
|
|
|
/* Check if it is triggered */
|
|
if (!triggered) {
|
|
if (curr_temp < TARGET_TJ)
|
|
return 0;
|
|
|
|
triggered = 1;
|
|
switch (tscpu_atm) {
|
|
case 1: /* FTL ATM v2 */
|
|
case 2: /* CPU_GPU_Weight ATM v2 */
|
|
#if MTKTSCPU_FAST_POLLING
|
|
total_power =
|
|
FIRST_STEP_TOTAL_POWER_BUDGET -
|
|
((curr_temp - TARGET_TJ) * tt_ratio_high_rise +
|
|
(curr_temp - prev_temp) * tp_ratio_high_rise) /
|
|
(PACKAGE_THETA_JA_RISE * tscpu_cur_fp_factor);
|
|
#else
|
|
total_power =
|
|
FIRST_STEP_TOTAL_POWER_BUDGET -
|
|
((curr_temp - TARGET_TJ) * tt_ratio_high_rise +
|
|
(curr_temp - prev_temp) * tp_ratio_high_rise) /
|
|
PACKAGE_THETA_JA_RISE;
|
|
#endif
|
|
break;
|
|
case 0:
|
|
default: /* ATM v1 */
|
|
total_power = FIRST_STEP_TOTAL_POWER_BUDGET;
|
|
}
|
|
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp, total_power);
|
|
|
|
return P_adaptive(total_power, gpu_loading);
|
|
}
|
|
|
|
/* Adjust total power budget if necessary */
|
|
switch (tscpu_atm) {
|
|
case 1: /* FTL ATM v2 */
|
|
case 2: /* CPU_GPU_Weight ATM v2 */
|
|
if ((curr_temp >= TARGET_TJ_HIGH)
|
|
&& (curr_temp > prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
total_power -=
|
|
MAX(((curr_temp - TARGET_TJ) *
|
|
tt_ratio_high_rise +
|
|
(curr_temp - prev_temp) *
|
|
tp_ratio_high_rise) /
|
|
(PACKAGE_THETA_JA_RISE *
|
|
tscpu_cur_fp_factor),
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#else
|
|
total_power -=
|
|
MAX(((curr_temp - TARGET_TJ) *
|
|
tt_ratio_high_rise +
|
|
(curr_temp - prev_temp) *
|
|
tp_ratio_high_rise) /
|
|
PACKAGE_THETA_JA_RISE,
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#endif
|
|
} else if ((curr_temp >= TARGET_TJ_HIGH)
|
|
&& (curr_temp <= prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
total_power -=
|
|
MAX(((curr_temp - TARGET_TJ) *
|
|
tt_ratio_high_fall -
|
|
(prev_temp - curr_temp) *
|
|
tp_ratio_high_fall) /
|
|
(PACKAGE_THETA_JA_FALL *
|
|
tscpu_cur_fp_factor),
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#else
|
|
total_power -=
|
|
MAX(((curr_temp - TARGET_TJ) *
|
|
tt_ratio_high_fall -
|
|
(prev_temp - curr_temp) *
|
|
tp_ratio_high_fall) /
|
|
PACKAGE_THETA_JA_FALL,
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#endif
|
|
} else if ((curr_temp <= TARGET_TJ_LOW)
|
|
&& (curr_temp > prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
total_power +=
|
|
MAX(((TARGET_TJ - curr_temp) *
|
|
tt_ratio_low_rise -
|
|
(curr_temp - prev_temp) *
|
|
tp_ratio_low_rise) /
|
|
(PACKAGE_THETA_JA_RISE *
|
|
tscpu_cur_fp_factor),
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#else
|
|
total_power +=
|
|
MAX(((TARGET_TJ - curr_temp) *
|
|
tt_ratio_low_rise -
|
|
(curr_temp - prev_temp) *
|
|
tp_ratio_low_rise) /
|
|
PACKAGE_THETA_JA_RISE,
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#endif
|
|
} else if ((curr_temp <= TARGET_TJ_LOW)
|
|
&& (curr_temp <= prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
total_power +=
|
|
MAX(((TARGET_TJ - curr_temp) *
|
|
tt_ratio_low_fall +
|
|
(prev_temp - curr_temp) *
|
|
tp_ratio_low_fall) /
|
|
(PACKAGE_THETA_JA_FALL *
|
|
tscpu_cur_fp_factor),
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#else
|
|
total_power +=
|
|
MAX(((TARGET_TJ - curr_temp) *
|
|
tt_ratio_low_fall +
|
|
(prev_temp - curr_temp) *
|
|
tp_ratio_low_fall) /
|
|
PACKAGE_THETA_JA_FALL,
|
|
MINIMUM_BUDGET_CHANGE);
|
|
#endif
|
|
}
|
|
|
|
total_power = (total_power > MINIMUM_TOTAL_POWER) ?
|
|
total_power : MINIMUM_TOTAL_POWER;
|
|
|
|
total_power = (total_power < MAXIMUM_TOTAL_POWER) ?
|
|
total_power : MAXIMUM_TOTAL_POWER;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
default: /* ATM v1 */
|
|
if ((curr_temp > TARGET_TJ_HIGH)
|
|
&& (curr_temp >= prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
delta_power = (curr_temp - prev_temp) /
|
|
(PACKAGE_THETA_JA_RISE *
|
|
tscpu_cur_fp_factor);
|
|
#else
|
|
delta_power = (curr_temp - prev_temp) /
|
|
PACKAGE_THETA_JA_RISE;
|
|
#endif
|
|
if (prev_temp > TARGET_TJ_HIGH) {
|
|
delta_power =
|
|
(delta_power >
|
|
MINIMUM_BUDGET_CHANGE) ?
|
|
delta_power :
|
|
MINIMUM_BUDGET_CHANGE;
|
|
}
|
|
|
|
total_power -= delta_power;
|
|
total_power = (total_power >
|
|
MINIMUM_TOTAL_POWER) ?
|
|
total_power :
|
|
MINIMUM_TOTAL_POWER;
|
|
}
|
|
|
|
if ((curr_temp < TARGET_TJ_LOW)
|
|
&& (curr_temp <= prev_temp)) {
|
|
#if MTKTSCPU_FAST_POLLING
|
|
delta_power = (prev_temp - curr_temp) /
|
|
(PACKAGE_THETA_JA_FALL *
|
|
tscpu_cur_fp_factor);
|
|
#else
|
|
delta_power = (prev_temp - curr_temp) /
|
|
PACKAGE_THETA_JA_FALL;
|
|
#endif
|
|
if (prev_temp < TARGET_TJ_LOW) {
|
|
delta_power =
|
|
(delta_power >
|
|
MINIMUM_BUDGET_CHANGE) ?
|
|
delta_power :
|
|
MINIMUM_BUDGET_CHANGE;
|
|
}
|
|
|
|
total_power += delta_power;
|
|
total_power = (total_power <
|
|
MAXIMUM_TOTAL_POWER) ?
|
|
total_power :
|
|
MAXIMUM_TOTAL_POWER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp,
|
|
total_power);
|
|
|
|
return P_adaptive(total_power, gpu_loading);
|
|
}
|
|
#if CONTINUOUS_TM
|
|
else if ((cl_dev_adp_cpu_state_active == 1)
|
|
&& (ctm_on) && (curr_temp < current_ETJ)) {
|
|
tscpu_printk("CTM exit curr_temp %d cetj %d\n",
|
|
TARGET_TJ, current_ETJ);
|
|
/* even cooler not exit,
|
|
* when CTM is on and current Tj < current_ETJ, leave ATM
|
|
*/
|
|
if (triggered) {
|
|
triggered = 0;
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp,
|
|
total_power);
|
|
return P_adaptive(0, 0);
|
|
}
|
|
#if THERMAL_HEADROOM
|
|
else {
|
|
if (thp_max_cpu_power != 0)
|
|
set_adaptive_cpu_power_limit((unsigned int)
|
|
MAX(thp_max_cpu_power,
|
|
MINIMUM_CPU_POWER));
|
|
else
|
|
set_adaptive_cpu_power_limit(0);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
else {
|
|
if (triggered) {
|
|
triggered = 0;
|
|
tscpu_dprintk("%s Tp %ld, Tc %ld, Pt %d\n", __func__,
|
|
prev_temp, curr_temp,
|
|
total_power);
|
|
|
|
return P_adaptive(0, 0);
|
|
}
|
|
#if THERMAL_HEADROOM
|
|
else {
|
|
if (thp_max_cpu_power != 0)
|
|
set_adaptive_cpu_power_limit((unsigned int)
|
|
MAX(thp_max_cpu_power,
|
|
MINIMUM_CPU_POWER));
|
|
else
|
|
set_adaptive_cpu_power_limit(0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int decide_ttj(void)
|
|
{
|
|
int i = 0;
|
|
int active_cooler_id = -1;
|
|
int ret = 117000; /* highest allowable TJ */
|
|
int temp_cl_dev_adp_cpu_state_active = 0;
|
|
int cur_min_gpu_pwr = (int)mt_gpufreq_get_min_power() + 1;
|
|
int cur_max_gpu_pwr = (int)mt_gpufreq_get_max_power() + 1;
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
static int prev_ttj = 85000;
|
|
|
|
prev_ttj = TARGET_TJ;
|
|
#endif
|
|
#endif
|
|
|
|
for (; i < MAX_CPT_ADAPTIVE_COOLERS; i++) {
|
|
if (cl_dev_adp_cpu_state[i]) {
|
|
ret = MIN(ret, TARGET_TJS[i]);
|
|
temp_cl_dev_adp_cpu_state_active = 1;
|
|
|
|
if (ret == TARGET_TJS[i])
|
|
active_cooler_id = i;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
cl_dev_adp_cpu_state_active = temp_cl_dev_adp_cpu_state_active;
|
|
// TARGET_TJ = ret;
|
|
|
|
#if CONTINUOUS_TM
|
|
if (ctm_on) {
|
|
int curr_tpcb = mtk_thermal_get_temp(MTK_THERMAL_SENSOR_AP);
|
|
|
|
if (ctm_on == 1) {
|
|
TARGET_TJ = MIN(MAX_TARGET_TJ,
|
|
MAX(STEADY_TARGET_TJ,
|
|
(COEF_AE - COEF_BE * (curr_tpcb
|
|
/ 1000))));
|
|
|
|
} else if (ctm_on == 2) {
|
|
/* +++ cATM+ +++ */
|
|
TARGET_TJ = ta_get_ttj();
|
|
/*if userspace cATM+ not ready*/
|
|
if (TARGET_TJ == 0)
|
|
TARGET_TJ = CLATM_INIT_CFG_0_TARGET_TJ;
|
|
/* --- cATM+ --- */
|
|
} else /*ctm_on = 0*/
|
|
TARGET_TJ = ret;
|
|
|
|
current_ETJ = MIN(MAX_EXIT_TJ,
|
|
MAX(STEADY_EXIT_TJ,
|
|
(COEF_AX - COEF_BX * (curr_tpcb
|
|
/ 1000))));
|
|
|
|
/* tscpu_printk("cttj %d cetj %d tpcb %d\n",
|
|
* TARGET_TJ, current_ETJ, curr_tpcb);
|
|
*/
|
|
}
|
|
#endif
|
|
cpu_target_tj = TARGET_TJ;
|
|
#if CONTINUOUS_TM
|
|
cpu_target_offset = TARGET_TJ - current_ETJ;
|
|
#endif
|
|
|
|
TARGET_TJ_HIGH = TARGET_TJ + 1000;
|
|
TARGET_TJ_LOW = TARGET_TJ - 1000;
|
|
|
|
if (active_cooler_id >= 0
|
|
&& MAX_CPT_ADAPTIVE_COOLERS > active_cooler_id) {
|
|
|
|
PACKAGE_THETA_JA_RISE =
|
|
PACKAGE_THETA_JA_RISES[active_cooler_id];
|
|
|
|
PACKAGE_THETA_JA_FALL =
|
|
PACKAGE_THETA_JA_FALLS[active_cooler_id];
|
|
|
|
MINIMUM_CPU_POWER = MINIMUM_CPU_POWERS[active_cooler_id];
|
|
MAXIMUM_CPU_POWER = MAXIMUM_CPU_POWERS[active_cooler_id];
|
|
|
|
/* get GPU min/max power from GPU DVFS should be
|
|
* done when configuring ATM instead of decide_ttj
|
|
*/
|
|
#if 0
|
|
{
|
|
MAXIMUM_GPU_POWER = (int)mt_gpufreq_get_max_power();
|
|
MINIMUM_GPU_POWER = (int)mt_gpufreq_get_min_power();
|
|
tscpu_printk(
|
|
"%s: MAXIMUM_GPU_POWER=%d, MINIMUM_GPU_POWER=%d\n",
|
|
__func__, MAXIMUM_GPU_POWER, MINIMUM_GPU_POWER);
|
|
}
|
|
#else
|
|
MINIMUM_GPU_POWER = MINIMUM_GPU_POWERS[active_cooler_id];
|
|
if (!is_max_gpu_power_specified[active_cooler_id])
|
|
MAXIMUM_GPU_POWERS[active_cooler_id] = cur_max_gpu_pwr;
|
|
else if (MAXIMUM_GPU_POWERS[active_cooler_id] < cur_min_gpu_pwr)
|
|
MAXIMUM_GPU_POWERS[active_cooler_id] = cur_min_gpu_pwr;
|
|
MAXIMUM_GPU_POWER = MAXIMUM_GPU_POWERS[active_cooler_id];
|
|
#endif
|
|
MINIMUM_TOTAL_POWER = MINIMUM_CPU_POWER + MINIMUM_GPU_POWER;
|
|
MAXIMUM_TOTAL_POWER = MAXIMUM_CPU_POWER + MAXIMUM_GPU_POWER;
|
|
|
|
FIRST_STEP_TOTAL_POWER_BUDGET =
|
|
FIRST_STEP_TOTAL_POWER_BUDGETS[active_cooler_id];
|
|
|
|
MINIMUM_BUDGET_CHANGE =
|
|
MINIMUM_BUDGET_CHANGES[active_cooler_id];
|
|
|
|
} else {
|
|
MINIMUM_CPU_POWER = MINIMUM_CPU_POWERS[0];
|
|
MAXIMUM_CPU_POWER = MAXIMUM_CPU_POWERS[0];
|
|
MINIMUM_GPU_POWER = MINIMUM_GPU_POWERS[0];
|
|
if (!is_max_gpu_power_specified[0])
|
|
MAXIMUM_GPU_POWERS[0] = cur_max_gpu_pwr;
|
|
else if (MAXIMUM_GPU_POWERS[0] < cur_min_gpu_pwr)
|
|
MAXIMUM_GPU_POWERS[0] = cur_min_gpu_pwr;
|
|
MAXIMUM_GPU_POWER = MAXIMUM_GPU_POWERS[0];
|
|
}
|
|
|
|
#if THERMAL_HEADROOM
|
|
MAXIMUM_CPU_POWER -= p_Tpcb_correlation *
|
|
MAX((bts_cur_temp - Tpcb_trip_point), 0) / 1000;
|
|
|
|
/* tscpu_printk("max_cpu_pwr %d %d\n",
|
|
* bts_cur_temp, MAXIMUM_CPU_POWER);
|
|
*/
|
|
|
|
/* TODO: use 0 as current P */
|
|
thp_max_cpu_power = (thp_threshold_tj - tscpu_read_curr_temp) *
|
|
thp_p_tj_correlation / 1000 + 0;
|
|
|
|
if (thp_max_cpu_power != 0)
|
|
MAXIMUM_CPU_POWER = MIN(MAXIMUM_CPU_POWER, thp_max_cpu_power);
|
|
|
|
MAXIMUM_CPU_POWER = MAX(MAXIMUM_CPU_POWER, MINIMUM_CPU_POWER);
|
|
|
|
/* tscpu_printk("thp max_cpu_pwr %d %d\n",
|
|
* thp_max_cpu_power, MAXIMUM_CPU_POWER);
|
|
*/
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (prev_ttj != TARGET_TJ)
|
|
atm_update_ttj_to_sspm();
|
|
if (atm_prev_active_atm_cl_id != active_cooler_id) {
|
|
atm_prev_active_atm_cl_id = active_cooler_id;
|
|
atm_update_atm_param_to_sspm();
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
#define CPUFREQ_SEG_CODE_IDX_0 7
|
|
|
|
static void mtk_thermal_get_turbo(void)
|
|
{
|
|
|
|
g_turbo_bin =
|
|
(get_devinfo_with_index(CPUFREQ_SEG_CODE_IDX_0) >> 3) & 0x1;
|
|
|
|
tscpu_printk("%s: turbo: %d\n", __func__, g_turbo_bin);
|
|
}
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static int adp_cpu_get_max_state
|
|
(struct thermal_cooling_device *cdev, unsigned long *state)
|
|
{
|
|
/* tscpu_dprintk("adp_cpu_get_max_state\n"); */
|
|
*state = 1;
|
|
return 0;
|
|
}
|
|
|
|
static int adp_cpu_get_cur_state
|
|
(struct thermal_cooling_device *cdev, unsigned long *state)
|
|
{
|
|
/* tscpu_dprintk("adp_cpu_get_cur_state\n"); */
|
|
*state = cl_dev_adp_cpu_state[(cdev->type[13] - '0')];
|
|
/* *state = cl_dev_adp_cpu_state; */
|
|
return 0;
|
|
}
|
|
|
|
static int adp_cpu_set_cur_state
|
|
(struct thermal_cooling_device *cdev, unsigned long state)
|
|
{
|
|
int ttj = 117000;
|
|
unsigned int prev_active_state = cl_dev_adp_cpu_state_active;
|
|
|
|
cl_dev_adp_cpu_state[(cdev->type[13] - '0')] = state;
|
|
|
|
/* TODO: no exit point can be obtained in mtk_ts_cpu.c */
|
|
ttj = decide_ttj();
|
|
|
|
/* tscpu_dprintk("adp_cpu_set_cur_state[%d] =%d, ttj=%d\n",
|
|
* (cdev->type[13] - '0'), state, ttj);
|
|
*/
|
|
|
|
if (prev_active_state && !cl_dev_adp_cpu_state_active
|
|
&& tscpu_g_curr_temp > current_ETJ)
|
|
tscpu_printk("[Warning] active 1 -> 0 but Tc(%d) > cetj(%d)\n",
|
|
tscpu_g_curr_temp, current_ETJ);
|
|
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled)
|
|
goto exit;
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef FAST_RESPONSE_ATM
|
|
if (active_adp_cooler == (int)(cdev->type[13] - '0')) {
|
|
/* = (NULL == mtk_thermal_get_gpu_loading_fp) ?
|
|
* 0 : mtk_thermal_get_gpu_loading_fp();
|
|
*/
|
|
unsigned int gpu_loading;
|
|
|
|
if (!mtk_get_gpu_loading(&gpu_loading))
|
|
gpu_loading = 0;
|
|
|
|
_adaptive_power_calc(tscpu_g_prev_temp, tscpu_g_curr_temp,
|
|
(unsigned int) gpu_loading);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
exit:
|
|
#endif
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static struct thermal_cooling_device_ops mtktscpu_cooler_adp_cpu_ops = {
|
|
.get_max_state = adp_cpu_get_max_state,
|
|
.get_cur_state = adp_cpu_get_cur_state,
|
|
.set_cur_state = adp_cpu_set_cur_state,
|
|
};
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static int tscpu_read_atm_setting(struct seq_file *m, void *v)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_CPT_ADAPTIVE_COOLERS; i++) {
|
|
seq_printf(m, "%s%02d\n", adaptive_cooler_name, i);
|
|
seq_printf(m, " first_step = %d\n",
|
|
FIRST_STEP_TOTAL_POWER_BUDGETS[i]);
|
|
|
|
seq_printf(m, " theta rise = %d\n",
|
|
PACKAGE_THETA_JA_RISES[i]);
|
|
|
|
seq_printf(m, " theta fall = %d\n",
|
|
PACKAGE_THETA_JA_FALLS[i]);
|
|
|
|
seq_printf(m, " min_budget_change = %d\n",
|
|
MINIMUM_BUDGET_CHANGES[i]);
|
|
|
|
seq_printf(m, " m cpu = %d\n", MINIMUM_CPU_POWERS[i]);
|
|
seq_printf(m, " M cpu = %d\n", MAXIMUM_CPU_POWERS[i]);
|
|
seq_printf(m, " m gpu = %d\n", MINIMUM_GPU_POWERS[i]);
|
|
seq_printf(m, " M gpu = %d\n", MAXIMUM_GPU_POWERS[i]);
|
|
}
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
seq_printf(m, " m vpu = %d\n", MINIMUM_VPU_POWER);
|
|
seq_printf(m, " M vpu = %d\n", MAXIMUM_VPU_POWER);
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
seq_printf(m, " m mdla = %d\n", MINIMUM_MDLA_POWER);
|
|
seq_printf(m, " M mdla = %d\n", MAXIMUM_MDLA_POWER);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_atm_setting
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[128];
|
|
/* char arg_name[32] = {0}; */
|
|
/* int arg_val = 0; */
|
|
int len = 0;
|
|
|
|
int i_id = -1, i_first_step = -1, i_theta_r = -1, i_theta_f = -1,
|
|
i_budget_change = -1, i_min_cpu_pwr = -1, i_max_cpu_pwr = -1,
|
|
i_min_gpu_pwr = -1, i_max_gpu_pwr = -1;
|
|
|
|
#if defined(THERMAL_VPU_SUPPORT)
|
|
#ifdef CONFIG_MTK_APUSYS_SUPPORT
|
|
MINIMUM_VPU_POWER = vpu_power_table[APU_OPP_NUM - 1].power;
|
|
MAXIMUM_VPU_POWER = vpu_power_table[APU_OPP_0].power;
|
|
#else
|
|
MINIMUM_VPU_POWER = vpu_power_table[VPU_OPP_NUM - 1].power;
|
|
MAXIMUM_VPU_POWER = vpu_power_table[VPU_OPP_0].power;
|
|
#endif
|
|
#endif
|
|
#if defined(THERMAL_MDLA_SUPPORT)
|
|
#ifdef CONFIG_MTK_APUSYS_SUPPORT
|
|
MINIMUM_MDLA_POWER = mdla_power_table[APU_OPP_NUM - 1].power;
|
|
MAXIMUM_MDLA_POWER = mdla_power_table[APU_OPP_0].power;
|
|
#else
|
|
MINIMUM_MDLA_POWER = mdla_power_table[MDLA_OPP_NUM - 1].power;
|
|
MAXIMUM_MDLA_POWER = mdla_power_table[MDLA_OPP_0].power;
|
|
#endif
|
|
#endif
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (sscanf(desc, "%d %d %d %d %d %d %d %d %d",
|
|
&i_id, &i_first_step, &i_theta_r, &i_theta_f,
|
|
&i_budget_change, &i_min_cpu_pwr, &i_max_cpu_pwr,
|
|
&i_min_gpu_pwr, &i_max_gpu_pwr) >= 9) {
|
|
|
|
tscpu_printk(
|
|
"%s input %d %d %d %d %d %d %d %d %d\n", __func__,
|
|
i_id, i_first_step,
|
|
i_theta_r, i_theta_f, i_budget_change,
|
|
i_min_cpu_pwr, i_max_cpu_pwr, i_min_gpu_pwr,
|
|
i_max_gpu_pwr);
|
|
|
|
if (i_id >= 0 && i_id < MAX_CPT_ADAPTIVE_COOLERS) {
|
|
if (i_first_step > 0)
|
|
FIRST_STEP_TOTAL_POWER_BUDGETS[i_id] =
|
|
i_first_step;
|
|
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_theta_r > 0)
|
|
PACKAGE_THETA_JA_RISES[i_id] = i_theta_r;
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_theta_f > 0)
|
|
PACKAGE_THETA_JA_FALLS[i_id] = i_theta_f;
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_budget_change >= 0)
|
|
MINIMUM_BUDGET_CHANGES[i_id] = i_budget_change;
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_min_cpu_pwr > 0)
|
|
MINIMUM_CPU_POWERS[i_id] = i_min_cpu_pwr;
|
|
#ifdef ATM_USES_PPM
|
|
else if (i_min_cpu_pwr == 0)
|
|
MINIMUM_CPU_POWERS[i_id] =
|
|
mt_ppm_thermal_get_min_power() + 1;
|
|
/* choose OPP with power "<=" limit */
|
|
#endif
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_max_cpu_pwr > 0)
|
|
MAXIMUM_CPU_POWERS[i_id] = i_max_cpu_pwr;
|
|
#ifdef ATM_USES_PPM
|
|
else if (i_max_cpu_pwr == 0)
|
|
MAXIMUM_CPU_POWERS[i_id] =
|
|
mt_ppm_thermal_get_max_power() + 1;
|
|
/* choose OPP with power "<=" limit */
|
|
#endif
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (i_min_gpu_pwr > 0) {
|
|
/* choose OPP with power "<=" limit */
|
|
int min_gpuopp_power =
|
|
(int) mt_gpufreq_get_min_power() + 1;
|
|
|
|
MINIMUM_GPU_POWERS[i_id] =
|
|
MAX(i_min_gpu_pwr, min_gpuopp_power);
|
|
|
|
} else if (i_min_gpu_pwr == 0)
|
|
MINIMUM_GPU_POWERS[i_id] =
|
|
(int) mt_gpufreq_get_min_power() + 1;
|
|
/* choose OPP with power "<=" limit */
|
|
else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
|
|
if (i_max_gpu_pwr > 0) {
|
|
/* choose OPP with power "<=" limit */
|
|
int min_gpuopp_power =
|
|
(int) mt_gpufreq_get_min_power() + 1;
|
|
|
|
MAXIMUM_GPU_POWERS[i_id] =
|
|
MAX(i_max_gpu_pwr, min_gpuopp_power);
|
|
is_max_gpu_power_specified[i_id] = 1;
|
|
} else if (i_max_gpu_pwr == 0) {
|
|
/* choose OPP with power "<=" limit */
|
|
MAXIMUM_GPU_POWERS[i_id] =
|
|
(int) mt_gpufreq_get_max_power() + 1;
|
|
is_max_gpu_power_specified[i_id] = 0;
|
|
} else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
|
|
active_adp_cooler = i_id;
|
|
|
|
/* --- SPA parameters --- */
|
|
thermal_spa_t.t_spa_Tpolicy_info.min_cpu_power[i_id] =
|
|
MINIMUM_CPU_POWERS[i_id];
|
|
|
|
thermal_spa_t.t_spa_Tpolicy_info.min_gpu_power[i_id] =
|
|
MINIMUM_GPU_POWERS[i_id];
|
|
|
|
tscpu_printk(
|
|
"tscpu_write_dtm_setting applied %d %d %d %d %d %d %d %d %d\n",
|
|
i_id,
|
|
FIRST_STEP_TOTAL_POWER_BUDGETS[i_id],
|
|
PACKAGE_THETA_JA_RISES[i_id],
|
|
PACKAGE_THETA_JA_FALLS[i_id],
|
|
MINIMUM_BUDGET_CHANGES[i_id],
|
|
MINIMUM_CPU_POWERS[i_id],
|
|
MAXIMUM_CPU_POWERS[i_id],
|
|
MINIMUM_GPU_POWERS[i_id],
|
|
MAXIMUM_GPU_POWERS[i_id]);
|
|
} else {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
|
|
return count;
|
|
}
|
|
tscpu_dprintk("tscpu_write_dtm_setting bad argument\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int tscpu_read_gpu_threshold(struct seq_file *m, void *v)
|
|
{
|
|
seq_printf(m, "H %d L %d\n", GPU_L_H_TRIP, GPU_L_L_TRIP);
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_gpu_threshold
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[128];
|
|
int len = 0;
|
|
|
|
int gpu_h = -1, gpu_l = -1;
|
|
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (sscanf(desc, "%d %d", &gpu_h, &gpu_l) >= 2) {
|
|
tscpu_printk("%s input %d %d\n", __func__,
|
|
gpu_h, gpu_l);
|
|
|
|
if ((gpu_h > 0) && (gpu_l > 0) && (gpu_h > gpu_l)) {
|
|
GPU_L_H_TRIP = gpu_h;
|
|
GPU_L_L_TRIP = gpu_l;
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
atm_update_cg_alloc_param_to_sspm();
|
|
#endif
|
|
#endif
|
|
|
|
tscpu_printk(
|
|
"%s applied %d %d\n", __func__,
|
|
GPU_L_H_TRIP, GPU_L_L_TRIP);
|
|
} else {
|
|
tscpu_dprintk(
|
|
"%s out of range\n", __func__);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
tscpu_dprintk("%s bad argument\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* +ASC+ */
|
|
static int tscpu_read_atm(struct seq_file *m, void *v)
|
|
{
|
|
|
|
seq_printf(m, "[%s] ver = %d\n", __func__, tscpu_atm);
|
|
seq_printf(m, "tt_ratio_high_rise = %d\n", tt_ratio_high_rise);
|
|
seq_printf(m, "tt_ratio_high_fall = %d\n", tt_ratio_high_fall);
|
|
seq_printf(m, "tt_ratio_low_rise = %d\n", tt_ratio_low_rise);
|
|
seq_printf(m, "tt_ratio_low_fall = %d\n", tt_ratio_low_fall);
|
|
seq_printf(m, "tp_ratio_high_rise = %d\n", tp_ratio_high_rise);
|
|
seq_printf(m, "tp_ratio_high_fall = %d\n", tp_ratio_high_fall);
|
|
seq_printf(m, "tp_ratio_low_rise = %d\n", tp_ratio_low_rise);
|
|
seq_printf(m, "tp_ratio_low_fall = %d\n", tp_ratio_low_fall);
|
|
|
|
#ifdef CONFIG_MACH_MT8168
|
|
dump_power_table();
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_atm
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[128];
|
|
int atm_ver;
|
|
int tmp_tt_ratio_high_rise;
|
|
int tmp_tt_ratio_high_fall;
|
|
int tmp_tt_ratio_low_rise;
|
|
int tmp_tt_ratio_low_fall;
|
|
int tmp_tp_ratio_high_rise;
|
|
int tmp_tp_ratio_high_fall;
|
|
int tmp_tp_ratio_low_rise;
|
|
int tmp_tp_ratio_low_fall;
|
|
int len = 0;
|
|
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (sscanf(desc, "%d %d %d %d %d %d %d %d %d ",
|
|
&atm_ver, &tmp_tt_ratio_high_rise, &tmp_tt_ratio_high_fall,
|
|
&tmp_tt_ratio_low_rise, &tmp_tt_ratio_low_fall,
|
|
&tmp_tp_ratio_high_rise, &tmp_tp_ratio_high_fall,
|
|
&tmp_tp_ratio_low_rise, &tmp_tp_ratio_low_fall) == 9)
|
|
/* if (5 <= sscanf(desc, "%d %d %d %d %d", &log_switch, &hot,
|
|
* &normal, &low, &lv_offset))
|
|
*/
|
|
{
|
|
tscpu_atm = atm_ver;
|
|
tt_ratio_high_rise = tmp_tt_ratio_high_rise;
|
|
tt_ratio_high_fall = tmp_tt_ratio_high_fall;
|
|
tt_ratio_low_rise = tmp_tt_ratio_low_rise;
|
|
tt_ratio_low_fall = tmp_tt_ratio_low_fall;
|
|
tp_ratio_high_rise = tmp_tp_ratio_high_rise;
|
|
tp_ratio_high_fall = tmp_tp_ratio_high_fall;
|
|
tp_ratio_low_rise = tmp_tp_ratio_low_rise;
|
|
tp_ratio_low_fall = tmp_tp_ratio_low_fall;
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
if (tscpu_atm == 3)
|
|
_adaptive_power_calc = _adaptive_power_ppb;
|
|
else
|
|
_adaptive_power_calc = _adaptive_power;
|
|
#endif
|
|
|
|
return count;
|
|
}
|
|
tscpu_printk("%s bad argument\n", __func__);
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
/* -ASC- */
|
|
#if THERMAL_HEADROOM
|
|
static int tscpu_read_thp(struct seq_file *m, void *v)
|
|
{
|
|
seq_printf(m, "Tpcb pt coef %d\n", p_Tpcb_correlation);
|
|
seq_printf(m, "Tpcb threshold %d\n", Tpcb_trip_point);
|
|
seq_printf(m, "Tj pt coef %d\n", thp_p_tj_correlation);
|
|
seq_printf(m, "thp tj threshold %d\n", thp_threshold_tj);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_thp
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[128];
|
|
int len = 0;
|
|
int tpcb_coef = -1, tpcb_trip = -1, thp_coef = -1, thp_threshold = -1;
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (sscanf(desc, "%d %d %d %d", &tpcb_coef, &tpcb_trip, &thp_coef,
|
|
&thp_threshold) >= 4) {
|
|
tscpu_printk("%s input %d %d %d %d\n", __func__,
|
|
tpcb_coef, tpcb_trip, thp_coef, thp_threshold);
|
|
|
|
p_Tpcb_correlation = tpcb_coef;
|
|
Tpcb_trip_point = tpcb_trip;
|
|
thp_p_tj_correlation = thp_coef;
|
|
thp_threshold_tj = thp_threshold;
|
|
|
|
return count;
|
|
}
|
|
tscpu_dprintk("%s bad argument\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#if CONTINUOUS_TM
|
|
static int tscpu_read_ctm(struct seq_file *m, void *v)
|
|
{
|
|
seq_printf(m, "ctm %d\n", ctm_on);
|
|
seq_printf(m, "Target Tj 0 %d\n", MAX_TARGET_TJ);
|
|
seq_printf(m, "Target Tj 2 %d\n", STEADY_TARGET_TJ);
|
|
seq_printf(m, "Tpcb 1 %d\n", TRIP_TPCB);
|
|
seq_printf(m, "Tpcb 2 %d\n", STEADY_TARGET_TPCB);
|
|
seq_printf(m, "Exit Tj 0 %d\n", MAX_EXIT_TJ);
|
|
seq_printf(m, "Exit Tj 2 %d\n", STEADY_EXIT_TJ);
|
|
seq_printf(m, "Enter_a %d\n", COEF_AE);
|
|
seq_printf(m, "Enter_b %d\n", COEF_BE);
|
|
seq_printf(m, "Exit_a %d\n", COEF_AX);
|
|
seq_printf(m, "Exit_b %d\n", COEF_BX);
|
|
|
|
/* +++ cATM+ parameters +++ */
|
|
seq_printf(m, "K_TT %d\n", K_TT);
|
|
seq_printf(m, "MAX_K_SUM_TT %d\n", MAX_K_SUM_TT);
|
|
seq_printf(m, "K_SUM_TT_LOW %d\n", K_SUM_TT_LOW);
|
|
seq_printf(m, "K_SUM_TT_HIGH %d\n", K_SUM_TT_HIGH);
|
|
seq_printf(m, "MIN_SUM_TT %d\n", MIN_SUM_TT);
|
|
seq_printf(m, "MAX_SUM_TT %d\n", MAX_SUM_TT);
|
|
seq_printf(m, "MIN_TTJ %d\n", MIN_TTJ);
|
|
seq_printf(m, "CATMP_STEADY_TTJ_DELTA %d\n", CATMP_STEADY_TTJ_DELTA);
|
|
/* --- cATM+ parameters --- */
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
seq_printf(m, "TPCB_EXTEND %d\n", TPCB_EXTEND);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_ctm(
|
|
struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[256];
|
|
int len = 0;
|
|
int t_ctm_on = -1, t_MAX_TARGET_TJ = -1, t_STEADY_TARGET_TJ = -1,
|
|
t_TRIP_TPCB = -1, t_STEADY_TARGET_TPCB = -1, t_MAX_EXIT_TJ = -1,
|
|
t_STEADY_EXIT_TJ = -1, t_COEF_AE = -1, t_COEF_BE = -1,
|
|
t_COEF_AX = -1, t_COEF_BX = -1, t_K_SUM_TT_HIGH = -1,
|
|
t_K_SUM_TT_LOW = -1, t_CATMP_STEADY_TTJ_DELTA = -1,
|
|
t_TPCB_EXTEND = -1;
|
|
int scan_count = 0;
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
|
|
scan_count =
|
|
sscanf(desc, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
|
|
&t_ctm_on, &t_MAX_TARGET_TJ, &t_STEADY_TARGET_TJ, &t_TRIP_TPCB,
|
|
&t_STEADY_TARGET_TPCB, &t_MAX_EXIT_TJ, &t_STEADY_EXIT_TJ,
|
|
&t_COEF_AE, &t_COEF_BE, &t_COEF_AX, &t_COEF_BX,
|
|
&t_K_SUM_TT_HIGH, &t_K_SUM_TT_LOW, &t_CATMP_STEADY_TTJ_DELTA,
|
|
&t_TPCB_EXTEND);
|
|
|
|
if (scan_count >= 11) {
|
|
tscpu_printk("%s input %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
__func__, t_ctm_on, t_MAX_TARGET_TJ, t_STEADY_TARGET_TJ,
|
|
t_TRIP_TPCB, t_STEADY_TARGET_TPCB,
|
|
t_MAX_EXIT_TJ, t_STEADY_EXIT_TJ,
|
|
t_COEF_AE, t_COEF_BE, t_COEF_AX, t_COEF_BX,
|
|
t_K_SUM_TT_HIGH, t_K_SUM_TT_LOW,
|
|
t_CATMP_STEADY_TTJ_DELTA,
|
|
t_TPCB_EXTEND);
|
|
|
|
if (t_ctm_on < 0 || t_ctm_on > 2) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_MAX_TARGET_TJ < -20000 || t_MAX_TARGET_TJ > 200000) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_STEADY_TARGET_TJ < -20000
|
|
|| t_STEADY_TARGET_TJ > 200000){
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_TRIP_TPCB < -20000 || t_TRIP_TPCB > 200000) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_STEADY_TARGET_TPCB < -20000
|
|
|| t_STEADY_TARGET_TPCB > 200000) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_MAX_EXIT_TJ < -20000 || t_MAX_EXIT_TJ > 200000) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_STEADY_EXIT_TJ < -20000 || t_STEADY_EXIT_TJ > 200000) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
if (t_COEF_AE < 0 || t_COEF_BE < 0
|
|
|| t_COEF_AX < 0 || t_COEF_BX < 0) {
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__,
|
|
DB_OPT_DEFAULT,
|
|
__func__,
|
|
"Wrong thermal policy");
|
|
#endif
|
|
}
|
|
/* no parameter checking here */
|
|
ctm_on = t_ctm_on; /* 2: cATM+, 1: cATMv1, 0: off */
|
|
|
|
MAX_TARGET_TJ = t_MAX_TARGET_TJ;
|
|
STEADY_TARGET_TJ = t_STEADY_TARGET_TJ;
|
|
TRIP_TPCB = t_TRIP_TPCB;
|
|
STEADY_TARGET_TPCB = t_STEADY_TARGET_TPCB;
|
|
MAX_EXIT_TJ = t_MAX_EXIT_TJ;
|
|
STEADY_EXIT_TJ = t_STEADY_EXIT_TJ;
|
|
|
|
COEF_AE = t_COEF_AE;
|
|
COEF_BE = t_COEF_BE;
|
|
COEF_AX = t_COEF_AX;
|
|
COEF_BX = t_COEF_BX;
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
if (g_turbo_bin && (STEADY_TARGET_TPCB >= 52000)) {
|
|
if (t_TPCB_EXTEND > 0 && t_TPCB_EXTEND < 10000) {
|
|
TRIP_TPCB += t_TPCB_EXTEND;
|
|
STEADY_TARGET_TPCB += t_TPCB_EXTEND;
|
|
COEF_AE = STEADY_TARGET_TJ +
|
|
(STEADY_TARGET_TPCB * COEF_BE) / 1000;
|
|
COEF_AX = STEADY_EXIT_TJ +
|
|
(STEADY_TARGET_TPCB * COEF_BX) / 1000;
|
|
TPCB_EXTEND = t_TPCB_EXTEND;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* +++ cATM+ parameters +++ */
|
|
if (ctm_on == 2) {
|
|
if (t_K_SUM_TT_HIGH >= 0
|
|
&& t_K_SUM_TT_HIGH < MAX_K_SUM_TT)
|
|
K_SUM_TT_HIGH = t_K_SUM_TT_HIGH;
|
|
|
|
if (t_K_SUM_TT_LOW >= 0
|
|
&& t_K_SUM_TT_LOW < MAX_K_SUM_TT)
|
|
K_SUM_TT_LOW = t_K_SUM_TT_LOW;
|
|
|
|
if (t_CATMP_STEADY_TTJ_DELTA >= 0)
|
|
CATMP_STEADY_TTJ_DELTA =
|
|
t_CATMP_STEADY_TTJ_DELTA;
|
|
|
|
catmplus_update_params();
|
|
}
|
|
/* --- cATM+ parameters --- */
|
|
|
|
/* --- SPA parameters --- */
|
|
thermal_spa_t.t_spa_Tpolicy_info.steady_target_tj =
|
|
STEADY_TARGET_TJ;
|
|
|
|
thermal_spa_t.t_spa_Tpolicy_info.steady_exit_tj =
|
|
STEADY_EXIT_TJ;
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
atm_update_catm_param_to_sspm();
|
|
#endif
|
|
#endif
|
|
|
|
return count;
|
|
}
|
|
|
|
tscpu_dprintk("%s bad argument\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
static int tscpu_read_phpb(struct seq_file *m, void *v)
|
|
{
|
|
int i;
|
|
struct phpb_param *p;
|
|
|
|
for (i = 0; i < NR_PHPB_PARAMS; i++) {
|
|
p = &phpb_params[i];
|
|
seq_printf(m, "[%s] %d %d\n", p->type, p->tt, p->tp);
|
|
}
|
|
seq_printf(m, "[common] %d\n", phpb_theta_max);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_write_phpb(struct file *file, const char __user *buffer,
|
|
size_t count, loff_t *data)
|
|
{
|
|
char *buf, *ori_buf;
|
|
int i, tt, tp;
|
|
int __theta;
|
|
int ret = -EINVAL;
|
|
struct phpb_param *p;
|
|
|
|
tscpu_printk("%s, input str len = %zu\n", __func__, count);
|
|
|
|
if (count >= 128 || count < 1)
|
|
return -EINVAL;
|
|
|
|
buf = kmalloc(count + 1, GFP_KERNEL);
|
|
if (buf == NULL)
|
|
return -EFAULT;
|
|
ori_buf = buf;
|
|
|
|
if (copy_from_user(buf, buffer, count)) {
|
|
ret = -EFAULT;
|
|
goto exit;
|
|
}
|
|
|
|
buf[count] = '\0';
|
|
|
|
if (strstr(buf, " ") == NULL)
|
|
goto exit;
|
|
|
|
for (i = 0; i < NR_PHPB_PARAMS; i++) {
|
|
p = &phpb_params[i];
|
|
if (strstr(buf, p->type))
|
|
break;
|
|
}
|
|
|
|
if (i < NR_PHPB_PARAMS) {
|
|
strsep(&buf, " ");
|
|
if (sscanf(buf, "%d %d", &tt, &tp) != 2)
|
|
goto exit;
|
|
/* TODO verify values */
|
|
p->tt = tt;
|
|
p->tp = tp;
|
|
} else {
|
|
if (strstr(buf, "common") == NULL)
|
|
goto exit;
|
|
strsep(&buf, " ");
|
|
if (kstrtoint(buf, 10, &__theta) != 0)
|
|
goto exit;
|
|
|
|
if (__theta < phpb_theta_min)
|
|
goto exit;
|
|
phpb_theta_max = __theta;
|
|
}
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
atm_update_ppb_param_to_sspm();
|
|
#endif
|
|
#endif
|
|
|
|
ret = count;
|
|
|
|
exit:
|
|
kfree(ori_buf);
|
|
return ret;
|
|
}
|
|
|
|
static void phpb_params_init(void)
|
|
{
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
phpb_params[PHPB_PARAM_CPU].tt = CLATM_INIT_CFG_PHPB_CPU_TT;
|
|
phpb_params[PHPB_PARAM_CPU].tp = CLATM_INIT_CFG_PHPB_CPU_TP;
|
|
#else
|
|
phpb_params[PHPB_PARAM_CPU].tt = 20;
|
|
phpb_params[PHPB_PARAM_CPU].tp = 20;
|
|
#endif
|
|
strncpy(phpb_params[PHPB_PARAM_CPU].type, "cpu", 3);
|
|
phpb_params[PHPB_PARAM_CPU].type[3] = '\0';
|
|
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
phpb_params[PHPB_PARAM_GPU].tt = CLATM_INIT_CFG_PHPB_GPU_TT;
|
|
phpb_params[PHPB_PARAM_GPU].tp = CLATM_INIT_CFG_PHPB_GPU_TP;
|
|
#else
|
|
phpb_params[PHPB_PARAM_GPU].tt = 80;
|
|
phpb_params[PHPB_PARAM_GPU].tp = 80;
|
|
#endif
|
|
strncpy(phpb_params[PHPB_PARAM_GPU].type, "gpu", 3);
|
|
phpb_params[PHPB_PARAM_GPU].type[3] = '\0';
|
|
}
|
|
#endif /* PRECISE_HYBRID_POWER_BUDGET */
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
static int atm_sspm_read(struct seq_file *m, void *v)
|
|
{
|
|
struct thermal_ipi_data thermal_data;
|
|
static int s_cpu_limit, s_gpu_limit;
|
|
|
|
if (atm_sspm_enabled == 1) {
|
|
int cpu_limit, gpu_limit;
|
|
|
|
if (atm_to_sspm(THERMAL_IPI_GET_ATM_CPU_LIMIT, 1,
|
|
&thermal_data, &cpu_limit) >= 0)
|
|
s_cpu_limit = cpu_limit;
|
|
|
|
if (atm_to_sspm(THERMAL_IPI_GET_ATM_GPU_LIMIT, 1,
|
|
&thermal_data, &gpu_limit) >= 0)
|
|
s_gpu_limit = gpu_limit;
|
|
} else {
|
|
s_cpu_limit = 0;
|
|
s_gpu_limit = 0;
|
|
}
|
|
seq_printf(m, "%d,%d,%d\n", atm_sspm_enabled, s_cpu_limit, s_gpu_limit);
|
|
seq_printf(m, "atm sspm %d\n", atm_sspm_enabled);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t atm_sspm_write
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[32];
|
|
int len = 0;
|
|
int t_enabled = -1;
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return -EFAULT;
|
|
|
|
desc[len] = '\0';
|
|
|
|
if (kstrtoint(desc, 10, &t_enabled) == 0) {
|
|
tscpu_printk("%s en %d\n", __func__, t_enabled);
|
|
|
|
if (t_enabled == 0) {
|
|
atm_enable_atm_in_sspm(0);
|
|
atm_sspm_enabled = 0;
|
|
} else if (t_enabled == 1) {
|
|
int ret = 0;
|
|
int cur_min_gpu_pwr =
|
|
(int)mt_gpufreq_get_min_power() + 1;
|
|
int cur_max_gpu_pwr =
|
|
(int)mt_gpufreq_get_max_power() + 1;
|
|
|
|
/* Fix the problem that mMc mMg not updated
|
|
* when trip point is not reached.
|
|
*/
|
|
MINIMUM_CPU_POWER = MINIMUM_CPU_POWERS[0];
|
|
MAXIMUM_CPU_POWER = MAXIMUM_CPU_POWERS[0];
|
|
MINIMUM_GPU_POWER = MINIMUM_GPU_POWERS[0];
|
|
if (!is_max_gpu_power_specified[0])
|
|
MAXIMUM_GPU_POWERS[0] = cur_max_gpu_pwr;
|
|
else if (MAXIMUM_GPU_POWERS[0] < cur_min_gpu_pwr)
|
|
MAXIMUM_GPU_POWERS[0] = cur_min_gpu_pwr;
|
|
MAXIMUM_GPU_POWER = MAXIMUM_GPU_POWERS[0];
|
|
|
|
ret = atm_update_atm_param_to_sspm();
|
|
if (ret == -2) {
|
|
tscpu_printk("%s atm in sspm not supported!\n",
|
|
__func__);
|
|
|
|
return count;
|
|
}
|
|
atm_update_ppb_param_to_sspm();
|
|
atm_update_catm_param_to_sspm();
|
|
atm_update_cg_alloc_param_to_sspm();
|
|
atm_update_ttj_to_sspm();
|
|
atm_enable_atm_in_sspm(1);
|
|
atm_sspm_enabled = 1;
|
|
set_adaptive_cpu_power_limit(0);
|
|
set_adaptive_gpu_power_limit(0);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
tscpu_printk("%s bad argument\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* CPT_ADAPTIVE_AP_COOLER */
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
static int tscpu_atm_setting_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_atm_setting, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_atm_setting_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_atm_setting_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_atm_setting,
|
|
.release = single_release,
|
|
};
|
|
|
|
#if CLATM_USE_MIN_CPU_OPP
|
|
static int tscpu_atm_cpu_min_opp_read(struct seq_file *m, void *v)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < MAX_CPT_ADAPTIVE_COOLERS; i++) {
|
|
seq_printf(m, "%s%02d\n", adaptive_cooler_name, i);
|
|
seq_printf(m, "mode = %d\n", g_c_min_opp.mode[i]);
|
|
|
|
seq_printf(m, "min CPU power = %d\n",
|
|
g_c_min_opp.min_CPU_power[i]);
|
|
|
|
seq_printf(m, "min CPU power from opp = %d\n",
|
|
g_c_min_opp.min_CPU_power_from_opp[i]);
|
|
|
|
seq_printf(m, "current min cpu power = %d\n",
|
|
MINIMUM_CPU_POWERS[i]);
|
|
|
|
for (j = 0; j < NR_PPM_CLUSTERS; j++) {
|
|
seq_printf(m, "cluster%02d core %d, freq_idx %d\n",
|
|
j, g_c_min_opp.cpu_opp_set[i][j].core_num,
|
|
g_c_min_opp.cpu_opp_set[i][j].freq_idx);
|
|
}
|
|
seq_puts(m, "\n");
|
|
}
|
|
|
|
seq_puts(m, "Two commands\n");
|
|
seq_puts(m, "1. Set a set of min cpu opp\n");
|
|
seq_puts(m, " echo [ATM_ID] [N_CLUSTER] [CORE_0] [F_IDX0] [CORE_1] [F_IDX1]");
|
|
seq_puts(m, " [CORE_2] [F_IDX2] > /proc/driver/thermal/clatm_cpu_min_opp\n");
|
|
seq_puts(m, " ATM_ID: 0:cpu_adaptive_00, 1: cpu_adaptive_01, 2: cpu_adaptive_02\n");
|
|
seq_puts(m, " N_CLUSTER: number of clusters in this platform\n");
|
|
seq_puts(m, " CORE_0: number of cores in cluster 0\n");
|
|
seq_puts(m, " F_IDX_0: frequency opp index in cluster 0\n");
|
|
seq_puts(m, " and etc.\n");
|
|
seq_puts(m, "2. Change mode\n");
|
|
seq_puts(m, " echo chmod [MODE_ID] > /proc/driver/thermal/clatm_cpu_min_opp\n");
|
|
seq_puts(m, " MODE_ID:\n");
|
|
seq_puts(m, " 1: Use a conventional min cpu power budget\n");
|
|
seq_puts(m, " 2: Use a set of min cpu opp\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t tscpu_atm_cpu_min_opp_write
|
|
(struct file *file, const char __user *buffer, size_t count, loff_t *data)
|
|
{
|
|
char desc[128], cmd[20];
|
|
int i, len = 0, arg;
|
|
int atm_id, num_cluster, core[3],
|
|
freq_idx[3];
|
|
|
|
len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
|
|
if (copy_from_user(desc, buffer, len))
|
|
return 0;
|
|
|
|
desc[len] = '\0';
|
|
if (sscanf(desc, "%d %d %d %d %d %d %d %d", &atm_id, &num_cluster,
|
|
&core[0], &freq_idx[0], &core[1], &freq_idx[1],
|
|
&core[2], &freq_idx[2]) == 8) {
|
|
if (atm_id < 0 || atm_id >= MAX_CPT_ADAPTIVE_COOLERS) {
|
|
tscpu_printk("Bad arg: atm_id error\n");
|
|
goto BAD_ARG;
|
|
}
|
|
|
|
if (num_cluster != NR_PPM_CLUSTERS) {
|
|
g_c_min_opp.mode[atm_id] = 0;
|
|
tscpu_printk("Bad arg: Total number of clusters doesn't match\n");
|
|
goto BAD_ARG;
|
|
}
|
|
|
|
for (i = 0; i < NR_PPM_CLUSTERS; i++) {
|
|
g_c_min_opp.cpu_opp_set[atm_id][i].core_num = core[i];
|
|
g_c_min_opp.cpu_opp_set[atm_id][i].freq_idx
|
|
= freq_idx[i];
|
|
}
|
|
|
|
if (g_c_min_opp.min_CPU_power[atm_id] == 0)
|
|
g_c_min_opp.min_CPU_power[atm_id] =
|
|
MINIMUM_CPU_POWERS[atm_id];
|
|
|
|
g_c_min_opp.min_CPU_power_from_opp[atm_id] =
|
|
ppm_find_pwr_idx(g_c_min_opp.cpu_opp_set[atm_id]);
|
|
if (g_c_min_opp.min_CPU_power_from_opp[atm_id] == -1) {
|
|
g_c_min_opp.mode[atm_id] = 0;
|
|
tscpu_printk("Error: When transfer a CPU opp to a power budget\n");
|
|
goto BAD_ARG;
|
|
}
|
|
|
|
g_c_min_opp.min_CPU_power_from_opp[atm_id] += 1;
|
|
MINIMUM_CPU_POWERS[atm_id] =
|
|
g_c_min_opp.min_CPU_power_from_opp[atm_id];
|
|
thermal_spa_t.t_spa_Tpolicy_info.min_cpu_power[atm_id] =
|
|
g_c_min_opp.min_CPU_power_from_opp[atm_id];
|
|
|
|
g_c_min_opp.mode[atm_id] = 2;
|
|
|
|
return count;
|
|
} else if (sscanf(desc, "%19s %d", cmd, &arg) == 2) {
|
|
if ((strncmp(cmd, "chmod", 5) == 0)) {
|
|
if (arg != 1 && arg != 2) {
|
|
tscpu_printk("Bad arg: mode should only be 1 and 2\n");
|
|
goto BAD_ARG;
|
|
}
|
|
|
|
for (i = 0; i < MAX_CPT_ADAPTIVE_COOLERS; i++) {
|
|
if (g_c_min_opp.mode[i] == 0) {
|
|
tscpu_printk("Skip cpu_adaptive_%d, because didn't initialized\n",
|
|
i);
|
|
continue;
|
|
}
|
|
if (arg == 1) {
|
|
if (g_c_min_opp.min_CPU_power[i] == 0)
|
|
continue;
|
|
|
|
MINIMUM_CPU_POWERS[i] =
|
|
g_c_min_opp.min_CPU_power[i];
|
|
thermal_spa_t.t_spa_Tpolicy_info.min_cpu_power[i] =
|
|
g_c_min_opp.min_CPU_power[i];
|
|
} else if (arg == 2) {
|
|
MINIMUM_CPU_POWERS[i] =
|
|
g_c_min_opp.min_CPU_power_from_opp[i];
|
|
thermal_spa_t.t_spa_Tpolicy_info.min_cpu_power[i] =
|
|
g_c_min_opp.min_CPU_power_from_opp[i];
|
|
}
|
|
|
|
g_c_min_opp.mode[i] = arg;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
tscpu_printk("Bad arg: No this command\n");
|
|
goto BAD_ARG;
|
|
}
|
|
BAD_ARG:
|
|
tscpu_printk("%s,%d: bad argument, %s\n", __func__, __LINE__, desc);
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int tscpu_atm_cpu_min_opp_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_atm_cpu_min_opp_read, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_atm_cpu_min_opp_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_atm_cpu_min_opp_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_atm_cpu_min_opp_write,
|
|
.release = single_release,
|
|
};
|
|
#endif
|
|
|
|
static int tscpu_gpu_threshold_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_gpu_threshold, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_gpu_threshold_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_gpu_threshold_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_gpu_threshold,
|
|
.release = single_release,
|
|
};
|
|
|
|
/* +ASC+ */
|
|
static int tscpu_open_atm(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_atm, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_atm_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_open_atm,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_atm,
|
|
.release = single_release,
|
|
};
|
|
/* -ASC- */
|
|
|
|
#if THERMAL_HEADROOM
|
|
static int tscpu_thp_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_thp, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_thp_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_thp_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_thp,
|
|
.release = single_release,
|
|
};
|
|
#endif
|
|
|
|
#if CONTINUOUS_TM
|
|
static int tscpu_ctm_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_ctm, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_ctm_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_ctm_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_ctm,
|
|
.release = single_release,
|
|
};
|
|
#endif /* CONTINUOUS_TM */
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
static int tscpu_phpb_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, tscpu_read_phpb, NULL);
|
|
}
|
|
|
|
static const struct file_operations mtktscpu_phpb_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = tscpu_phpb_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = tscpu_write_phpb,
|
|
.release = single_release,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
static int atm_sspm_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, atm_sspm_read, NULL);
|
|
}
|
|
|
|
static const struct file_operations atm_sspm_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = atm_sspm_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.write = atm_sspm_write,
|
|
.release = single_release,
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* CPT_ADAPTIVE_AP_COOLER */
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
static void phpb_init(struct proc_dir_entry *mtktscpu_dir)
|
|
{
|
|
struct proc_dir_entry *entry;
|
|
|
|
phpb_params_init();
|
|
|
|
entry = proc_create("clphpb", 0664,
|
|
mtktscpu_dir, &mtktscpu_phpb_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
}
|
|
#endif
|
|
|
|
static void tscpu_cooler_create_fs(void)
|
|
{
|
|
struct proc_dir_entry *entry = NULL;
|
|
struct proc_dir_entry *mtktscpu_dir = NULL;
|
|
|
|
mtktscpu_dir = mtk_thermal_get_proc_drv_therm_dir_entry();
|
|
if (!mtktscpu_dir) {
|
|
tscpu_printk("[%s]: mkdir /proc/driver/thermal failed\n",
|
|
__func__);
|
|
|
|
} else {
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
entry = proc_create("clatm_setting",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_atm_setting_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
|
|
#if CLATM_USE_MIN_CPU_OPP
|
|
entry = proc_create("clatm_cpu_min_opp",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_atm_cpu_min_opp_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif
|
|
|
|
entry = proc_create("clatm_gpu_threshold",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_gpu_threshold_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif /* #if CPT_ADAPTIVE_AP_COOLER */
|
|
|
|
|
|
/* +ASC+ */
|
|
entry = proc_create("clatm",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_atm_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
/* -ASC- */
|
|
|
|
#if THERMAL_HEADROOM
|
|
entry = proc_create("clthp",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_thp_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif
|
|
|
|
#if CONTINUOUS_TM
|
|
entry = proc_create("clctm",
|
|
0664,
|
|
mtktscpu_dir, &mtktscpu_ctm_fops);
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
phpb_init(mtktscpu_dir);
|
|
#endif
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
entry = proc_create("clatm_sspm",
|
|
0664,
|
|
mtktscpu_dir, &atm_sspm_fops);
|
|
|
|
if (entry)
|
|
proc_set_user(entry, uid, gid);
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
#ifdef FAST_RESPONSE_ATM
|
|
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
void atm_cancel_hrtimer(void)
|
|
{
|
|
hrtimer_try_to_cancel(&atm_hrtimer);
|
|
}
|
|
|
|
void atm_restart_hrtimer(void)
|
|
{
|
|
ktime_t ktime;
|
|
|
|
ktime = ktime_set(0, atm_hrtimer_polling_delay);
|
|
hrtimer_start(&atm_hrtimer, ktime, HRTIMER_MODE_REL);
|
|
#ifdef ATM_CFG_PROFILING
|
|
atm_resumed = 1;
|
|
#endif
|
|
}
|
|
|
|
static unsigned long atm_get_timeout_time(int curr_temp)
|
|
{
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
return atm_hrtimer_polling_delay;
|
|
#else
|
|
/*
|
|
* curr_temp can't smaller than -30'C
|
|
*/
|
|
curr_temp = (curr_temp < -30000) ? -30000 : curr_temp;
|
|
|
|
|
|
if (curr_temp >= 65000)
|
|
return atm_hrtimer_polling_delay;
|
|
else
|
|
return (atm_hrtimer_polling_delay
|
|
<< ((81394 - curr_temp) >> 14));
|
|
#endif
|
|
}
|
|
|
|
#elif KRTATM_TIMER == KRTATM_NORMAL
|
|
|
|
void atm_cancel_hrtimer(void)
|
|
{
|
|
}
|
|
|
|
void atm_restart_hrtimer(void)
|
|
{
|
|
}
|
|
|
|
static unsigned long atm_get_timeout_time(int curr_temp)
|
|
{
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
return atm_timer_polling_delay;
|
|
#else
|
|
|
|
if (curr_temp >= polling_trip_temp0)
|
|
return atm_timer_polling_delay / polling_factor0;
|
|
else if (curr_temp >= polling_trip_temp1)
|
|
return atm_timer_polling_delay;
|
|
else if (curr_temp >= polling_trip_temp2)
|
|
return atm_timer_polling_delay * polling_factor1;
|
|
else
|
|
return atm_timer_polling_delay * polling_factor2;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
static enum hrtimer_restart atm_loop(struct hrtimer *timer)
|
|
{
|
|
ktime_t ktime;
|
|
#elif KRTATM_TIMER == KRTATM_NORMAL
|
|
static void atm_loop(struct timer_list *t)
|
|
{
|
|
#endif
|
|
int temp;
|
|
#ifdef ENALBE_UART_LIMIT
|
|
#if ENALBE_UART_LIMIT
|
|
static int hasDisabled;
|
|
#endif
|
|
#endif
|
|
char buffer[128];
|
|
unsigned long polling_time;
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
unsigned long polling_time_s;
|
|
unsigned long polling_time_ns;
|
|
#endif
|
|
ktime_t now;
|
|
|
|
now = ktime_get();
|
|
|
|
tscpu_workqueue_start_timer();
|
|
|
|
atm_prev_maxtj = atm_curr_maxtj;
|
|
atm_curr_maxtj = tscpu_get_curr_temp();
|
|
|
|
|
|
atm_prev_maxtj_time = atm_curr_maxtj_time;
|
|
atm_curr_maxtj_time = ktime_to_us(now);
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
if (atm_sspm_enabled == 1) {
|
|
#ifdef ATM_CFG_PROFILING
|
|
atm_resumed = 1; /* Must skip last timestamp. */
|
|
#endif
|
|
goto exit;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
temp = sprintf(buffer, "%s c %d p %d l %d ct %lld pt %lld ", __func__,
|
|
atm_curr_maxtj, atm_prev_maxtj,
|
|
adaptive_cpu_power_limit,
|
|
atm_curr_maxtj_time,
|
|
atm_prev_maxtj_time);
|
|
#if 0
|
|
if (atm_curr_maxtj >= 100000
|
|
|| (atm_curr_maxtj - atm_prev_maxtj >= 15000))
|
|
print_risky_temps(buffer, temp, 1);
|
|
else
|
|
print_risky_temps(buffer, temp, 0);
|
|
#endif
|
|
|
|
#ifdef ENALBE_UART_LIMIT
|
|
#if ENALBE_UART_LIMIT
|
|
temp = atm_curr_maxtj;
|
|
if ((TEMP_DIS_UART - TEMP_TOLERANCE) < temp) {
|
|
/************************************************
|
|
* Disable UART log
|
|
************************************************
|
|
*/
|
|
if (mt_get_uartlog_status()) {
|
|
hasDisabled = 1;
|
|
set_uartlog_status(false);
|
|
}
|
|
}
|
|
|
|
if (temp < (TEMP_EN_UART + TEMP_TOLERANCE)) {
|
|
/*************************************************
|
|
* Restore UART log
|
|
************************************************
|
|
*/
|
|
if (!mt_get_uartlog_status() && hasDisabled)
|
|
set_uartlog_status(true);
|
|
|
|
hasDisabled = 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if (krtatm_thread_handle != NULL)
|
|
wake_up_process(krtatm_thread_handle);
|
|
|
|
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && CPT_ADAPTIVE_AP_COOLER && \
|
|
PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
exit:
|
|
#endif
|
|
#endif
|
|
|
|
polling_time = atm_get_timeout_time(atm_curr_maxtj);
|
|
|
|
#if defined(THERMAL_APU_UNLIMIT)
|
|
if (cl_get_apu_status() == 1) {/*flag not be cleared*/
|
|
total_apu_polling_time =
|
|
total_apu_polling_time + polling_time;
|
|
} else {
|
|
/*flag is cleared, clear timer*/
|
|
total_apu_polling_time = 0;
|
|
}
|
|
|
|
/*count till 10 sec(10000ms) timeout*/
|
|
if (total_apu_polling_time >= 10000) {
|
|
total_apu_polling_time = 0;
|
|
cl_set_apu_status(0);//clear apu flag
|
|
|
|
tscpu_printk("%s ainr: total_apu_polling_time = 0\n",
|
|
__func__);
|
|
}
|
|
#endif
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
|
|
/*avoid overflow*/
|
|
if (polling_time > (1000000000-1)) {
|
|
polling_time_s = polling_time / 1000000000;
|
|
polling_time_ns = polling_time % 1000000000;
|
|
ktime = ktime_set(polling_time_s, polling_time_ns);
|
|
/* tscpu_warn("%s polling_time_s=%ld "
|
|
* "polling_time_ns=%ld\n", __func__,
|
|
* polling_time_s,polling_time_ns);
|
|
*/
|
|
|
|
} else {
|
|
ktime = ktime_set(0, polling_time);
|
|
}
|
|
|
|
hrtimer_forward_now(timer, ktime);
|
|
|
|
return HRTIMER_RESTART;
|
|
#elif KRTATM_TIMER == KRTATM_NORMAL
|
|
|
|
atm_timer.expires = jiffies + msecs_to_jiffies(polling_time);
|
|
add_timer(&atm_timer);
|
|
#endif
|
|
}
|
|
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
static void atm_hrtimer_init(void)
|
|
{
|
|
ktime_t ktime;
|
|
|
|
tscpu_dprintk("%s\n", __func__);
|
|
|
|
/*100000000 = 100 ms,polling delay can't larger than 100ms*/
|
|
atm_hrtimer_polling_delay =
|
|
(atm_hrtimer_polling_delay < 100000000) ?
|
|
atm_hrtimer_polling_delay : 100000000;
|
|
|
|
ktime = ktime_set(0, atm_hrtimer_polling_delay);
|
|
|
|
hrtimer_init(&atm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
|
|
atm_hrtimer.function = atm_loop;
|
|
hrtimer_start(&atm_hrtimer, ktime, HRTIMER_MODE_REL);
|
|
}
|
|
#elif KRTATM_TIMER == KRTATM_NORMAL
|
|
static void atm_timer_init(void)
|
|
{
|
|
tscpu_dprintk("%s\n", __func__);
|
|
|
|
/*polling delay can't larger than 100ms*/
|
|
atm_timer_polling_delay = (atm_timer_polling_delay < 100) ?
|
|
atm_timer_polling_delay : 100;
|
|
|
|
timer_setup(&atm_timer, atm_loop, TIMER_DEFERRABLE);
|
|
atm_timer.expires =
|
|
jiffies + msecs_to_jiffies(atm_timer_polling_delay);
|
|
|
|
add_timer(&atm_timer);
|
|
}
|
|
#endif
|
|
|
|
#define KRTATM_RT (1)
|
|
#define KRTATM_CFS (2)
|
|
#define KRTATM_SCH KRTATM_CFS
|
|
|
|
static int krtatm_thread(void *arg)
|
|
{
|
|
#ifdef ATM_CFG_PROFILING
|
|
ktime_t last, delta;
|
|
#endif
|
|
|
|
#if KRTATM_SCH == KRTATM_RT
|
|
struct sched_param param = {.sched_priority = 98 };
|
|
|
|
sched_setscheduler(current, SCHED_FIFO, ¶m);
|
|
#elif KRTATM_SCH == KRTATM_CFS
|
|
set_user_nice(current, MIN_NICE);
|
|
#endif
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
|
|
tscpu_dprintk("%s 1st run\n", __func__);
|
|
|
|
schedule();
|
|
|
|
for (;;) {
|
|
#ifdef ATM_CFG_PROFILING
|
|
if (atm_resumed) {
|
|
atm_resumed = 0;
|
|
} else {
|
|
delta = ktime_get();
|
|
if (ktime_after(delta, last))
|
|
atm_profile_atm_period(
|
|
ktime_to_us(ktime_sub(delta, last)));
|
|
}
|
|
last = ktime_get();
|
|
#endif
|
|
tscpu_dprintk("%s awake\n", __func__);
|
|
#if (CONFIG_THERMAL_AEE_RR_REC == 1)
|
|
aee_rr_rec_thermal_ATM_status(ATM_WAKEUP);
|
|
#endif
|
|
if (kthread_should_stop())
|
|
break;
|
|
|
|
{
|
|
#ifdef ATM_CFG_PROFILING
|
|
ktime_t start, end;
|
|
#endif
|
|
unsigned int gpu_loading;
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
start = ktime_get();
|
|
cpu_pwr_lmt_latest_delay = 0;
|
|
gpu_pwr_lmt_latest_delay = 0;
|
|
#endif
|
|
|
|
if (!mtk_get_gpu_loading(&gpu_loading))
|
|
gpu_loading = 0;
|
|
|
|
/* use separate prev/curr in krtatm because
|
|
* krtatm may be blocked by PPM
|
|
*/
|
|
krtatm_prev_maxtj = krtatm_curr_maxtj;
|
|
krtatm_curr_maxtj = atm_curr_maxtj;
|
|
if (krtatm_prev_maxtj == 0)
|
|
krtatm_prev_maxtj = atm_prev_maxtj;
|
|
|
|
_adaptive_power_calc(krtatm_prev_maxtj,
|
|
krtatm_curr_maxtj,
|
|
(unsigned int) gpu_loading);
|
|
|
|
trace_ATM__result(
|
|
TARGET_TJ,
|
|
atm_curr_maxtj,
|
|
#if defined(CONFIG_MACH_MT6739)
|
|
get_immediate_cpu_wrap(),
|
|
0,
|
|
#elif defined(CONFIG_MACH_MT6765) || defined(CONFIG_MACH_MT6771) || \
|
|
defined(CONFIG_MACH_MT8168) || defined(CONFIG_MACH_MT6761)
|
|
get_immediate_cpuLL_wrap(),
|
|
get_immediate_cpuL_wrap(),
|
|
#else
|
|
get_immediate_cpuL_wrap(),
|
|
get_immediate_cpuB_wrap(),
|
|
#endif
|
|
get_immediate_gpu_wrap(),
|
|
gpu_loading,
|
|
(adaptive_cpu_power_limit == 0x7FFFFFFF)
|
|
? MAXIMUM_CPU_POWER : adaptive_cpu_power_limit,
|
|
(adaptive_gpu_power_limit == 0x7FFFFFFF)
|
|
? MAXIMUM_GPU_POWER : adaptive_gpu_power_limit,
|
|
cl_dev_adp_cpu_state_active,
|
|
#if defined(EARA_THERMAL_SUPPORT)
|
|
is_EARA_handled
|
|
#else
|
|
0
|
|
#endif
|
|
);
|
|
|
|
/* To confirm if krtatm kthread is really running. */
|
|
if (krtatm_curr_maxtj >= 100000 ||
|
|
(krtatm_curr_maxtj - krtatm_prev_maxtj >= 20000)) {
|
|
tscpu_warn("%s c %d p %d cl %d gl %d s %d\n",
|
|
__func__, krtatm_curr_maxtj,
|
|
krtatm_prev_maxtj,
|
|
adaptive_cpu_power_limit,
|
|
adaptive_gpu_power_limit,
|
|
cl_dev_adp_cpu_state_active);
|
|
/* dump more info when atm is deactivated */
|
|
if (!cl_dev_adp_cpu_state_active) {
|
|
#ifdef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
|
|
pr_info_ratelimited(TSCPU_LOG_TAG
|
|
"tjs %d ttj %d %d on %d sspm %d %d\n",
|
|
TARGET_TJS[0], TARGET_TJ,
|
|
current_ETJ, ctm_on,
|
|
#ifdef THERMAL_SSPM_THERMAL_THROTTLE_SWITCH
|
|
tscpu_sspm_thermal_throttle,
|
|
#else
|
|
1, /* disabled */
|
|
#endif
|
|
#if THERMAL_ENABLE_TINYSYS_SSPM && \
|
|
CPT_ADAPTIVE_AP_COOLER && PRECISE_HYBRID_POWER_BUDGET && CONTINUOUS_TM
|
|
atm_sspm_enabled);
|
|
#else
|
|
0);
|
|
#endif
|
|
#else /* !CONFIG_MTK_TINYSYS_SSPM_SUPPORT */
|
|
pr_info_ratelimited(TSCPU_LOG_TAG
|
|
"tjs %d ttj %d %d on %d\n",
|
|
TARGET_TJS[0], TARGET_TJ,
|
|
current_ETJ, ctm_on);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef ATM_CFG_PROFILING
|
|
end = ktime_get();
|
|
if (ktime_after(end, start))
|
|
atm_profile_atm_exec((ktime_to_us(
|
|
ktime_sub(end, start)) -
|
|
cpu_pwr_lmt_latest_delay
|
|
- gpu_pwr_lmt_latest_delay));
|
|
#endif
|
|
}
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
schedule();
|
|
}
|
|
|
|
tscpu_warn("%s stopped\n", __func__);
|
|
return 0;
|
|
}
|
|
#endif /* FAST_RESPONSE_ATM */
|
|
|
|
static int __init mtk_cooler_atm_init(void)
|
|
{
|
|
int err = 0;
|
|
|
|
tscpu_dprintk("%s: start\n", __func__);
|
|
|
|
err = apthermolmt_register_user(&ap_atm, ap_atm_log);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
/* default use old version */
|
|
_adaptive_power_calc = _adaptive_power;
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
if (tscpu_atm == 3)
|
|
_adaptive_power_calc = _adaptive_power_ppb;
|
|
#endif
|
|
cl_dev_adp_cpu[0] = mtk_thermal_cooling_device_register(
|
|
"cpu_adaptive_0", NULL,
|
|
&mtktscpu_cooler_adp_cpu_ops);
|
|
|
|
cl_dev_adp_cpu[1] = mtk_thermal_cooling_device_register(
|
|
"cpu_adaptive_1", NULL,
|
|
&mtktscpu_cooler_adp_cpu_ops);
|
|
|
|
cl_dev_adp_cpu[2] = mtk_thermal_cooling_device_register(
|
|
"cpu_adaptive_2", NULL,
|
|
&mtktscpu_cooler_adp_cpu_ops);
|
|
|
|
#if defined(CLATM_SET_INIT_CFG)
|
|
mtk_thermal_cooling_device_add_exit_point(
|
|
cl_dev_adp_cpu[0], CLATM_INIT_CFG_0_EXIT_POINT);
|
|
|
|
mtk_thermal_cooling_device_add_exit_point(
|
|
cl_dev_adp_cpu[1], CLATM_INIT_CFG_1_EXIT_POINT);
|
|
|
|
mtk_thermal_cooling_device_add_exit_point(
|
|
cl_dev_adp_cpu[2], CLATM_INIT_CFG_2_EXIT_POINT);
|
|
#endif
|
|
|
|
#endif
|
|
if (err) {
|
|
tscpu_printk("%s fail\n", __func__);
|
|
return err;
|
|
}
|
|
tscpu_cooler_create_fs();
|
|
|
|
#ifdef FAST_RESPONSE_ATM
|
|
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
atm_hrtimer_init();
|
|
#elif KRTATM_SCH == KRTATM_NORMAL
|
|
atm_timer_init();
|
|
#endif
|
|
|
|
#if defined(CATM_TPCB_EXTEND)
|
|
mtk_thermal_get_turbo();
|
|
#endif
|
|
|
|
tscpu_dprintk("%s creates krtatm\n", __func__);
|
|
krtatm_thread_handle = kthread_create(krtatm_thread,
|
|
(void *)NULL, "krtatm");
|
|
|
|
if (IS_ERR(krtatm_thread_handle)) {
|
|
krtatm_thread_handle = NULL;
|
|
tscpu_printk("%s krtatm creation fails\n", __func__);
|
|
} else
|
|
wake_up_process(krtatm_thread_handle);
|
|
#endif
|
|
#if 0
|
|
reset_gpu_power_history();
|
|
#endif
|
|
tscpu_dprintk("%s: end\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static void __exit mtk_cooler_atm_exit(void)
|
|
{
|
|
#ifdef FAST_RESPONSE_ATM
|
|
|
|
#if KRTATM_TIMER == KRTATM_HR
|
|
hrtimer_cancel(&atm_hrtimer);
|
|
#elif KRTATM_SCH == KRTATM_NORMAL
|
|
del_timer(&atm_timer);
|
|
#endif
|
|
|
|
if (krtatm_thread_handle)
|
|
kthread_stop(krtatm_thread_handle);
|
|
#endif
|
|
|
|
#if CPT_ADAPTIVE_AP_COOLER
|
|
if (cl_dev_adp_cpu[0]) {
|
|
mtk_thermal_cooling_device_unregister(
|
|
cl_dev_adp_cpu[0]);
|
|
|
|
cl_dev_adp_cpu[0] = NULL;
|
|
}
|
|
|
|
if (cl_dev_adp_cpu[1]) {
|
|
mtk_thermal_cooling_device_unregister(
|
|
cl_dev_adp_cpu[1]);
|
|
|
|
cl_dev_adp_cpu[1] = NULL;
|
|
}
|
|
|
|
if (cl_dev_adp_cpu[2]) {
|
|
mtk_thermal_cooling_device_unregister(
|
|
cl_dev_adp_cpu[2]);
|
|
|
|
cl_dev_adp_cpu[2] = NULL;
|
|
}
|
|
#endif
|
|
|
|
apthermolmt_unregister_user(&ap_atm);
|
|
}
|
|
|
|
module_init(mtk_cooler_atm_init);
|
|
module_exit(mtk_cooler_atm_exit);
|