Squashed backup commit (no shallow-clone history issues) of xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream commit 9eece662e) plus all fixes applied to get everpal_defconfig building clean against a modern (GCC 15.2.0) toolchain -- see the previous commit message on the lineage-23.2 branch (also in this repo history is not available here since this is a squashed snapshot; full incremental history lives in the local DL380 checkout and the upstream GitHub remote). Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
973 lines
21 KiB
C
973 lines
21 KiB
C
/*
|
|
* Copyright (C) 2018 MediaTek Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/version.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/seq_file.h>
|
|
|
|
#ifdef CONFIG_OF
|
|
#include <linux/of.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_address.h>
|
|
#endif
|
|
|
|
#if defined(CONFIG_MTK_CLKMGR)
|
|
#include <mach/mtk_clkmgr.h>
|
|
#else
|
|
#include <linux/clk.h>
|
|
#endif
|
|
|
|
#include <tscpu_settings.h>
|
|
#include "mtk_idle.h"
|
|
|
|
#if CFG_THERMAL_KERNEL_IGNORE_HOT_SENSOR
|
|
#include <mt-plat/mtk_devinfo.h>
|
|
#endif
|
|
|
|
#if CONFIG_LVTS_ERROR_AEE_WARNING
|
|
#include <mt-plat/aee.h>
|
|
#include <linux/delay.h>
|
|
#if DUMP_VCORE_VOLTAGE
|
|
#include <linux/regulator/consumer.h>
|
|
#endif
|
|
struct lvts_error_data {
|
|
int ts_temp[TS_ENUM_MAX][R_BUFFER_SIZE]; /* A ring buffer */
|
|
int ts_temp_r[TS_ENUM_MAX][R_BUFFER_SIZE]; /* A ring buffer */
|
|
int ts_temp_v[TS_ENUM_MAX][R_BUFFER_SIZE]; /* A ring buffer */
|
|
#if DUMP_VCORE_VOLTAGE
|
|
int vcore_voltage[R_BUFFER_SIZE]; /* A ring buffer */
|
|
#endif
|
|
int c_index; /* Current index points to the space to replace.*/
|
|
int e_occurred; /* 1: An error occurred, 0: Nothing happened*/
|
|
int f_count; /* Future count */
|
|
enum thermal_sensor e_mcu;
|
|
enum thermal_sensor e_lvts;
|
|
};
|
|
struct lvts_error_data g_lvts_e_data;
|
|
int tscpu_ts_mcu_temp_v[L_TS_MCU_NUM];
|
|
int tscpu_ts_lvts_temp_v[L_TS_LVTS_NUM];
|
|
#endif
|
|
|
|
|
|
#if CFG_THERM_LVTS
|
|
int tscpu_ts_lvts_temp[L_TS_LVTS_NUM];
|
|
int tscpu_ts_lvts_temp_r[L_TS_LVTS_NUM];
|
|
#endif
|
|
|
|
int tscpu_curr_cpu_temp;
|
|
int tscpu_curr_gpu_temp;
|
|
#if CFG_THERMAL_KERNEL_IGNORE_HOT_SENSOR
|
|
static int ignore_hot_sensor;
|
|
#endif
|
|
|
|
static int tscpu_curr_max_ts_temp;
|
|
|
|
int __attribute__ ((weak))
|
|
mtk_idle_notifier_register(struct notifier_block *n)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int get_immediate_none_wrap(void)
|
|
{
|
|
return -127000;
|
|
}
|
|
|
|
/* chip dependent */
|
|
int get_immediate_cpuL_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = MAX(
|
|
MAX(tscpu_ts_lvts_temp[L_TS_LVTS1_0],
|
|
tscpu_ts_lvts_temp[L_TS_LVTS1_1]),
|
|
MAX(tscpu_ts_lvts_temp[L_TS_LVTS1_2],
|
|
tscpu_ts_lvts_temp[L_TS_LVTS1_3])
|
|
);
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_cpuB_LVTS1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = MAX(tscpu_ts_lvts_temp[L_TS_LVTS2_0],
|
|
tscpu_ts_lvts_temp[L_TS_LVTS2_1]);
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
|
|
int get_immediate_gpu_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = MAX(tscpu_ts_lvts_temp[L_TS_LVTS3_0],
|
|
tscpu_ts_lvts_temp[L_TS_LVTS3_1]);
|
|
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
|
|
}
|
|
|
|
int get_immediate_infa_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_2];
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_connsys_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_3];
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_md_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = MAX(MAX(tscpu_ts_lvts_temp[L_TS_LVTS4_0],
|
|
tscpu_ts_lvts_temp[L_TS_LVTS4_1]),
|
|
tscpu_ts_lvts_temp[L_TS_LVTS4_2]);
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* module LVTS Plan
|
|
*=====================================================
|
|
* MCU_LITTLE LVTS1-0, LVTS1-1, LVTS1-2, LVTS1-3
|
|
* BIG LVTS2-0, LVTS2-1
|
|
* GPU LVTS3-0, LVTS3-1
|
|
* SOC LVTS3-2
|
|
* CONSYS LVTS3-3
|
|
* MD-4G LVTS4-0
|
|
* MD-5G LVTS4-1
|
|
* MD-3G LVTS4-2
|
|
*/
|
|
|
|
|
|
/*
|
|
* THERMAL_BANK0, //L CPU (LVTS1)
|
|
* THERMAL_BANK1, //B CPU (LVTS2)
|
|
* THERMAL_BANK2, //GPU (LVTS3)
|
|
* THERMAL_BANK3, //MD (LVTS4)
|
|
*/
|
|
|
|
int (*max_temperature_in_bank[THERMAL_BANK_NUM])(void) = {
|
|
get_immediate_cpuB_LVTS1_wrap,
|
|
get_immediate_cpuL_wrap,
|
|
get_immediate_gpu_wrap,
|
|
get_immediate_md_wrap
|
|
};
|
|
|
|
int get_immediate_cpuB_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = get_immediate_cpuB_LVTS1_wrap();
|
|
|
|
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
|
|
|
|
|
|
int get_immediate_ts0_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS1_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS1_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts2_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS1_2];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts3_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS1_3];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts4_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS2_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts5_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS2_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts6_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts7_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts8_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_2];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_ts9_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[L_TS_LVTS3_3];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
#if CFG_THERM_LVTS
|
|
int get_immediate_tslvts1_0_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS1_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts1_1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS1_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
int get_immediate_tslvts1_2_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS1_2];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts1_3_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS1_3];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts2_0_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS2_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts2_1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS2_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts3_0_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS3_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts3_1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS3_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts3_2_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS3_2];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts3_3_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS3_3];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts4_0_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS4_0];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts4_1_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS4_1];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
int get_immediate_tslvts4_2_wrap(void)
|
|
{
|
|
int curr_temp;
|
|
|
|
curr_temp = tscpu_ts_lvts_temp[TS_LVTS4_2];
|
|
tscpu_dprintk("%s curr_temp=%d\n", __func__, curr_temp);
|
|
|
|
return curr_temp;
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
int get_immediate_tsabb_wrap(void)
|
|
{
|
|
|
|
return 0;
|
|
}
|
|
|
|
int (*get_immediate_tsX[TS_ENUM_MAX])(void) = {
|
|
|
|
#if CFG_THERM_LVTS
|
|
get_immediate_tslvts1_0_wrap,
|
|
get_immediate_tslvts1_1_wrap,
|
|
get_immediate_tslvts1_2_wrap,
|
|
get_immediate_tslvts1_3_wrap,
|
|
get_immediate_tslvts2_0_wrap,
|
|
get_immediate_tslvts2_1_wrap,
|
|
get_immediate_tslvts3_0_wrap,
|
|
get_immediate_tslvts3_1_wrap,
|
|
get_immediate_tslvts3_2_wrap,
|
|
get_immediate_tslvts3_3_wrap,
|
|
get_immediate_tslvts4_0_wrap,
|
|
get_immediate_tslvts4_1_wrap,
|
|
get_immediate_tslvts4_2_wrap
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* this only returns latest stored max ts temp but not updated from TC.
|
|
*/
|
|
int tscpu_get_curr_max_ts_temp(void)
|
|
{
|
|
return tscpu_curr_max_ts_temp;
|
|
}
|
|
|
|
#if CFG_THERM_LVTS
|
|
int tscpu_max_temperature(void)
|
|
{
|
|
int i, j, max = 0;
|
|
|
|
#if CFG_LVTS_DOMINATOR
|
|
#if CFG_THERM_LVTS
|
|
tscpu_dprintk("lvts_max_temperature %s, %d\n", __func__, __LINE__);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
|
for (j = 0; j < lvts_tscpu_g_tc[i].ts_number; j++) {
|
|
if (i == 0 && j == 0) {
|
|
max = tscpu_ts_lvts_temp[
|
|
lvts_tscpu_g_tc[i].ts[j]];
|
|
} else {
|
|
if (max < tscpu_ts_lvts_temp[
|
|
lvts_tscpu_g_tc[i].ts[j]])
|
|
max = tscpu_ts_lvts_temp[
|
|
lvts_tscpu_g_tc[i].ts[j]];
|
|
}
|
|
}
|
|
}
|
|
#endif /* CFG_THERM_LVTS */
|
|
#else
|
|
tscpu_dprintk("tscpu_get_temp %s, %d\n", __func__, __LINE__);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tscpu_g_tc); i++) {
|
|
for (j = 0; j < tscpu_g_tc[i].ts_number; j++) {
|
|
if (i == 0 && j == 0) {
|
|
max = tscpu_ts_mcu_temp[tscpu_g_tc[i].ts[j]];
|
|
} else {
|
|
if (max < tscpu_ts_mcu_temp[
|
|
tscpu_g_tc[i].ts[j]])
|
|
max = tscpu_ts_mcu_temp[
|
|
tscpu_g_tc[i].ts[j]];
|
|
}
|
|
}
|
|
}
|
|
#endif /* CFG_LVTS_DOMINATOR */
|
|
return max;
|
|
}
|
|
#endif
|
|
|
|
int tscpu_get_curr_temp(void)
|
|
{
|
|
tscpu_update_tempinfo();
|
|
|
|
#if PRECISE_HYBRID_POWER_BUDGET
|
|
/* update CPU/GPU temp data whenever TZ times out...
|
|
* If the update timing is aligned to TZ polling,
|
|
* this segment should be moved to TZ code instead of thermal
|
|
* controller driver
|
|
*/
|
|
/*
|
|
* module LVTS Plan
|
|
*=====================================================
|
|
* MCU_LITTLE LVTS1-0, LVTS1-1, LVTS1-2, LVTS1-3
|
|
* BIG LVTS2-0, LVTS2-1
|
|
* GPU LVTS3-0, LVTS3-1
|
|
* SOC LVTS3-2
|
|
* CONSYS LVTS3-3
|
|
* MD-4G LVTS4-0
|
|
* MD-5G LVTS4-1
|
|
* MD-3G LVTS4-2
|
|
*/
|
|
|
|
|
|
|
|
#if CFG_LVTS_DOMINATOR
|
|
#if CFG_THERM_LVTS
|
|
tscpu_curr_cpu_temp =
|
|
MAX(
|
|
(MAX(
|
|
MAX(tscpu_ts_lvts_temp[TS_LVTS1_0],
|
|
tscpu_ts_lvts_temp[TS_LVTS1_1]),
|
|
MAX(tscpu_ts_lvts_temp[TS_LVTS1_2],
|
|
tscpu_ts_lvts_temp[TS_LVTS1_3])
|
|
)),
|
|
(MAX(
|
|
tscpu_ts_lvts_temp[TS_LVTS2_0],
|
|
tscpu_ts_lvts_temp[TS_LVTS2_1])
|
|
)
|
|
);
|
|
|
|
tscpu_curr_gpu_temp = MAX(tscpu_ts_lvts_temp[TS_LVTS3_0],
|
|
tscpu_ts_lvts_temp[TS_LVTS3_1]);
|
|
#endif /* CFG_THERM_LVTS */
|
|
#else
|
|
/* It is platform dependent which TS is better to present CPU/GPU
|
|
* temperature
|
|
*/
|
|
tscpu_curr_cpu_temp = MAX(
|
|
MAX(MAX(tscpu_ts_temp[TS_MCU5], tscpu_ts_temp[TS_MCU6]),
|
|
MAX(tscpu_ts_temp[TS_MCU7], tscpu_ts_temp[TS_MCU8])),
|
|
tscpu_ts_temp[TS_MCU9]);
|
|
|
|
tscpu_curr_gpu_temp = MAX(tscpu_ts_temp[TS_MCU1],
|
|
tscpu_ts_temp[TS_MCU2]);
|
|
#endif /* CFG_LVTS_DOMINATOR */
|
|
#endif /* PRECISE_HYBRID_POWER_BUDGET */
|
|
|
|
/* though tscpu_max_temperature is common, put it in mtk_ts_cpu.c is
|
|
* weird.
|
|
*/
|
|
|
|
tscpu_curr_max_ts_temp = tscpu_max_temperature();
|
|
|
|
return tscpu_curr_max_ts_temp;
|
|
}
|
|
|
|
#if CONFIG_LVTS_ERROR_AEE_WARNING
|
|
char mcu_s_array[TS_ENUM_MAX][17] = {
|
|
#if CFG_THERM_LVTS
|
|
"TS_LVTS1_0",
|
|
"TS_LVTS1_1",
|
|
"TS_LVTS1_2",
|
|
"TS_LVTS1_3",
|
|
"TS_LVTS2_0",
|
|
"TS_LVTS2_1",
|
|
"TS_LVTS3_0",
|
|
"TS_LVTS3_1",
|
|
"TS_LVTS3_2",
|
|
"TS_LVTS3_3",
|
|
"TS_LVTS4_0",
|
|
"TS_LVTS4_1",
|
|
"TS_LVTS4_2"
|
|
#endif
|
|
};
|
|
|
|
static void dump_lvts_error_info(void)
|
|
{
|
|
int i, j, index, e_index, offset;
|
|
#if DUMP_LVTS_REGISTER
|
|
int cnt, temp;
|
|
#endif
|
|
enum thermal_sensor mcu_index, lvts_index;
|
|
char buffer[512];
|
|
|
|
mcu_index = g_lvts_e_data.e_mcu;
|
|
lvts_index = g_lvts_e_data.e_lvts;
|
|
index = g_lvts_e_data.c_index;
|
|
e_index = (index + HISTORY_SAMPLES + 1) % R_BUFFER_SIZE;
|
|
|
|
tscpu_printk("[LVTS_ERROR][DUMP] %s:%d and %s:%d error: |%d| > %d\n",
|
|
mcu_s_array[mcu_index],
|
|
g_lvts_e_data.ts_temp[mcu_index][e_index],
|
|
mcu_s_array[lvts_index],
|
|
g_lvts_e_data.ts_temp[lvts_index][e_index],
|
|
g_lvts_e_data.ts_temp[mcu_index][e_index] -
|
|
g_lvts_e_data.ts_temp[lvts_index][e_index],
|
|
LVTS_ERROR_THRESHOLD);
|
|
|
|
for (i = TS_MCU1; i <= TS_LVTS4_1; i++) {
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s][DUMP] ",
|
|
mcu_s_array[i]);
|
|
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
index = (g_lvts_e_data.c_index + 1 + j)
|
|
% R_BUFFER_SIZE;
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp[i][index]);
|
|
|
|
}
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
}
|
|
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s_R][DUMP] ",
|
|
mcu_s_array[lvts_index]);
|
|
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
index = (g_lvts_e_data.c_index + 1 + j) % R_BUFFER_SIZE;
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp_r[lvts_index][index]);
|
|
}
|
|
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s_V][DUMP] ",
|
|
mcu_s_array[mcu_index]);
|
|
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
index = (g_lvts_e_data.c_index + 1 + j) % R_BUFFER_SIZE;
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp_v[mcu_index][index]);
|
|
}
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s_V][DUMP] ",
|
|
mcu_s_array[lvts_index]);
|
|
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
index = (g_lvts_e_data.c_index + 1 + j) % R_BUFFER_SIZE;
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp_v[lvts_index][index]);
|
|
}
|
|
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
|
|
dump_efuse_data();
|
|
#if DUMP_LVTS_REGISTER
|
|
read_controller_reg_when_error();
|
|
|
|
lvts_thermal_disable_all_periodoc_temp_sensing();
|
|
lvts_wait_for_all_sensing_point_idle();
|
|
|
|
read_device_reg_when_error();
|
|
dump_lvts_register_value();
|
|
#endif
|
|
#if DUMP_VCORE_VOLTAGE
|
|
offset = sprintf(buffer, "[LVTS_ERROR][Vcore_V][DUMP] ",
|
|
mcu_s_array[lvts_index]);
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
index = (g_lvts_e_data.c_index + 1 + j) % R_BUFFER_SIZE;
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.vcore_voltage[index]);
|
|
}
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
#endif
|
|
#if DUMP_LVTS_REGISTER
|
|
lvts_reset_device_and_stop_clk();
|
|
#endif
|
|
#ifdef CONFIG_MTK_AEE_FEATURE
|
|
aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_DEFAULT, __func__,
|
|
"LVTS_ERROR: %s, %s diff: %d\n", mcu_s_array[mcu_index],
|
|
mcu_s_array[lvts_index],
|
|
g_lvts_e_data.ts_temp[mcu_index][e_index] -
|
|
g_lvts_e_data.ts_temp[lvts_index][e_index]);
|
|
#endif
|
|
|
|
g_lvts_e_data.e_occurred = 0;
|
|
g_lvts_e_data.f_count = -1;
|
|
#if DUMP_LVTS_REGISTER
|
|
clear_lvts_register_value_array();
|
|
|
|
lvts_device_identification();
|
|
lvts_Device_Enable_Init_all_Devices();
|
|
lvts_device_read_count_RC_N();
|
|
lvts_efuse_setting();
|
|
|
|
lvts_thermal_disable_all_periodoc_temp_sensing();
|
|
Enable_LVTS_CTRL_for_thermal_Data_Fetch();
|
|
lvts_tscpu_thermal_initial_all_tc();
|
|
#endif
|
|
}
|
|
|
|
static void check_lvts_error(enum thermal_sensor mcu_index,
|
|
enum thermal_sensor lvts_index)
|
|
{
|
|
int temp;
|
|
|
|
temp = tscpu_ts_temp[mcu_index] - tscpu_ts_temp[lvts_index];
|
|
|
|
if (temp < 0)
|
|
temp = temp * -1;
|
|
|
|
/*Skip if LVTS thermal controllers doens't ready */
|
|
if (temp > 100000)
|
|
return;
|
|
|
|
if (temp > LVTS_ERROR_THRESHOLD) {
|
|
tscpu_printk("[LVTS_ERROR] %s:%d and %s:%d error: |%d| > %d\n",
|
|
mcu_s_array[mcu_index],
|
|
tscpu_ts_temp[mcu_index],
|
|
mcu_s_array[lvts_index],
|
|
tscpu_ts_temp[lvts_index],
|
|
tscpu_ts_temp[mcu_index] -
|
|
tscpu_ts_temp[lvts_index],
|
|
LVTS_ERROR_THRESHOLD);
|
|
g_lvts_e_data.e_occurred = 1;
|
|
g_lvts_e_data.e_mcu = mcu_index;
|
|
g_lvts_e_data.e_lvts = lvts_index;
|
|
g_lvts_e_data.f_count = -1;
|
|
}
|
|
}
|
|
void dump_lvts_error_data_info(void)
|
|
{
|
|
char buffer[512];
|
|
int offset, j;
|
|
|
|
tscpu_printk("[LVTS_ERROR] c_index %d, e_occurred %d, f_count %d\n",
|
|
g_lvts_e_data.c_index, g_lvts_e_data.e_occurred,
|
|
g_lvts_e_data.f_count);
|
|
tscpu_printk("[LVTS_ERROR] e_mcu %d, e_lvts %d\n", g_lvts_e_data.e_mcu,
|
|
g_lvts_e_data.e_lvts);
|
|
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s][DUMP] ",
|
|
mcu_s_array[TS_LVTS1_0]);
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp[TS_LVTS1_0][j]);
|
|
|
|
}
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
|
|
offset = sprintf(buffer, "[LVTS_ERROR][%s_raw][DUMP] ",
|
|
mcu_s_array[TS_LVTS1_0]);
|
|
for (j = 0; j < R_BUFFER_SIZE; j++) {
|
|
offset += sprintf(buffer + offset, "%d ",
|
|
g_lvts_e_data.ts_temp_r[TS_LVTS1_0][j]);
|
|
|
|
}
|
|
buffer[offset] = '\0';
|
|
tscpu_printk("%s\n", buffer);
|
|
}
|
|
#endif
|
|
|
|
int tscpu_read_temperature_info(struct seq_file *m, void *v)
|
|
{
|
|
seq_printf(m, "curr_temp = %d\n", tscpu_get_curr_max_ts_temp());
|
|
|
|
#if !defined(CFG_THERM_NO_AUXADC)
|
|
tscpu_dump_cali_info(m, v);
|
|
#endif
|
|
|
|
#if CFG_THERM_LVTS
|
|
seq_puts(m, "-----------------\n");
|
|
lvts_tscpu_dump_cali_info(m, v);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int thermal_idle_notify_call(struct notifier_block *nfb,
|
|
unsigned long id,
|
|
void *arg)
|
|
{
|
|
switch (id) {
|
|
case NOTIFY_DPIDLE_ENTER:
|
|
break;
|
|
case NOTIFY_SOIDLE_ENTER:
|
|
break;
|
|
case NOTIFY_DPIDLE_LEAVE:
|
|
break;
|
|
case NOTIFY_SOIDLE_LEAVE:
|
|
break;
|
|
case NOTIFY_SOIDLE3_ENTER:
|
|
#if LVTS_VALID_DATA_TIME_PROFILING
|
|
SODI3_count++;
|
|
if (SODI3_count != 1 && isTempValid == 0)
|
|
noValid_count++;
|
|
|
|
if (isTempValid == 1 || SODI3_count == 1)
|
|
start_timestamp = thermal_get_current_time_us();
|
|
|
|
isTempValid = 0;
|
|
#endif
|
|
break;
|
|
case NOTIFY_SOIDLE3_LEAVE:
|
|
#if CFG_THERM_LVTS
|
|
lvts_sodi3_release_thermal_controller();
|
|
#endif
|
|
break;
|
|
default:
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
return NOTIFY_OK;
|
|
}
|
|
|
|
static struct notifier_block thermal_idle_nfb = {
|
|
.notifier_call = thermal_idle_notify_call,
|
|
};
|
|
|
|
#ifdef CONFIG_OF
|
|
int get_io_reg_base(void)
|
|
{
|
|
struct device_node *node = NULL;
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,therm_ctrl");
|
|
WARN_ON_ONCE(node == 0);
|
|
if (node) {
|
|
/* Setup IO addresses */
|
|
thermal_base = of_iomap(node, 0);
|
|
}
|
|
|
|
/*tscpu_printk("[THERM_CTRL] thermal_base= 0x%px\n",thermal_base);*/
|
|
|
|
/*get thermal irq num */
|
|
thermal_irq_number = irq_of_parse_and_map(node, 0);
|
|
tscpu_printk("[THERM_CTRL] thermal_irq_number=%d\n",
|
|
thermal_irq_number);
|
|
if (!thermal_irq_number) {
|
|
/*TODO: need check "irq number"*/
|
|
tscpu_printk("[THERM_CTRL] get irqnr failed=%d\n",
|
|
thermal_irq_number);
|
|
return 0;
|
|
}
|
|
|
|
if (of_property_read_u32_index(node, "reg", 1, &thermal_phy_base)) {
|
|
tscpu_printk("[THERM_CTRL] config error thermal_phy_base\n");
|
|
return 0;
|
|
}
|
|
|
|
/*tscpu_printk("[THERM_CTRL] phy_base=0x%x\n", thermal_phy_base);*/
|
|
|
|
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,mt6768-auxadc");
|
|
WARN_ON_ONCE(node == 0);
|
|
if (node) {
|
|
/* Setup IO addresses */
|
|
auxadc_ts_base = of_iomap(node, 0);
|
|
}
|
|
|
|
if (of_property_read_u32_index(node, "reg", 1, &auxadc_ts_phy_base)) {
|
|
tscpu_printk("[THERM_CTRL] config error auxadc_ts_phy_base\n");
|
|
return 0;
|
|
}
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,infracfg_ao");
|
|
WARN_ON_ONCE(node == 0);
|
|
if (node) {
|
|
/* Setup IO addresses */
|
|
infracfg_ao_base = of_iomap(node, 0);
|
|
|
|
if (infracfg_ao_base)
|
|
mtk_idle_notifier_register(&thermal_idle_nfb);
|
|
}
|
|
|
|
node = of_find_compatible_node(NULL, NULL,
|
|
"mediatek,mt6833-apmixedsys");
|
|
WARN_ON_ONCE(node == 0);
|
|
if (node) {
|
|
/* Setup IO addresses */
|
|
th_apmixed_base = of_iomap(node, 0);
|
|
}
|
|
|
|
if (of_property_read_u32_index(node, "reg", 1, &apmixed_phy_base)) {
|
|
tscpu_printk("[THERM_CTRL] config error apmixed_phy_base=\n");
|
|
return 0;
|
|
}
|
|
|
|
#if THERMAL_GET_AHB_BUS_CLOCK
|
|
/* TODO: If this is required, it needs to confirm which node to read. */
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,infrasys");
|
|
if (!node) {
|
|
pr_notice("[CLK_INFRACFG_AO] find node failed\n");
|
|
return 0;
|
|
}
|
|
therm_clk_infracfg_ao_base = of_iomap(node, 0);
|
|
if (!therm_clk_infracfg_ao_base) {
|
|
pr_notice("[CLK_INFRACFG_AO] base failed\n");
|
|
return 0;
|
|
}
|
|
#endif
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
/* chip dependent */
|
|
int tscpu_thermal_clock_on(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
/* Use CCF */
|
|
tscpu_printk("%s\n", __func__);
|
|
ret = clk_prepare_enable(therm_main);
|
|
if (ret)
|
|
tscpu_printk("Cannot enable thermal clock.\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* chip dependent */
|
|
int tscpu_thermal_clock_off(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
/* Use CCF */
|
|
tscpu_printk("%s\n", __func__);
|
|
clk_disable_unprepare(therm_main);
|
|
return ret;
|
|
}
|
|
|
|
#if CFG_THERMAL_KERNEL_IGNORE_HOT_SENSOR
|
|
#define CPU_SEGMENT 7
|
|
int tscpu_check_cpu_segment(void)
|
|
{
|
|
int val = (get_devinfo_with_index(CPU_SEGMENT) & 0xFF);
|
|
|
|
if (val == 0x30)
|
|
ignore_hot_sensor = 1;
|
|
else
|
|
ignore_hot_sensor = 0;
|
|
|
|
return val;
|
|
}
|
|
#endif
|
|
|