soc/mediatek/mt8189: Add thermal driver

Add MT8189 thermal driver for LVTS (low voltage thermal sensor)
initialization.

BUG=b:379008996
BRANCH=none
TEST=temperature log should between 30~50 degrees:
[INFO ]  thermal_init: thermal initialized
[INFO ]  [LVTS_MSR] ts0 msr_all=13c50, valid=1, msr_temp=15440, temp=44430
[INFO ]  [LVTS_MSR] ts1 msr_all=13c41, valid=1, msr_temp=15425, temp=44660
[INFO ]  [LVTS_MSR] ts2 msr_all=13c3f, valid=1, msr_temp=15423, temp=44690
[INFO ]  [LVTS_MSR] ts3 msr_all=13c4e, valid=1, msr_temp=15438, temp=44461
[INFO ]  [LVTS_MSR] ts4 msr_all=13bc6, valid=1, msr_temp=15302, temp=46540
[INFO ]  [LVTS_MSR] ts5 msr_all=13bd2, valid=1, msr_temp=15314, temp=46356
[INFO ]  [LVTS_MSR] ts6 msr_all=13bd1, valid=1, msr_temp=15313, temp=46372
[INFO ]  [LVTS_MSR] ts7 msr_all=13bc9, valid=1, msr_temp=15305, temp=46494
[INFO ]  [LVTS_MSR] ts8 msr_all=13bed, valid=1, msr_temp=15341, temp=45944
[INFO ]  [LVTS_MSR] ts9 msr_all=13be3, valid=1, msr_temp=15331, temp=46097
[INFO ]  [LVTS_MSR] ts10 msr_all=13c01, valid=1, msr_temp=15361, temp=45638
[INFO ]  [LVTS_MSR] ts11 msr_all=13bc6, valid=1, msr_temp=15302, temp=46540
[INFO ]  [LVTS_MSR] ts12 msr_all=13c06, valid=1, msr_temp=15366, temp=45562
[INFO ]  [LVTS_MSR] ts13 msr_all=13c03, valid=1, msr_temp=15363, temp=45607
[INFO ]  [LVTS_MSR] ts14 msr_all=13bf3, valid=1, msr_temp=15347, temp=45852
[INFO ]  [LVTS_MSR] ts15 msr_all=13c1a, valid=1, msr_temp=15386, temp=45256
[INFO ]  [LVTS_MSR] ts16 msr_all=13c8b, valid=1, msr_temp=15499, temp=43528
[INFO ]  [LVTS_MSR] ts17 msr_all=13c8b, valid=1, msr_temp=15499, temp=43528

Signed-off-by: Raymond Sun <raymond.sun@mediatek.corp-partner.google.com>
Signed-off-by: Kai-chun Huang <kai-chun.huang@mediatek.corp-partner.google..com>
Change-Id: I37dd9da6592146ade556660fa07d2fa374646da5
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88441
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-by: Yidi Lin <yidilin@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Vince Liu 2025-07-18 21:38:14 +08:00 committed by Yu-Ping Wu
commit 6aec09875b
11 changed files with 662 additions and 3 deletions

View file

@ -9,8 +9,10 @@ DECLARE_REGION(dram_dma)
DECLARE_REGION(resv_mem_optee)
DECLARE_REGION(resv_mem_gpu)
DECLARE_REGION(resv_mem_gpueb)
DECLARE_REGION(cpucooler_reserved)
DECLARE_REGION(dvfs2_reserved)
DECLARE_REGION(ptp1_reserved)
DECLARE_REGION(thermal_reserved)
DECLARE_OPTIONAL_REGION(mcufw_reserved)
#endif /* _SOC_MEDIATEK_COMMON_SYMBOLS_H_ */

View file

@ -38,8 +38,10 @@ struct lvts_thermal_controller {
int lvts_write_device(uint16_t config, uint8_t dev_reg_idx, uint8_t data, int tc_num);
const struct lvts_thermal_controller *lvts_get_controller(int tc_num);
void lvts_configure_polling_speed_and_filter(const struct lvts_thermal_controller *tc);
void lvts_set_device_single_mode(int tc_num);
int lvts_read_tc_raw_and_temp(void *msr_reg, enum lvts_sensor ts_name, uint32_t golden_temp);
void lvts_thermal_init(void);
void lvts_clock_gate_disable(void);
void lvts_tscpu_reset_thermal(void);
void lvts_thermal_cal_prepare(void);
void lvts_device_identification(void);

View file

@ -10,6 +10,14 @@
#define LVTS_SENSOR_POINT_SELECTION_SETTING 0x13121110
#define LVTS_CALCULATION_SCALING_RULE 0x300
__weak void lvts_set_device_single_mode(int tc_num)
{
}
__weak void lvts_clock_gate_disable(void)
{
}
static int lvts_raw_to_temp(uint16_t msr_raw, enum lvts_sensor ts_name, uint32_t golden_temp)
{
int temp_mc;
@ -66,6 +74,8 @@ static void lvts_tscpu_thermal_initial_all_tc(void)
write32(&tc->regs->lvtstssel_0, LVTS_SENSOR_POINT_SELECTION_SETTING);
/* Set calculation scale rules */
write32(&tc->regs->lvtscalscale_0, LVTS_CALCULATION_SCALING_RULE);
/* Set Device Single mode */
lvts_set_device_single_mode(i);
lvts_configure_polling_speed_and_filter(tc);
}
@ -311,6 +321,8 @@ void lvts_thermal_init(void)
if (lvts_lk_init_check())
return;
lvts_clock_gate_disable();
lvts_tscpu_reset_thermal();
lvts_thermal_cal_prepare();

View file

@ -24,6 +24,8 @@ romstage-y += dvfs.c
romstage-y += ../common/emi.c
romstage-y += ../common/memory.c ../common/memory_test.c ../common/memory_type.c
romstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c
romstage-y += ../common/thermal.c thermal.c
romstage-y += ../common/thermal_sram.c thermal_sram.c
romstage-y += ../common/mt6315.c mt6315.c
romstage-y += ../common/mt6359p.c mt6359p.c
romstage-y += ../common/pmif.c ../common/pmif_clk.c ../common/pmif_init.c pmif_clk.c

View file

@ -35,6 +35,7 @@ enum {
INFRA_AO_BCRM_BASE = IO_PHYS + 0x00022000,
DEVAPC_INFRA_AO_BASE = IO_PHYS + 0x00030000,
DEVAPC_INFRA_AO1_BASE = IO_PHYS + 0x00034000,
INFRACFG_BASE = IO_PHYS + 0x0020E000,
EMI0_BASE = IO_PHYS + 0x00219000,
EMI0_MPU_BASE = IO_PHYS + 0x00226000,
DRAMC_CHA_AO_BASE = IO_PHYS + 0x00230000,

View file

@ -4,19 +4,23 @@
#define __SOC_MEDIATEK_MT8189_INCLUDE_SOC_EFUSE_H__
#include <soc/addressmap.h>
#include <soc/thermal_internal.h>
#include <stdint.h>
struct efuse_regs {
u32 reserved1[96];
u32 adc_cali_reg;
u32 reserved2[391];
u32 reserved2[8];
u32 lvts_reg[LVTS_ADDRESS_INDEX_NUM];
u32 reserved3[360];
u32 cpu_id_reg;
u32 reserved3[15];
u32 reserved4[15];
u32 cpu_seg_id_reg;
u32 reserved4[14908];
u32 reserved5[14908];
u32 ecc_status_reg;
};
check_member(efuse_regs, adc_cali_reg, 0x180);
check_member(efuse_regs, lvts_reg, 0x1A4);
check_member(efuse_regs, cpu_id_reg, 0x7A0);
check_member(efuse_regs, cpu_seg_id_reg, 0x7E0);
check_member(efuse_regs, ecc_status_reg, 0xF0D4);

View file

@ -60,6 +60,7 @@ struct mtk_infracfg_ao_regs {
};
check_member(mtk_infracfg_ao_regs, infra_bus_dcm_ctrl, 0x0070);
check_member(mtk_infracfg_ao_regs, infracfg_ao_module_cg_0_set, 0x0080);
check_member(mtk_infracfg_ao_regs, infracfg_ao_module_cg_0_clr, 0x0084);
check_member(mtk_infracfg_ao_regs, infracfg_ao_module_cg_1, 0x0094);
check_member(mtk_infracfg_ao_regs, infracfg_ao_module_cg_2_set, 0x00A4);
check_member(mtk_infracfg_ao_regs, infracfg_ao_module_cg_3_set, 0x00C0);

View file

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_H__
#define __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_H__
#include <soc/thermal_common.h>
#endif /* __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_H__ */

View file

@ -0,0 +1,170 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_INTERNAL_H__
#define __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_INTERNAL_H__
#include <soc/addressmap.h>
#include <soc/spm_mtcmos.h>
#include <soc/symbols.h>
#define LVTS_MAGIC 0x0000555
#define MAX_TS_NUMBER 4
#define LVTS_COF_T_SLP_GLD 219960
#define LVTS_COF_COUNT_R_GLD 14437
#define LVTS_COF_T_CONST_OFS 280000
#define LVTS_ADDRESS_INDEX_NUM (L_TS_LVTS_NUM + LVTS_CONTROLLER_NUM)
#define LVTS_GROUP_INTERVAL_DELAY_MASK GENMASK(29, 20)
#define LVTS_COEFF_A (-250460)
#define DEFAULT_EFUSE_GOLDEN_TEMP 50
#define DEFAULT_EFUSE_GOLDEN_TEMP_HT 170
#define DEFAULT_EFUSE_COUNT 35000
#define DEFAULT_EFUSE_COUNT_RC 2750
/* INFRACFG_AO_BASE + 0x0084 */
#define THERM_CG BIT(10)
/* THERM_CTRL_BASE + lvts_tc_offset_enum + 0x0050 */
#define DEVICE_SENSING_STATUS BIT(25)
#define DEVICE_ACCESS_START_BIT BIT(24)
#define WRITE_ACCESS BIT(16)
/* THERM_CTRL_BASE + lvts_tc_offset_enum + 0x000C */
#define STAGE3_INT_EN BIT(31)
/* SRAM for Thermal */
#define THERMAL_ATC_SRAM_OFFSET 0x280
#define THERMAL_SRAM_BASE (_thermal_reserved + THERMAL_ATC_SRAM_OFFSET)
#define THERMAL_SRAM_LEN (24 * 4)
#define THERMAL_STAT_SRAM_BASE _cpucooler_reserved
#define THERMAL_STAT_SRAM_LEN REGION_SIZE(cpucooler_reserved)
/*
* module LVTS Plan
*=====================================================
* MCU_BIG core0/1 LVTS1-0, LVTS1-1, LVTS1-2, LVTS1-3
* MCU_BIG core2/3 LVTS2-0, LVTS2-1, LVTS2-2, LVTS2-3
* MCU_LITTLE LVTS3-0, LVTS3-1, LVTS3-2, LVTS3-3
* SOC-TOP,APU LVTS4-0, LVTS4-1, LVTS4-2, LVTS4-3
* GPU LVTS5-0, LVTS5-1
* ptp_therm_ctrl_AP Base address: (+0x1031_5000), 0x1031_5100, 0x1031_5200
* ptp_therm_ctrl_MCU Base address: (+0x1031_6000), 0x1031_6100, 0x1031_6200, 0x1031_6300
*/
/* private thermal sensor */
enum lvts_sensor {
L_TS_LVTS1_0 = 0, /* LVTS1-0 Big-core0 */
L_TS_LVTS1_1, /* LVTS1-1 Big-core0 */
L_TS_LVTS1_2, /* LVTS1-2 Big-core1 */
L_TS_LVTS1_3, /* LVTS1-3 Big-core1 */
L_TS_LVTS2_0, /* LVTS2-0 Big-core2 */
L_TS_LVTS2_1, /* LVTS2-1 Big-core2 */
L_TS_LVTS2_2, /* LVTS2-2 Big-core3 */
L_TS_LVTS2_3, /* LVTS2-3 Big-core3 */
L_TS_LVTS3_0, /* LVTS3-0 Little-core0 */
L_TS_LVTS3_1, /* LVTS3-1 Little-core1 */
L_TS_LVTS3_2, /* LVTS3-2 Little-core2 */
L_TS_LVTS3_3, /* LVTS3-3 Little-core3 */
L_TS_LVTS4_0, /* LVTS4-0 SCO-TOP */
L_TS_LVTS4_1, /* LVTS4-1 SCO-TOP */
L_TS_LVTS4_2, /* LVTS4-0 SCO-TOP */
L_TS_LVTS4_3, /* LVTS4-1 APU */
L_TS_LVTS5_0, /* LVTS5-0 GPU */
L_TS_LVTS5_1, /* LVTS5-1 GPU */
L_TS_LVTS_NUM,
};
enum lvts_tc_enum {
LVTS_MCU_CONTROLLER0 = 0,
LVTS_MCU_CONTROLLER1,
LVTS_MCU_CONTROLLER2,
LVTS_AP_CONTROLLER0,
LVTS_MFG_CONTROLLER0,
LVTS_CONTROLLER_NUM,
};
enum lvts_tc_offset_enum {
TC_OFFSET_AP_CONTROLLER0 = 0,
TC_OFFSET_MFG_CONTROLLER0 = 0x100,
TC_OFFSET_MCU_CONTROLLER0 = 0x1000,
TC_OFFSET_MCU_CONTROLLER1 = 0x1100,
TC_OFFSET_MCU_CONTROLLER2 = 0x1200,
};
struct mtk_thermal_controller_regs {
u32 lvtsmonctl0_0;
u32 lvtsmonctl1_0;
u32 lvtsmonctl2_0;
u32 lvtsmonint_0;
u32 reserved1[5];
u32 lvtsh2nthre_0;
u32 lvtshthre_0;
u32 lvtscthre_0;
u32 lvtsoffseth_0;
u32 lvtsoffsetl_0;
u32 lvtsmsrctl0_0;
u32 lvtsmsrctl1_0;
u32 lvtstssel_0;
u32 reserved2[1];
u32 lvtscalscale_0;
u32 lvts_id_0;
u32 lvts_config_0;
u32 lvtsedata[4];
u32 reserved3[11];
u32 lvtsmsr[4];
u32 reserved4[4];
u32 lvtsrdata0_0;
u32 reserved5[3];
u32 lvtsprotctl_0;
u32 reserved6[2];
u32 lvtsprottc_0;
u32 reserved7[5];
u32 lvtsclken_0;
u32 reserved8[2];
u32 lvtsspare[2];
u32 reserved9[2];
};
check_member(mtk_thermal_controller_regs, lvtsmonint_0, 0x000C);
check_member(mtk_thermal_controller_regs, lvtsh2nthre_0, 0x0024);
check_member(mtk_thermal_controller_regs, lvtstssel_0, 0x0040);
check_member(mtk_thermal_controller_regs, lvtscalscale_0, 0x0048);
check_member(mtk_thermal_controller_regs, lvtsedata[3], 0x0060);
check_member(mtk_thermal_controller_regs, lvtsmsr[0], 0x0090);
check_member(mtk_thermal_controller_regs, lvtsmsr[3], 0x009C);
check_member(mtk_thermal_controller_regs, lvtsrdata0_0, 0x00B0);
check_member(mtk_thermal_controller_regs, lvtsprotctl_0, 0x00C0);
check_member(mtk_thermal_controller_regs, lvtsprottc_0, 0x00CC);
check_member(mtk_thermal_controller_regs, lvtsclken_0, 0x00E4);
check_member(mtk_thermal_controller_regs, lvtsspare[0], 0x00F0);
check_member(mtk_thermal_controller_regs, lvtsspare[1], 0x00F4);
struct mtk_infracfg_regs {
u32 reserved1[968];
u32 mcu_rst_set;
u32 mcu_rst_clr;
u32 reserved2[10];
u32 ap_rst_set;
u32 ap_rst_clr;
};
check_member(mtk_infracfg_regs, mcu_rst_set, 0x0F20);
check_member(mtk_infracfg_regs, mcu_rst_clr, 0x0F24);
check_member(mtk_infracfg_regs, ap_rst_set, 0x0F50);
check_member(mtk_infracfg_regs, ap_rst_clr, 0x0F54);
/* LVTS Thermal Controller Register Definition */
static struct mtk_thermal_controller_regs *const
mtk_lvts_mcu_controller0 = (void *)(THERM_CTRL_BASE + TC_OFFSET_MCU_CONTROLLER0);
static struct mtk_thermal_controller_regs *const
mtk_lvts_mcu_controller1 = (void *)(THERM_CTRL_BASE + TC_OFFSET_MCU_CONTROLLER1);
static struct mtk_thermal_controller_regs *const
mtk_lvts_mcu_controller2 = (void *)(THERM_CTRL_BASE + TC_OFFSET_MCU_CONTROLLER2);
static struct mtk_thermal_controller_regs *const
mtk_lvts_ap_controller0 = (void *)(THERM_CTRL_BASE + TC_OFFSET_AP_CONTROLLER0);
static struct mtk_thermal_controller_regs *const
mtk_lvts_mfg_controller0 = (void *)(THERM_CTRL_BASE + TC_OFFSET_MFG_CONTROLLER0);
static struct mtk_infracfg_regs *const mtk_infracfg = (void *)INFRACFG_BASE;
#endif /* __SOC_MEDIATEK_MT8189_INCLUDE_SOC_THERMAL_INTERNAL_H__ */

View file

@ -0,0 +1,448 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
/*
* This file is created based on MT8189 Functional Specification
* Chapter number: 9.13
*/
#include <assert.h>
#include <delay.h>
#include <soc/efuse.h>
#include <soc/thermal.h>
#define LVTS_DEVICE_WRITE_CONFIG 0xC103
static uint32_t golden_temp;
static u32 ts_edata[L_TS_LVTS_NUM];
static u32 op_cali[LVTS_CONTROLLER_NUM];
static u32 count_rc_now[L_TS_LVTS_NUM];
/*
* module LVTS Plan
*=====================================================
* MCU_BIG core0/1 LVTS1-0, LVTS1-1, LVTS1-2, LVTS1-3
* MCU_BIG core2/3 LVTS2-0, LVTS2-1, LVTS2-2, LVTS2-3
* MCU_LITTLE LVTS3-0, LVTS3-1, LVTS3-2, LVTS3-3
* SOC-TOP,APU LVTS4-0, LVTS4-1, LVTS4-2, LVTS4-3
* GPU LVTS5-0, LVTS5-1
*
* ptp_therm_ctrl_AP Base address: (+0x1031_5000), 0x1031_5100, 0x1031_5200
* ptp_therm_ctrl_MCU Base address: (+0x1031_6000), 0x1031_6100, 0x1031_6200, 0x1031_6300
*/
static const struct lvts_thermal_controller lvts_tscpu_g_tc[LVTS_CONTROLLER_NUM] = {
[LVTS_MCU_CONTROLLER0] = { /* MCU_BIG core0/1 */
.ts = {L_TS_LVTS1_0, L_TS_LVTS1_1, L_TS_LVTS1_2, L_TS_LVTS1_3},
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
.ts_number = 4,
.reboot_temperature = 119000,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = false,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x0F6,
.period_unit = 0x001,
.filter_interval_delay = 0x001,
.sensor_interval_delay = 0x001
},
.regs = mtk_lvts_mcu_controller0,
},
[LVTS_MCU_CONTROLLER1] = { /* MCU_BIG core2/3 */
.ts = {L_TS_LVTS2_0, L_TS_LVTS2_1, L_TS_LVTS2_2, L_TS_LVTS2_3},
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
.ts_number = 4,
.reboot_temperature = 119000,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = false,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x0F6,
.period_unit = 0x001,
.filter_interval_delay = 0x001,
.sensor_interval_delay = 0x001
},
.regs = mtk_lvts_mcu_controller1,
},
[LVTS_MCU_CONTROLLER2] = { /* MCU_LITTLE */
.ts = {L_TS_LVTS3_0, L_TS_LVTS3_1, L_TS_LVTS3_2, L_TS_LVTS3_3},
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
.ts_number = 4,
.reboot_temperature = 119000,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = false,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x1C1,
.period_unit = 0x001,
.filter_interval_delay = 0x001,
.sensor_interval_delay = 0x001
},
.regs = mtk_lvts_mcu_controller2,
},
[LVTS_AP_CONTROLLER0] = { /* SOC-TOP, APU */
.ts = {L_TS_LVTS4_0, L_TS_LVTS4_1, L_TS_LVTS4_2, L_TS_LVTS4_3},
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
.ts_number = 4,
.reboot_temperature = 119000,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = false,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x0D2,
.period_unit = 0x001,
.filter_interval_delay = 0x001,
.sensor_interval_delay = 0x001
},
.regs = mtk_lvts_ap_controller0,
},
[LVTS_MFG_CONTROLLER0] = { /* MFG */
.ts = {L_TS_LVTS5_0, L_TS_LVTS5_1},
.sensor_on_off = {SEN_ON, SEN_ON},
.ts_number = 2,
.reboot_temperature = 119000,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = false,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x08A,
.period_unit = 0x001,
.filter_interval_delay = 0x001,
.sensor_interval_delay = 0x001
},
.regs = mtk_lvts_mfg_controller0,
},
};
const struct lvts_thermal_controller *lvts_get_controller(int tc_num)
{
assert(tc_num < LVTS_CONTROLLER_NUM);
return &lvts_tscpu_g_tc[tc_num];
}
void lvts_clock_gate_disable(void)
{
write32(&mtk_infracfg_ao->infracfg_ao_module_cg_0_clr, THERM_CG);
}
void lvts_tscpu_reset_thermal(void)
{
/* Reset AP thermal control */
write32(&mtk_infracfg->ap_rst_set, BIT(23));
write32(&mtk_infracfg->ap_rst_clr, BIT(23));
/* Reset MCU thermal control */
write32(&mtk_infracfg->mcu_rst_set, BIT(12));
write32(&mtk_infracfg->mcu_rst_clr, BIT(12));
}
void lvts_thermal_cal_prepare(void)
{
u32 temp[LVTS_ADDRESS_INDEX_NUM];
int i;
bool efuse_calibrated = false;
enum lvts_sensor sensor_groups[] = {L_TS_LVTS1_0, L_TS_LVTS2_0,
L_TS_LVTS3_0, L_TS_LVTS4_0,
L_TS_LVTS5_0};
const size_t sensor_group_size = 4;
int idx;
for (i = 0; i < ARRAY_SIZE(temp); i++) {
temp[i] = read32(&mtk_efuse->lvts_reg[i]);
printk(BIOS_INFO, "[lvts_cali] %d: 0x%x\n", i, temp[i]);
if (temp[i] != 0)
efuse_calibrated = true;
}
/* 0x11F1_01A4,LVTS1 */
golden_temp = (temp[0] & GENMASK(7, 0));
idx = 0;
for (i = 0; i < ARRAY_SIZE(sensor_groups); i++) {
idx++;
for (int j = 0; j < sensor_group_size; j++) {
enum lvts_sensor sensor = sensor_groups[i] + j;
if (sensor >= L_TS_LVTS_NUM)
break;
ts_edata[sensor] = temp[idx++] & GENMASK(23, 0);
}
}
/* 0x11F1_01A4,LVTS1 */
op_cali[LVTS_MCU_CONTROLLER0] = ((temp[0] & GENMASK(31, 8)) >> 8);
/* 0x11F1_01B8,LVTS2 */
op_cali[LVTS_MCU_CONTROLLER1] = (temp[5] & GENMASK(23, 0));
/* 0x11F1_01CC,LVTS3 */
op_cali[LVTS_MCU_CONTROLLER2] = (temp[10] & GENMASK(23, 0));
/* 0x11F1_01E0,LVTS4 */
op_cali[LVTS_AP_CONTROLLER0] = (temp[15] & GENMASK(23, 0));
/* 0x11F1_01F4,LVTS5 */
op_cali[LVTS_MFG_CONTROLLER0] = (temp[20] & GENMASK(23, 0));
if (!efuse_calibrated) {
/* It means all efuse data are equal to 0 */
printk(BIOS_ERR,
"[lvts_cal] The efuses of this sample are all zero, "
"meaning it is not calibrated, fake!!!\n");
golden_temp = DEFAULT_EFUSE_GOLDEN_TEMP;
for (i = 0; i < L_TS_LVTS_NUM; i++)
ts_edata[i] = DEFAULT_EFUSE_COUNT;
for (i = 0; i < LVTS_CONTROLLER_NUM; i++)
op_cali[i] = DEFAULT_EFUSE_COUNT_RC;
}
printk(BIOS_INFO, "[lvts_cal] golden_temp = %d mdegC\n", golden_temp);
printk(BIOS_INFO, "[lvts_cal] num:ts_edata:op_cali ");
for (i = 0; i < ARRAY_SIZE(ts_edata); i++) {
if (i < ARRAY_SIZE(op_cali))
printk(BIOS_INFO, "%d:%d:%d ", i, ts_edata[i], op_cali[i]);
else
printk(BIOS_INFO, "%d:%d ", i, ts_edata[i]);
}
printk(BIOS_INFO, "\n");
write32(&lvts_tscpu_g_tc[0].regs->lvtsspare[1], golden_temp);
}
void lvts_device_identification(void)
{
u32 dev_id, data;
int i;
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
/* Enable LVTS_CTRL Clock */
write32(&tc->regs->lvtsclken_0, 0x00000001);
/* Reset All Devices */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0xFF, 0xFF, i);
/* Read back Dev_ID with Update */
lvts_write_device(0xC502, 0xFC, 0x55, i);
dev_id = 0x81 + i;
if (!retry(LVTS_READ_ID_RETRY_CNT,
(data = read32(&tc->regs->lvts_id_0) & GENMASK(7, 0)) == dev_id,
udelay(LVTS_READ_ID_DELAY_US)))
printk(BIOS_ERR,
"LVTS_TC_%d read timeout, addr:0x%lx, Device ID should be 0x%x,"
" but 0x%x\n",
i, (uintptr_t)(&tc->regs->lvts_id_0), dev_id, data);
}
}
void lvts_device_enable_init_all_devices(void)
{
int i;
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
/* Stop Counting (RG_TSFM_ST=0) */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x03, 0x00, i);
/* RG_TSFM_LPDLY[1:0]=2' 10 */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x07, 0xA6, i);
/* Set LVTS device counting window 20us */
/* Counting Window */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x05, 0x00, i);
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x04, 0x20, i);
/* TSV2F_CHOP_CKSEL & TSV2F_EN */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0A, 0x8C, i);
/* TSBG_DEM_CKSEL * TSBG_CHOP_EN */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0C, 0xFC, i);
/* Set TS_RSV */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x09, 0x8D, i);
/* Set TS_CHOP control */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x08, 0xF1, i);
}
}
static u32 lvts_read_device(u32 config, u32 dev_reg_idx, int tc_num)
{
u32 data;
u32 *lvts_config_reg = &lvts_tscpu_g_tc[tc_num].regs->lvts_config_0;
config |= (dev_reg_idx & 0xFF) << 8;
write32(lvts_config_reg, config);
/* Wait 2us + 3us buffer */
udelay(5);
if (!retry(CHECK_DEVICE_ACCESS_RETRY_CNT,
!(read32(lvts_config_reg) & DEVICE_ACCESS_START_BIT),
udelay(2)))
printk(BIOS_ERR,
"read err: DEVICE_ACCESS_START_BIT is not ready, "
"ASIF transaction not finished, reg0x%x\n",
dev_reg_idx);
data = read32(&lvts_tscpu_g_tc[tc_num].regs->lvtsrdata0_0);
return data;
}
static void lvts_device_check_counting_status(const struct lvts_thermal_controller *tc)
{
/*
* Check this when LVTS device is counting for a temperature or
* a RC (Resistor-Capacitor Calibration) now
*/
if (!retry(CHECK_DEVICE_ACCESS_RETRY_CNT,
!(read32(&tc->regs->lvts_config_0) & DEVICE_SENSING_STATUS),
udelay(2)))
printk(BIOS_ERR, "Error: DEVICE_SENSING_STATUS is not ready\n");
}
static void lvts_device_read_count_rc_n(void)
{
/* Perform RC (Resistor-Capacitor Calibration) and read current count (count_rc_n) */
int i, j, s_index;
u32 data;
/* Set LVTS MANUAL-RCK operation */
for (i = 0; i < LVTS_CONTROLLER_NUM; i++)
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0E, 0x00, i);
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
/* Set LVTS Manual-RCK operation */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0E, 0x00, i);
for (j = 0; j < tc->ts_number; j++) {
if (tc->sensor_on_off[j] == SEN_OFF)
continue;
s_index = tc->ts[j];
/* Select sensor-N with RCK */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0D, j, i);
/* Set Device Low-Power Single mode */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x06, 0x78, i);
/* Set TS_EN and DEV_EN */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x08, 0xF5, i);
/* Toggle VCO_RST */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x08, 0xFD, i);
/* Set TS_EN and DEV_EN */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x08, 0xF5, i);
/* wait 10us */
udelay(10);
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x03, 0x02, i);
/* polling counting status */
lvts_device_check_counting_status(tc);
/* disable TS_EN */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x08, 0xF1, i);
/* wait 40us at sensor0 */
/* 2us is margin for different IC */
if (j == 0)
udelay(42);
/* Get RCK count data (sensor-N) */
data = lvts_read_device(0xC1020000, 0x00, i);
/* wait 2us + 3us buffer */
udelay(5);
/* Get RCK value from LSB[23:0] */
count_rc_now[s_index] = data & GENMASK(23, 0);
/*
* Recover Setting for Normal Access on
* temperature fetch
*/
/* Select Sensor-N without RCK */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x0D, (0x10 | j), i);
}
}
printk(BIOS_INFO, "[COUNT_RC_NOW] ");
for (i = 0; i < L_TS_LVTS_NUM; i++)
printk(BIOS_INFO, "%d:%d ", i, count_rc_now[i]);
printk(BIOS_INFO, "\n");
}
void lvts_efuse_setting(void)
{
int i, j, s_index;
uint32_t efuse_data;
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
lvts_device_read_count_rc_n();
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
assert(tc->ts_number <= ARRAY_SIZE(tc->regs->lvtsedata));
for (j = 0; j < tc->ts_number; j++) {
if (tc->sensor_on_off[j] == SEN_OFF)
continue;
s_index = tc->ts[j];
efuse_data = ((u64)count_rc_now[s_index] * ts_edata[s_index]) >> 14;
write32(&tc->regs->lvtsedata[j], efuse_data);
printk(BIOS_INFO,
"efuse LVTSEDATA[%d]_%d %#x\n", j, i,
read32(&tc->regs->lvtsedata[j]));
}
}
}
void lvts_tscpu_thermal_read_tc_temp(const struct lvts_thermal_controller *tc, int order)
{
enum lvts_sensor ts_name = tc->ts[order];
int temperature;
assert(order < ARRAY_SIZE(tc->regs->lvtsmsr));
temperature = lvts_read_tc_raw_and_temp(&tc->regs->lvtsmsr[order],
ts_name,
golden_temp);
printk(BIOS_INFO,
"%s order %d ts_name %d temp %d mdegC\n",
__func__, order, ts_name, temperature);
}
void lvts_set_device_single_mode(int tc_num)
{
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x06, 0xF8, tc_num);
}
uint16_t lvts_temp_to_raw(int temp_mc, enum lvts_sensor ts_name)
{
/*
* MSR_RAW = ((temp_mc - GOLDEN_TEMP/2 - b) * 16384) / a
* a = -250.46
* b = 250.46
*/
uint32_t msr_raw;
int64_t temp1;
temp1 = (int64_t)golden_temp * 500 - LVTS_COEFF_A - temp_mc;
assert(temp1 >= 0);
msr_raw = ((temp1 << 14) / (-1 * LVTS_COEFF_A)) & 0xFFFF;
printk(BIOS_INFO, "%s msr_raw = %u, temp_mc = %d\n", __func__, msr_raw, temp_mc);
return msr_raw;
}
void thermal_init(void)
{
lvts_thermal_init();
thermal_sram_init();
}

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <soc/thermal.h>
void thermal_sram_init(void)
{
thermal_cls_sram();
thermal_stat_cls_sram();
}