soc/mediatek/mt8196: Add thermal driver
Add thermal driver to support LVTS (Low Voltage Thermal Sensor). BUG=b:317009620 TEST=Check temperatures read from each sensors. [INFO ] [LVTS_MSR] ts0 msr_all=14104, msr_temp=16644, temp=35694 [INFO ] lvts_tscpu_thermal_read_tc_temp order 0 ts_name 0 temp 35694 rg_temp 35697(36554) [INFO ] [LVTS_MSR] ts1 msr_all=14116, msr_temp=16662, temp=36088 [INFO ] lvts_tscpu_thermal_read_tc_temp order 1 ts_name 1 temp 36088 rg_temp 36091(36958) [INFO ] [LVTS_MSR] ts2 msr_all=140f6, msr_temp=16630, temp=35387 [INFO ] lvts_tscpu_thermal_read_tc_temp order 2 ts_name 2 temp 35387 rg_temp 35390(36240) [INFO ] [LVTS_MSR] ts3 msr_all=14105, msr_temp=16645, temp=35716 [INFO ] lvts_tscpu_thermal_read_tc_temp order 3 ts_name 3 temp 35716 rg_temp 35718(36576) [INFO ] [LVTS_MSR] ts4 msr_all=14129, msr_temp=16681, temp=36504 [INFO ] lvts_tscpu_thermal_read_tc_temp order 0 ts_name 4 temp 36504 rg_temp 36507(37384) [INFO ] [LVTS_MSR] ts5 msr_all=1412d, msr_temp=16685, temp=36592 [INFO ] lvts_tscpu_thermal_read_tc_temp order 1 ts_name 5 temp 36592 rg_temp 36595(37474) [INFO ] [LVTS_MSR] ts6 msr_all=140eb, msr_temp=16619, temp=35146 [INFO ] lvts_tscpu_thermal_read_tc_temp order 2 ts_name 6 temp 35146 rg_temp 35149(35993) [INFO ] [LVTS_MSR] ts7 msr_all=14126, msr_temp=16678, temp=36438 [INFO ] lvts_tscpu_thermal_read_tc_temp order 3 ts_name 7 temp 36438 rg_temp 36442(37317) Signed-off-by: Zhaoqing Jiu <zhaoqing.jiu@mediatek.corp-partner.google.com> Change-Id: Ieef94a6909e4da82461351bcb9292e9d01db3362 Reviewed-on: https://review.coreboot.org/c/coreboot/+/86017 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:
parent
38f6a68d2d
commit
c0f0be625b
7 changed files with 1008 additions and 0 deletions
|
|
@ -9,5 +9,6 @@ DECLARE_REGION(dram_dma)
|
|||
DECLARE_REGION(resv_mem_optee)
|
||||
DECLARE_REGION(resv_mem_gpu)
|
||||
DECLARE_REGION(resv_mem_gpueb)
|
||||
DECLARE_REGION(mcufw_reserved)
|
||||
|
||||
#endif /* _SOC_MEDIATEK_COMMON_SYMBOLS_H_ */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ romstage-y += ../common/pmif_clk.c pmif_clk.c
|
|||
romstage-y += ../common/pmif.c pmif_init.c
|
||||
romstage-y += pmif_spmi.c
|
||||
romstage-y += srclken_rc.c
|
||||
romstage-y += thermal.c
|
||||
romstage-y += thermal_sram.c
|
||||
|
||||
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c
|
||||
ramstage-y += ../common/dpm_v2.c
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ enum {
|
|||
APINFRA_MEM_CTRL_AO_DEBUG_BASE = IO_PHYS + 0x04125000,
|
||||
APIFRBUS_AO_MEM_REG_BASE = IO_PHYS + 0x04126000,
|
||||
THERM_CTRL_BASE = IO_PHYS + 0x04414000,
|
||||
INFRACFG_AO_SEC_BASE = IO_PHYS + 0x04461000,
|
||||
VOTE_BASE = IO_PHYS + 0x04500000,
|
||||
DBG_TRACKER_BASE = IO_PHYS + 0x04780000,
|
||||
INFRA_TRACKER_BASE = IO_PHYS + 0x047A0000,
|
||||
|
|
|
|||
9
src/soc/mediatek/mt8196/include/soc/thermal.h
Normal file
9
src/soc/mediatek/mt8196/include/soc/thermal.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
||||
|
||||
#ifndef SOC_MEDIATEK_MT8196_THERMAL_H
|
||||
#define SOC_MEDIATEK_MT8196_THERMAL_H
|
||||
|
||||
void thermal_sram_init(void);
|
||||
void thermal_init(void);
|
||||
|
||||
#endif /* SOC_MEDIATEK_MT8196_THERMAL_H */
|
||||
242
src/soc/mediatek/mt8196/include/soc/thermal_internal.h
Normal file
242
src/soc/mediatek/mt8196/include/soc/thermal_internal.h
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
||||
|
||||
#ifndef SOC_MEDIATEK_MT8196_THERMAL_INTERNAL_H
|
||||
#define SOC_MEDIATEK_MT8196_THERMAL_INTERNAL_H
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/mmio.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <soc/symbols.h>
|
||||
#include <soc/thermal.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define LVTS_MAGIC 0x0000555
|
||||
#define MAX_TS_NUMBER 4
|
||||
|
||||
/* private thermal sensor enum */
|
||||
enum lvts_sensor {
|
||||
L_TS_LVTS11_0 = 0, /* LVTS11-0 SOC-TOP */
|
||||
L_TS_LVTS11_1, /* LVTS11-1 SOC-TOP */
|
||||
L_TS_LVTS11_2, /* LVTS11-2 SOC-TOP */
|
||||
L_TS_LVTS11_3, /* LVTS11-3 SOC-TOP */
|
||||
L_TS_LVTS12_0, /* LVTS12-0 SOC-BOT */
|
||||
L_TS_LVTS12_1, /* LVTS12-1 SOC-BOT */
|
||||
L_TS_LVTS12_2, /* LVTS12-2 SOC-BOT */
|
||||
L_TS_LVTS12_3, /* LVTS12-3 SOC-BOT */
|
||||
L_TS_LVTS13_0, /* LVTS13-0 MD-AP */
|
||||
L_TS_LVTS13_1, /* LVTS13-1 MD-AP */
|
||||
L_TS_LVTS13_2, /* LVTS13-2 MD-AP */
|
||||
L_TS_LVTS13_3, /* LVTS13-3 MD-AP */
|
||||
L_TS_LVTS14_0, /* LVTS14-0 SOC-ADCT */
|
||||
L_TS_LVTS14_3, /* LVTS14-3 SOC-ADCT */
|
||||
L_TS_LVTS_NUM,
|
||||
};
|
||||
|
||||
enum lvts_tc {
|
||||
LVTS_AP_CONTROLLER0 = 0,
|
||||
LVTS_AP_CONTROLLER1,
|
||||
LVTS_AP_CONTROLLER2,
|
||||
LVTS_AP_CONTROLLER3,
|
||||
LVTS_CONTROLLER_NUM,
|
||||
};
|
||||
|
||||
enum lvts_tc_offset {
|
||||
TS_OFFSET_AP_CONTROLLER0 = 0,
|
||||
TS_OFFSET_AP_CONTROLLER1 = 0x100,
|
||||
TS_OFFSET_AP_CONTROLLER2 = 0x200,
|
||||
TS_OFFSET_AP_CONTROLLER3 = 0x300,
|
||||
};
|
||||
|
||||
enum sensor_switch_status {
|
||||
SEN_OFF,
|
||||
SEN_ON,
|
||||
};
|
||||
|
||||
enum controller_switch_status {
|
||||
CTRL_OFF,
|
||||
CTRL_ON,
|
||||
};
|
||||
|
||||
struct lvts_thermal_controller_speed {
|
||||
uint32_t group_interval_delay;
|
||||
uint32_t period_unit;
|
||||
uint32_t filter_interval_delay;
|
||||
uint32_t sensor_interval_delay;
|
||||
};
|
||||
|
||||
struct lvts_thermal_controller {
|
||||
enum lvts_sensor ts[MAX_TS_NUMBER];
|
||||
enum sensor_switch_status sensor_on_off[MAX_TS_NUMBER];
|
||||
enum controller_switch_status ctrl_on_off;
|
||||
size_t ts_number;
|
||||
int reboot_temperature;
|
||||
int dominator_ts_idx;
|
||||
struct lvts_thermal_controller_speed speed;
|
||||
struct mtk_thermal_controller_regs *regs;
|
||||
};
|
||||
|
||||
/* LVTS Thermal Controller Register Definition */
|
||||
static struct mtk_thermal_controller_regs *const
|
||||
mtk_lvts_ap_controller0 = (void *)(THERM_CTRL_BASE + TS_OFFSET_AP_CONTROLLER0);
|
||||
static struct mtk_thermal_controller_regs *const
|
||||
mtk_lvts_ap_controller1 = (void *)(THERM_CTRL_BASE + TS_OFFSET_AP_CONTROLLER1);
|
||||
static struct mtk_thermal_controller_regs *const
|
||||
mtk_lvts_ap_controller2 = (void *)(THERM_CTRL_BASE + TS_OFFSET_AP_CONTROLLER2);
|
||||
static struct mtk_thermal_controller_regs *const
|
||||
mtk_lvts_ap_controller3 = (void *)(THERM_CTRL_BASE + TS_OFFSET_AP_CONTROLLER3);
|
||||
|
||||
struct mtk_thermal_controller_regs {
|
||||
u32 lvtsmonctl0_0;
|
||||
u32 lvtsmonctl1_0;
|
||||
u32 lvtsmonctl2_0;
|
||||
u32 lvtsmonint_0;
|
||||
u32 lvtsmonintsts_0;
|
||||
u32 lvtsmonidet0_0;
|
||||
u32 lvtsmonidet1_0;
|
||||
u32 lvtsmonidet2_0;
|
||||
u32 lvtsmonidet3_0;
|
||||
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 lvtsdeviceto_0;
|
||||
u32 lvtscalscale_0;
|
||||
u32 lvts_id_0;
|
||||
u32 lvts_config_0;
|
||||
u32 lvtsedata[4];
|
||||
u32 reserved0[1];
|
||||
u32 lvtsgslope_0;
|
||||
u32 lvtsmsroft_0;
|
||||
u32 lvtsatp[4];
|
||||
u32 reserved1[4];
|
||||
u32 lvtsmsr[4];
|
||||
u32 lvtsimmd[4];
|
||||
u32 lvtsrdata[4];
|
||||
u32 lvtsprotctl_0;
|
||||
u32 lvtsprotta_0;
|
||||
u32 lvtsprottb_0;
|
||||
u32 lvtsprottc_0;
|
||||
u32 reserved2[1];
|
||||
u32 lvtstemp[4];
|
||||
u32 lvtsclken_0;
|
||||
u32 lvtsdbgsel_0;
|
||||
u32 lvtsdbgsig_0;
|
||||
u32 lvtsspare[4];
|
||||
};
|
||||
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonctl0_0, 0x000);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonctl1_0, 0x004);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonctl2_0, 0x008);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonint_0, 0x00c);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonintsts_0, 0x010);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonidet0_0, 0x014);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonidet1_0, 0x018);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonidet2_0, 0x01c);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmonidet3_0, 0x020);
|
||||
check_member(mtk_thermal_controller_regs, lvtsh2nthre_0, 0x024);
|
||||
check_member(mtk_thermal_controller_regs, lvtshthre_0, 0x028);
|
||||
check_member(mtk_thermal_controller_regs, lvtscthre_0, 0x02c);
|
||||
check_member(mtk_thermal_controller_regs, lvtsoffseth_0, 0x030);
|
||||
check_member(mtk_thermal_controller_regs, lvtsoffsetl_0, 0x034);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmsrctl0_0, 0x038);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmsrctl1_0, 0x03c);
|
||||
check_member(mtk_thermal_controller_regs, lvtstssel_0, 0x040);
|
||||
check_member(mtk_thermal_controller_regs, lvtsdeviceto_0, 0x044);
|
||||
check_member(mtk_thermal_controller_regs, lvtscalscale_0, 0x048);
|
||||
check_member(mtk_thermal_controller_regs, lvts_id_0, 0x04c);
|
||||
check_member(mtk_thermal_controller_regs, lvts_config_0, 0x050);
|
||||
check_member(mtk_thermal_controller_regs, lvtsedata, 0x054);
|
||||
check_member(mtk_thermal_controller_regs, lvtsgslope_0, 0x068);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmsroft_0, 0x06c);
|
||||
check_member(mtk_thermal_controller_regs, lvtsatp, 0x070);
|
||||
check_member(mtk_thermal_controller_regs, lvtsmsr, 0x090);
|
||||
check_member(mtk_thermal_controller_regs, lvtsimmd, 0x0a0);
|
||||
check_member(mtk_thermal_controller_regs, lvtsrdata, 0x0b0);
|
||||
check_member(mtk_thermal_controller_regs, lvtsprotctl_0, 0x0c0);
|
||||
check_member(mtk_thermal_controller_regs, lvtsprotta_0, 0x0c4);
|
||||
check_member(mtk_thermal_controller_regs, lvtsprottb_0, 0x0c8);
|
||||
check_member(mtk_thermal_controller_regs, lvtsprottc_0, 0x0cc);
|
||||
check_member(mtk_thermal_controller_regs, lvtstemp, 0x0d4);
|
||||
check_member(mtk_thermal_controller_regs, lvtsclken_0, 0x0e4);
|
||||
check_member(mtk_thermal_controller_regs, lvtsdbgsel_0, 0x0e8);
|
||||
check_member(mtk_thermal_controller_regs, lvtsdbgsig_0, 0x0ec);
|
||||
check_member(mtk_thermal_controller_regs, lvtsspare, 0x0f0);
|
||||
|
||||
#define LDO_ON_SETTING 0x1108
|
||||
|
||||
#define AP_RST_SET (INFRACFG_AO_SEC_BASE + 0xf30)
|
||||
#define AP_RST_CLR (INFRACFG_AO_SEC_BASE + 0xf34)
|
||||
|
||||
#define LVTS_COF_T_SLP_GLD 358830
|
||||
#define LVTS_COF_COUNT_R_GLD 34389
|
||||
#define LVTS_COF_T_CONST_OFS 0
|
||||
|
||||
#define DEFAULT_EFUSE_GOLDEN_TEMP 60
|
||||
#define DEFAULT_EFUSE_COUNT 34389
|
||||
#define DEFAULT_EFUSE_COUNT_RC 24173
|
||||
|
||||
#define HIGH_OFFSET3_INT_EN BIT(25)
|
||||
#define HIGH_OFFSET2_INT_EN BIT(13)
|
||||
#define HIGH_OFFSET1_INT_EN BIT(8)
|
||||
#define HIGH_OFFSET0_INT_EN BIT(3)
|
||||
|
||||
#define LOW_OFFSET3_INT_EN BIT(24)
|
||||
#define LOW_OFFSET2_INT_EN BIT(12)
|
||||
#define LOW_OFFSET1_INT_EN BIT(7)
|
||||
#define LOW_OFFSET0_INT_EN BIT(2)
|
||||
|
||||
#define HOT_INT3_EN BIT(23)
|
||||
#define HOT_INT2_EN BIT(11)
|
||||
#define HOT_INT1_EN BIT(6)
|
||||
#define HOT_INT0_EN BIT(1)
|
||||
|
||||
#define COLD_INT3_EN BIT(22)
|
||||
#define COLD_INT2_EN BIT(10)
|
||||
#define COLD_INT1_EN BIT(5)
|
||||
#define COLD_INT0_EN BIT(0)
|
||||
|
||||
#define STAGE3_INT_EN BIT(31)
|
||||
|
||||
#define DEVICE_ACCESS_START_BIT BIT(24)
|
||||
|
||||
#define CPU_LVTS_RESET_ADDR (MCUCFG_BASE + 0x610)
|
||||
|
||||
/* chip dependent */
|
||||
#define LVTS_ADDRESS_INDEX_0 (EFUSEC_BASE + 0x334)
|
||||
#define LVTS_ADDRESS_INDEX_1 (EFUSEC_BASE + 0x338)
|
||||
#define LVTS_ADDRESS_INDEX_2 (EFUSEC_BASE + 0x33C)
|
||||
#define LVTS_ADDRESS_INDEX_3 (EFUSEC_BASE + 0x340)
|
||||
#define LVTS_ADDRESS_INDEX_4 (EFUSEC_BASE + 0x344)
|
||||
#define LVTS_ADDRESS_INDEX_5 (EFUSEC_BASE + 0x348)
|
||||
#define LVTS_ADDRESS_INDEX_6 (EFUSEC_BASE + 0x34C)
|
||||
#define LVTS_ADDRESS_INDEX_7 (EFUSEC_BASE + 0x350)
|
||||
#define LVTS_ADDRESS_INDEX_8 (EFUSEC_BASE + 0x354)
|
||||
#define LVTS_ADDRESS_INDEX_9 (EFUSEC_BASE + 0x358)
|
||||
#define LVTS_ADDRESS_INDEX_10 (EFUSEC_BASE + 0x35C)
|
||||
#define LVTS_ADDRESS_INDEX_11 (EFUSEC_BASE + 0x360)
|
||||
#define LVTS_ADDRESS_INDEX_12 (EFUSEC_BASE + 0x364)
|
||||
#define LVTS_ADDRESS_INDEX_13 (EFUSEC_BASE + 0x368)
|
||||
#define LVTS_ADDRESS_INDEX_14 (EFUSEC_BASE + 0x36C)
|
||||
#define LVTS_ADDRESS_INDEX_15 (EFUSEC_BASE + 0x370)
|
||||
#define LVTS_ADDRESS_INDEX_16 (EFUSEC_BASE + 0x374)
|
||||
#define LVTS_ADDRESS_INDEX_17 (EFUSEC_BASE + 0x378)
|
||||
#define LVTS_ADDRESS_INDEX_18 (EFUSEC_BASE + 0x37C)
|
||||
#define LVTS_ADDRESS_INDEX_19 (EFUSEC_BASE + 0x380)
|
||||
#define LVTS_ADDRESS_INDEX_20 (EFUSEC_BASE + 0x384)
|
||||
#define LVTS_ADDRESS_INDEX_21 (EFUSEC_BASE + 0x388)
|
||||
#define LVTS_ADDRESS_INDEX_22 (EFUSEC_BASE + 0x38C)
|
||||
#define LVTS_ADDRESS_INDEX_23 (EFUSEC_BASE + 0x390)
|
||||
#define LVTS_ADDRESS_INDEX_24 (EFUSEC_BASE + 0x394)
|
||||
#define LVTS_ADDRESS_INDEX_25 (EFUSEC_BASE + 0x398)
|
||||
#define LVTS_ADDRESS_INDEX_26 (EFUSEC_BASE + 0x39C)
|
||||
#define LVTS_ADDRESS_INDEX_27 (EFUSEC_BASE + 0x3A0)
|
||||
#define LVTS_ADDRESS_INDEX_28 (EFUSEC_BASE + 0x3A4)
|
||||
#define LVTS_ADDRESS_INDEX_29 (EFUSEC_BASE + 0x3A8)
|
||||
#define LVTS_ADDRESS_INDEX_30 (EFUSEC_BASE + 0x3AC)
|
||||
#define LVTS_ADDRESS_INDEX_31 (EFUSEC_BASE + 0x3B0)
|
||||
|
||||
#endif /* SOC_MEDIATEK_MT8196_THERMAL_INTERNAL_H */
|
||||
692
src/soc/mediatek/mt8196/thermal.c
Normal file
692
src/soc/mediatek/mt8196/thermal.c
Normal file
|
|
@ -0,0 +1,692 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
||||
|
||||
#include <assert.h>
|
||||
#include <console/console.h>
|
||||
#include <delay.h>
|
||||
#include <soc/thermal.h>
|
||||
#include <soc/thermal_internal.h>
|
||||
|
||||
#define LVTS_DEVICE_ACCESS_DELAY_US 3
|
||||
#define CHECK_DEVICE_ACCESS_RETRY_CNT 100
|
||||
#define THERMAL_LVTS_MSR_OFT 64552
|
||||
#define LVTS_READ_ID_DELAY_US 3
|
||||
#define LVTS_READ_ID_RETRY_CNT 5
|
||||
#define LVTS_SINGLE_SENSE_MODE_EN BIT(9)
|
||||
#define CHECK_SENSING_POINTS_IDLE_RETRY_CNT 100
|
||||
#define LVTS_DEVICE_WRITE_CONFIG 0x8103
|
||||
#define LVTS_DEVICE_READ_CONFIG 0x8502
|
||||
#define LVTS_SENSOR_POINT_SELECTION_SETTING 0x13121110
|
||||
#define LVTS_CALCULATION_SCALING_RULE 0x00000300
|
||||
|
||||
/*
|
||||
* module LVTS Plan
|
||||
*=====================================================
|
||||
* Dsu0, Core3, Core7_0/1 LVTS1-0, LVTS1-1, LVTS1-2, LVTS1-3
|
||||
* Core4_0/1, Core1, Core2 LVTS2-0, LVTS2-1, LVTS2-2, LVTS2-3
|
||||
* Dsu2, Dsu1, Core6_0/1 LVTS3-0, LVTS3-1, LVTS3-2, LVTS3-3
|
||||
* Dsu3, Core0, Core5_0/1 LVTS4-0, LVTS4-1, LVTS4-2, LVTS4-3
|
||||
* APUa LVTS5-0, LVTS5-1, LVTS5-2, LVTS5-3
|
||||
* GPUa LVTS7-0, LVTS7-1
|
||||
* SOC-TOP LVTS11-0, LVTS11-1, LVTS11-2, LVTS11-3
|
||||
* SOC-BOT LVTS12-0, LVTS12-1, LVTS12-2, LVTS12-3
|
||||
* MD-AP LVTS13-0, LVTS13-1, LVTS13-2, LVTS13-3
|
||||
* SOC-ADCT LVTS14-0, LVTS14-3
|
||||
* ptp_therm_ctrl_AP Base address: 0x1441_4000, 0x1441_4100,
|
||||
* 0x1441_4200
|
||||
* ptp_therm_ctrl_MCU Base address: 0x0C23_0000, 0x0C23_0100,
|
||||
* 0x0C23_0200, 0x0C23_0300,
|
||||
*/
|
||||
static const struct lvts_thermal_controller lvts_tscpu_g_tc[LVTS_CONTROLLER_NUM] = {
|
||||
[LVTS_AP_CONTROLLER0] = { /* SOC-TOP */
|
||||
.ts = {L_TS_LVTS11_0, L_TS_LVTS11_1, L_TS_LVTS11_2, L_TS_LVTS11_3},
|
||||
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
|
||||
.ctrl_on_off = CTRL_ON,
|
||||
.ts_number = 4,
|
||||
.reboot_temperature = 118800,
|
||||
.dominator_ts_idx = 0,
|
||||
.speed = {
|
||||
.group_interval_delay = 0x7fff,
|
||||
.period_unit = 0x001,
|
||||
.filter_interval_delay = 0x001,
|
||||
.sensor_interval_delay = 0x001,
|
||||
},
|
||||
.regs = mtk_lvts_ap_controller0,
|
||||
},
|
||||
[LVTS_AP_CONTROLLER1] = { /* SOC-BOT */
|
||||
.ts = {L_TS_LVTS12_0, L_TS_LVTS12_1, L_TS_LVTS12_2, L_TS_LVTS12_3},
|
||||
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
|
||||
.ctrl_on_off = CTRL_ON,
|
||||
.ts_number = 4,
|
||||
.reboot_temperature = 118800,
|
||||
.dominator_ts_idx = 0,
|
||||
.speed = {
|
||||
.group_interval_delay = 0x7fff,
|
||||
.period_unit = 0x001,
|
||||
.filter_interval_delay = 0x001,
|
||||
.sensor_interval_delay = 0x001,
|
||||
},
|
||||
.regs = mtk_lvts_ap_controller1,
|
||||
},
|
||||
[LVTS_AP_CONTROLLER2] = { /* MD-AP */
|
||||
.ts = {L_TS_LVTS13_0, L_TS_LVTS13_1, L_TS_LVTS13_2, L_TS_LVTS13_3},
|
||||
.sensor_on_off = {SEN_ON, SEN_ON, SEN_ON, SEN_ON},
|
||||
.ctrl_on_off = CTRL_OFF,
|
||||
.ts_number = 4,
|
||||
.reboot_temperature = 118800,
|
||||
.dominator_ts_idx = 0,
|
||||
.speed = {
|
||||
.group_interval_delay = 0x7fff,
|
||||
.period_unit = 0x001,
|
||||
.filter_interval_delay = 0x001,
|
||||
.sensor_interval_delay = 0x001,
|
||||
},
|
||||
.regs = mtk_lvts_ap_controller2,
|
||||
},
|
||||
[LVTS_AP_CONTROLLER3] = { /* SOC-ADCT */
|
||||
.ts = {L_TS_LVTS14_0, L_TS_LVTS14_3},
|
||||
.sensor_on_off = {SEN_ON, SEN_ON},
|
||||
.ctrl_on_off = CTRL_OFF,
|
||||
.ts_number = 2,
|
||||
.reboot_temperature = 118800,
|
||||
.dominator_ts_idx = 0,
|
||||
.speed = {
|
||||
.group_interval_delay = 0x7fff,
|
||||
.period_unit = 0x001,
|
||||
.filter_interval_delay = 0x001,
|
||||
.sensor_interval_delay = 0x001,
|
||||
},
|
||||
.regs = mtk_lvts_ap_controller3,
|
||||
},
|
||||
};
|
||||
|
||||
static uint32_t golden_temp;
|
||||
static uint32_t ts_edata[L_TS_LVTS_NUM];
|
||||
static uint8_t op_cali[LVTS_CONTROLLER_NUM];
|
||||
|
||||
static int lvts_write_device(uint16_t config, uint8_t dev_reg_idx, uint8_t data, int tc_num)
|
||||
{
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[tc_num];
|
||||
uint32_t config_data = (config << 16) | (dev_reg_idx << 8) | data;
|
||||
|
||||
write32(&tc->regs->lvts_config_0, config_data);
|
||||
|
||||
/*
|
||||
* LVTS Device Register Setting takes 1us (by 26MHz clock source)
|
||||
* interface latency to access.
|
||||
* So we set 2~3 us delay could guarantee access complete.
|
||||
*/
|
||||
udelay(LVTS_DEVICE_ACCESS_DELAY_US);
|
||||
|
||||
/*
|
||||
* Check ASIF bus status for transaction finished
|
||||
* Wait until DEVICE_ACCESS_START = 0
|
||||
*/
|
||||
if (!retry(CHECK_DEVICE_ACCESS_RETRY_CNT,
|
||||
!(read32(&tc->regs->lvts_config_0) & DEVICE_ACCESS_START_BIT), udelay(2))) {
|
||||
printk(BIOS_ERR, "DEVICE_ACCESS_START didn't ready, reg0x%x\n",
|
||||
dev_reg_idx);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvts_raw_to_temp(uint16_t msr_raw, enum lvts_sensor ts_name)
|
||||
{
|
||||
/* In millidegree Celsius */
|
||||
int temp_mc;
|
||||
int64_t temp1, coff_a;
|
||||
|
||||
coff_a = LVTS_COF_T_SLP_GLD;
|
||||
|
||||
temp1 = (coff_a * msr_raw) / (1 << 14);
|
||||
temp_mc = temp1 + golden_temp * 500 - coff_a;
|
||||
|
||||
return temp_mc;
|
||||
}
|
||||
|
||||
/*
|
||||
* The return value is NOT the same as the argument `msr_raw` of lvts_raw_to_temp.
|
||||
* Instead, it is equal to "(1 << 28) / msr_raw".
|
||||
*/
|
||||
static uint16_t lvts_temp_to_raw(int temp_mc, enum lvts_sensor ts_name)
|
||||
{
|
||||
uint32_t msr_raw = 0;
|
||||
int64_t coff_a = 0;
|
||||
int64_t temp1;
|
||||
|
||||
coff_a = LVTS_COF_T_SLP_GLD;
|
||||
|
||||
temp1 = (int64_t)temp_mc - (golden_temp * 500) + coff_a;
|
||||
assert(temp1 > 0);
|
||||
msr_raw = ((coff_a << 14) / temp1) & 0xFFFF;
|
||||
|
||||
printk(BIOS_DEBUG, "%s: msr_raw=%u, temp_mc=%d\n", __func__, msr_raw, temp_mc);
|
||||
|
||||
return msr_raw;
|
||||
}
|
||||
|
||||
static void lvts_efuse_setting(void)
|
||||
{
|
||||
int i, j, s_index;
|
||||
uint32_t efuse_data;
|
||||
uint32_t val_0, val_1;
|
||||
|
||||
printk(BIOS_INFO, "%s\n", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
val_0 = 0;
|
||||
val_1 = 0;
|
||||
for (j = 0; j < tc->ts_number; j++) {
|
||||
if (tc->sensor_on_off[j] == SEN_OFF)
|
||||
continue;
|
||||
|
||||
s_index = tc->ts[j];
|
||||
|
||||
efuse_data = ts_edata[s_index] + THERMAL_LVTS_MSR_OFT;
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
write32(&tc->regs->lvtsedata[0], efuse_data);
|
||||
printk(BIOS_INFO, "efuse LVTSEDATA00_%d %#x\n", i,
|
||||
read32(&tc->regs->lvtsedata[0]));
|
||||
val_0 |= ((LVTS_COF_T_SLP_GLD + 500) / 1000);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
write32(&tc->regs->lvtsedata[1], efuse_data);
|
||||
printk(BIOS_INFO, "efuse LVTSEDATA01_%d %#x\n", i,
|
||||
read32(&tc->regs->lvtsedata[1]));
|
||||
val_0 |= (((LVTS_COF_T_SLP_GLD + 500) / 1000) << 10);
|
||||
break;
|
||||
case 2:
|
||||
write32(&tc->regs->lvtsedata[2], efuse_data);
|
||||
printk(BIOS_INFO, "efuse LVTSEDATA02_%d %#x\n", i,
|
||||
read32(&tc->regs->lvtsedata[2]));
|
||||
val_1 |= ((LVTS_COF_T_SLP_GLD + 500) / 1000);
|
||||
break;
|
||||
case 3:
|
||||
write32(&tc->regs->lvtsedata[3], efuse_data);
|
||||
printk(BIOS_INFO, "efuse LVTSEDATA03_%d %#x\n", i,
|
||||
read32(&tc->regs->lvtsedata[3]));
|
||||
val_1 |= (((LVTS_COF_T_SLP_GLD + 500) / 1000) << 10);
|
||||
break;
|
||||
default:
|
||||
printk(BIOS_ERR, "%s, illegal ts order : %d!!\n", __func__, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
val_0 |= (golden_temp << 20);
|
||||
printk(BIOS_INFO, "%s, spare setting: %#x, %#x\n", __func__, val_0, val_1);
|
||||
write32(&tc->regs->lvtsmsroft_0, THERMAL_LVTS_MSR_OFT);
|
||||
write32(&tc->regs->lvtsspare[1], val_0);
|
||||
write32(&tc->regs->lvtsspare[2], val_1);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_device_identification(void)
|
||||
{
|
||||
uint32_t dev_id, data;
|
||||
int i;
|
||||
|
||||
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
/* Enable LVTS_CTRL Clock */
|
||||
write32(&tc->regs->lvtsclken_0, 0x00000001);
|
||||
|
||||
/* Turn On LDO & set DIV_MODE and wait 10 us */
|
||||
write32(&tc->regs->lvtsgslope_0, LDO_ON_SETTING);
|
||||
udelay(10);
|
||||
|
||||
/* Reset All Devices */
|
||||
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0xFF, 0xFF, i);
|
||||
|
||||
/* Read back Dev_ID with Update */
|
||||
lvts_write_device(LVTS_DEVICE_READ_CONFIG, 0xFC, 0x55, i);
|
||||
|
||||
dev_id = 0x8B + 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_device_enable_init_all_devices(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t cali_0, cali_1;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
/* Stop Counting (RG_TSFM_ST=0) */
|
||||
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x03, 0x00, i);
|
||||
|
||||
/* Set Bandgap Calibration */
|
||||
if ((op_cali[i] & (1 << 5)) != 0) {
|
||||
cali_0 = (op_cali[i] & 0xf) << 4;
|
||||
cali_1 = ((op_cali[i] >> 4) & 1) << 4;
|
||||
} else {
|
||||
cali_0 = (op_cali[i] & 0xf);
|
||||
cali_1 = ((op_cali[i] >> 4) & 1) << 3;
|
||||
}
|
||||
cali_1 |= 0xA0;
|
||||
|
||||
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x20, cali_0, i);
|
||||
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x21, cali_1, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_thermal_cal_prepare(void)
|
||||
{
|
||||
uint32_t temp[7];
|
||||
int i, j;
|
||||
bool efuse_calibrated = false;
|
||||
|
||||
temp[0] = read32p(LVTS_ADDRESS_INDEX_0);
|
||||
temp[1] = read32p(LVTS_ADDRESS_INDEX_12);
|
||||
temp[2] = read32p(LVTS_ADDRESS_INDEX_13);
|
||||
temp[3] = read32p(LVTS_ADDRESS_INDEX_14);
|
||||
temp[4] = read32p(LVTS_ADDRESS_INDEX_15);
|
||||
temp[5] = read32p(LVTS_ADDRESS_INDEX_27);
|
||||
temp[6] = read32p(LVTS_ADDRESS_INDEX_28);
|
||||
|
||||
printk(BIOS_INFO,
|
||||
"[lvts_cali] %d: %#x, %d: %#x, %d: %#x, %d: %#x, %d: %#x, %d: %#x, %d: %#x\n",
|
||||
0, temp[0], 1, temp[1], 2, temp[2], 3, temp[3], 4, temp[4], 5, temp[5], 6, temp[6]);
|
||||
|
||||
golden_temp = temp[0] & GENMASK(7, 0);
|
||||
|
||||
ts_edata[L_TS_LVTS11_0] = (temp[1] & GENMASK(31, 16)) >> 16;
|
||||
ts_edata[L_TS_LVTS11_1] = temp[1] & GENMASK(15, 0);
|
||||
ts_edata[L_TS_LVTS11_2] = (temp[2] & GENMASK(31, 16)) >> 16;
|
||||
ts_edata[L_TS_LVTS11_3] = temp[2] & GENMASK(15, 0);
|
||||
ts_edata[L_TS_LVTS12_0] = (temp[3] & GENMASK(31, 16)) >> 16;
|
||||
ts_edata[L_TS_LVTS12_1] = temp[3] & GENMASK(15, 0);
|
||||
ts_edata[L_TS_LVTS12_2] = (temp[4] & GENMASK(31, 16)) >> 16;
|
||||
ts_edata[L_TS_LVTS12_3] = temp[4] & GENMASK(15, 0);
|
||||
op_cali[LVTS_AP_CONTROLLER0] = (temp[5] & GENMASK(29, 24)) >> 24;
|
||||
op_cali[LVTS_AP_CONTROLLER1] = (temp[6] & GENMASK(29, 24)) >> 24;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(temp); i++) {
|
||||
if (temp[i] != 0) {
|
||||
efuse_calibrated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!efuse_calibrated) {
|
||||
/* It means all efuse data are equal to 0 */
|
||||
printk(BIOS_ERR, "[lvts_cal] This sample is not calibrated; Use fake efuse\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] = 0;
|
||||
}
|
||||
printk(BIOS_INFO, "[lvts_cal] golden_temp = %d\n", golden_temp);
|
||||
|
||||
printk(BIOS_INFO, "[lvts_cal] num:ts_edata ");
|
||||
for (i = 0; i < L_TS_LVTS_NUM; i++)
|
||||
printk(BIOS_INFO, "%d:%d ", i, ts_edata[i]);
|
||||
printk(BIOS_INFO, "\n");
|
||||
|
||||
printk(BIOS_INFO, "num:op_cali ");
|
||||
for (j = 0; j < LVTS_CONTROLLER_NUM; j++)
|
||||
printk(BIOS_INFO, "%d:0x%x ", j, op_cali[j]);
|
||||
|
||||
printk(BIOS_INFO, "\n");
|
||||
|
||||
write32(&lvts_tscpu_g_tc[LVTS_AP_CONTROLLER0].regs->lvtsspare[1], golden_temp);
|
||||
}
|
||||
|
||||
static int lvts_read_tc_raw_and_temp(void *msr_reg, enum lvts_sensor ts_name)
|
||||
{
|
||||
int temp;
|
||||
uint32_t msr_data;
|
||||
uint16_t msr_raw;
|
||||
|
||||
msr_data = read32(msr_reg);
|
||||
msr_raw = msr_data & 0xFFFF;
|
||||
|
||||
if (msr_raw > 0) {
|
||||
temp = lvts_raw_to_temp(msr_raw, ts_name);
|
||||
} else {
|
||||
/*
|
||||
* 26111 is magic num.
|
||||
* This is to keep system alive for a while to wait until
|
||||
* HW init is done, because 0 msr raw will translate to 28x'C
|
||||
* and then 28x'C will trigger a SW reset.
|
||||
*
|
||||
* If HW init finishes, this msr raw will not be 0,
|
||||
* system can report normal temperature.
|
||||
* If wait over 60 times zero, this means something wrong with HW.
|
||||
*/
|
||||
temp = 26111;
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "[LVTS_MSR] ts%d msr_all=%x, msr_temp=%d, temp=%d\n", ts_name,
|
||||
msr_data, msr_raw, temp);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void lvts_tscpu_thermal_read_tc_temp(const struct lvts_thermal_controller *tc, int order)
|
||||
{
|
||||
uint32_t rg_temp;
|
||||
enum lvts_sensor ts_name = tc->ts[order];
|
||||
int temperature;
|
||||
|
||||
ASSERT(order < ARRAY_SIZE(tc->regs->lvtsatp));
|
||||
|
||||
temperature = lvts_read_tc_raw_and_temp(&tc->regs->lvtsatp[order], ts_name);
|
||||
rg_temp = read32(&tc->regs->lvtstemp[order]) & 0x7FFFFF;
|
||||
|
||||
printk(BIOS_INFO, "%s order %d ts_name %d temp %d rg_temp %d(%d)\n", __func__, order,
|
||||
ts_name, temperature, (rg_temp * 1000 / 1024), rg_temp);
|
||||
}
|
||||
|
||||
static void read_all_tc_lvts_temperature(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < tc->ts_number; j++)
|
||||
lvts_tscpu_thermal_read_tc_temp(tc, j);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_enable_sensing_points(const struct lvts_thermal_controller *tc)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
|
||||
uint32_t value = LVTS_SINGLE_SENSE_MODE_EN;
|
||||
|
||||
for (i = 0; i < tc->ts_number; i++) {
|
||||
if (tc->sensor_on_off[i] == SEN_ON)
|
||||
value |= BIT(i);
|
||||
}
|
||||
|
||||
write32(&tc->regs->lvtsmonctl0_0, value);
|
||||
|
||||
printk(BIOS_INFO, "%s, value in LVTSMONCTL0_0 = %#x\n", __func__, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* disable ALL periodoc temperature sensing point
|
||||
*/
|
||||
static void lvts_disable_all_sensing_points(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
printk(BIOS_INFO, "%s\n", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
write32(&tc->regs->lvtsmonctl0_0, LVTS_SINGLE_SENSE_MODE_EN);
|
||||
}
|
||||
}
|
||||
|
||||
static int lvts_check_all_sensing_points_idle(void)
|
||||
{
|
||||
uint32_t mask, temp;
|
||||
int i;
|
||||
|
||||
mask = BIT(10) | BIT(7) | BIT(0);
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
temp = read32(&tc->regs->lvtsmsrctl1_0);
|
||||
if ((temp & mask) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lvts_wait_all_sensing_points_idle(void)
|
||||
{
|
||||
if (!retry(CHECK_SENSING_POINTS_IDLE_RETRY_CNT,
|
||||
lvts_check_all_sensing_points_idle() == 0,
|
||||
udelay(2)))
|
||||
printk(BIOS_ERR, "%s timeout\n", __func__);
|
||||
}
|
||||
|
||||
static void lvts_enable_all_sensing_points(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
printk(BIOS_INFO, "%s\n", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
lvts_enable_sensing_points(tc);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_set_init_flag(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(BIOS_INFO, "%s\n", __func__);
|
||||
|
||||
/* write init done flag to inform kernel */
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
printk(BIOS_INFO, "%s %d:%zu, tc_base_addr:%p\n", __func__, i,
|
||||
tc->ts_number, tc->regs);
|
||||
|
||||
write32(&tc->regs->lvtsspare[0], LVTS_MAGIC);
|
||||
}
|
||||
}
|
||||
|
||||
static void lvts_configure_polling_speed_and_filter(const struct lvts_thermal_controller *tc)
|
||||
{
|
||||
uint32_t lvts_mon_ctl1, lvts_mon_ctl2;
|
||||
|
||||
lvts_mon_ctl1 = (((tc->speed.group_interval_delay << 17) & GENMASK(31, 17)) |
|
||||
(tc->speed.period_unit & GENMASK(9, 0)));
|
||||
|
||||
lvts_mon_ctl2 = (((tc->speed.filter_interval_delay << 16) & GENMASK(25, 16)) |
|
||||
(tc->speed.sensor_interval_delay & GENMASK(9, 0)));
|
||||
|
||||
/*
|
||||
* Calculate period unit in Module clock x 256, and the Module clock
|
||||
* will be changed to 26M when Infrasys enters Sleep mode.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bus clock 66M counting unit is
|
||||
* 12 * 1/66M * 256 = 12 * 3.879us = 46.545 us
|
||||
*/
|
||||
write32(&tc->regs->lvtsmonctl1_0, lvts_mon_ctl1);
|
||||
/*
|
||||
* filt interval is 1 * 46.545us = 46.545us,
|
||||
* sen interval is 429 * 46.545us = 19.968ms
|
||||
*/
|
||||
write32(&tc->regs->lvtsmonctl2_0, lvts_mon_ctl2);
|
||||
|
||||
/* temperature sampling control, 1 sample */
|
||||
write32(&tc->regs->lvtsmsrctl0_0, 0);
|
||||
|
||||
udelay(1);
|
||||
printk(BIOS_INFO, "%s, LVTSMONCTL1_0= 0x%x,LVTSMONCTL2_0= 0x%x,LVTSMSRCTL0_0= 0x%x\n",
|
||||
__func__, read32(&tc->regs->lvtsmonctl1_0), read32(&tc->regs->lvtsmonctl2_0),
|
||||
read32(&tc->regs->lvtsmsrctl0_0));
|
||||
}
|
||||
|
||||
static void lvts_tscpu_thermal_initial_all_tc(void)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
printk(BIOS_INFO, "%s\n", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
/* set sensor index of LVTS */
|
||||
write32(&tc->regs->lvtstssel_0, LVTS_SENSOR_POINT_SELECTION_SETTING);
|
||||
/* set calculation scale rules */
|
||||
write32(&tc->regs->lvtscalscale_0, LVTS_CALCULATION_SCALING_RULE);
|
||||
|
||||
lvts_configure_polling_speed_and_filter(tc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void lvts_tscpu_reset_thermal(void)
|
||||
{
|
||||
/* Enable thermal control software reset */
|
||||
write32p(AP_RST_SET, BIT(11));
|
||||
|
||||
/* Clear thermal control software reset */
|
||||
write32p(AP_RST_CLR, BIT(11));
|
||||
}
|
||||
|
||||
static void lvts_set_tc_trigger_hw_protect(const struct lvts_thermal_controller *tc)
|
||||
{
|
||||
int d_index, i;
|
||||
uint32_t raw_high;
|
||||
uint16_t raw;
|
||||
enum lvts_sensor ts_name;
|
||||
|
||||
if (tc->dominator_ts_idx < tc->ts_number) {
|
||||
d_index = tc->dominator_ts_idx;
|
||||
} else {
|
||||
printk(BIOS_ERR, "LVTS, dominator_ts_idx %d >= ts_number %zu; use idx 0\n",
|
||||
tc->dominator_ts_idx, tc->ts_number);
|
||||
d_index = 0;
|
||||
}
|
||||
|
||||
ts_name = tc->ts[d_index];
|
||||
|
||||
printk(BIOS_INFO, "%s, the dominator ts_name is %d\n", __func__, ts_name);
|
||||
|
||||
/* Maximum of 4 sensing points */
|
||||
raw_high = 0;
|
||||
for (i = 0; i < tc->ts_number; i++) {
|
||||
ts_name = tc->ts[i];
|
||||
raw = lvts_temp_to_raw(tc->reboot_temperature, ts_name);
|
||||
raw_high = MAX(raw_high, raw);
|
||||
}
|
||||
|
||||
setbits32(&tc->regs->lvtsprotctl_0, 0x3FFF);
|
||||
/* disable trigger SPM interrupt */
|
||||
write32(&tc->regs->lvtsmonint_0, 0);
|
||||
|
||||
clrsetbits32(&tc->regs->lvtsprotctl_0, 0xF << 16, BIT(16));
|
||||
|
||||
write32(&tc->regs->lvtsprottc_0, raw_high);
|
||||
|
||||
/* enable trigger Hot SPM interrupt */
|
||||
write32(&tc->regs->lvtsmonint_0, STAGE3_INT_EN);
|
||||
|
||||
clrbits32(&tc->regs->lvtsprotctl_0, 0xFFFF);
|
||||
}
|
||||
|
||||
static void lvts_config_all_tc_hw_protect(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
lvts_set_tc_trigger_hw_protect(tc);
|
||||
}
|
||||
}
|
||||
|
||||
static bool lvts_lk_init_check(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lvts_tscpu_g_tc); i++) {
|
||||
const struct lvts_thermal_controller *tc = &lvts_tscpu_g_tc[i];
|
||||
if (tc->ctrl_on_off == CTRL_OFF)
|
||||
continue;
|
||||
|
||||
/* Check LVTS device ID */
|
||||
if ((read32(&tc->regs->lvtsspare[0]) & GENMASK(11, 0)) != LVTS_MAGIC)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lvts_thermal_init(void)
|
||||
{
|
||||
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
|
||||
|
||||
if (lvts_lk_init_check())
|
||||
return;
|
||||
|
||||
lvts_tscpu_reset_thermal();
|
||||
|
||||
lvts_thermal_cal_prepare();
|
||||
lvts_device_identification();
|
||||
lvts_device_enable_init_all_devices();
|
||||
lvts_efuse_setting();
|
||||
|
||||
lvts_disable_all_sensing_points();
|
||||
lvts_wait_all_sensing_points_idle();
|
||||
lvts_tscpu_thermal_initial_all_tc();
|
||||
lvts_config_all_tc_hw_protect();
|
||||
lvts_enable_all_sensing_points();
|
||||
|
||||
lvts_set_init_flag();
|
||||
|
||||
printk(BIOS_INFO, "%s: thermal initialized\n", __func__);
|
||||
|
||||
read_all_tc_lvts_temperature();
|
||||
}
|
||||
|
||||
static void reset_cpu_lvts(void)
|
||||
{
|
||||
write32p(CPU_LVTS_RESET_ADDR, 1);
|
||||
udelay(10);
|
||||
write32p(CPU_LVTS_RESET_ADDR, 0);
|
||||
|
||||
printk(BIOS_INFO, "%s done\n", __func__);
|
||||
}
|
||||
|
||||
void thermal_init(void)
|
||||
{
|
||||
reset_cpu_lvts();
|
||||
lvts_thermal_init();
|
||||
thermal_sram_init();
|
||||
}
|
||||
61
src/soc/mediatek/mt8196/thermal_sram.c
Normal file
61
src/soc/mediatek/mt8196/thermal_sram.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
||||
|
||||
#include <arch/cache.h>
|
||||
#include <soc/thermal_internal.h>
|
||||
#include <string.h>
|
||||
|
||||
/* SRAM for Thermal */
|
||||
#define THERMAL_SRAM_BASE (_mcufw_reserved + 0x1000)
|
||||
#define THERMAL_SRAM_LEN 0x400
|
||||
|
||||
static void thermal_cls_sram(void)
|
||||
{
|
||||
int i = 0;
|
||||
const uint32_t pattern = 0x27BC86AA;
|
||||
uint32_t *buff = (uint32_t *)THERMAL_SRAM_BASE;
|
||||
for (i = 0; i < THERMAL_SRAM_LEN / sizeof(*buff); i++) {
|
||||
*buff = pattern;
|
||||
buff++;
|
||||
}
|
||||
dcache_clean_invalidate_by_mva((void *)THERMAL_SRAM_BASE, THERMAL_SRAM_LEN);
|
||||
}
|
||||
|
||||
/* SRAM for Thermal state */
|
||||
#define THERMAL_STAT_SRAM_BASE ((uintptr_t)_sram + 0x0001A800)
|
||||
#define THERMAL_STAT_SRAM_LEN 0x400
|
||||
|
||||
static void thermal_stat_cls_sram(void)
|
||||
{
|
||||
int i = 0;
|
||||
const uint32_t pattern = 0xFFFFFFFF;
|
||||
uint32_t *buff = (uint32_t *)THERMAL_STAT_SRAM_BASE;
|
||||
for (i = 0; i < THERMAL_STAT_SRAM_LEN / sizeof(*buff); i++) {
|
||||
*buff = pattern;
|
||||
buff++;
|
||||
}
|
||||
dcache_clean_invalidate_by_mva((void *)THERMAL_STAT_SRAM_BASE, THERMAL_STAT_SRAM_LEN);
|
||||
}
|
||||
|
||||
/* SRAM for GPU Thermal state */
|
||||
#define GPU_THERMAL_STAT_SRAM_BASE ((uintptr_t)_sram + 0x00017C00)
|
||||
#define GPU_THERMAL_STAT_SRAM_LEN 0x400
|
||||
|
||||
static void thermal_gpu_stat_cls_sram(void)
|
||||
{
|
||||
int i = 0;
|
||||
const uint32_t pattern = 0xFFFFFFFF;
|
||||
uint32_t *buff = (uint32_t *)GPU_THERMAL_STAT_SRAM_BASE;
|
||||
for (i = 0; i < GPU_THERMAL_STAT_SRAM_LEN / sizeof(*buff); i++) {
|
||||
*buff = pattern;
|
||||
buff++;
|
||||
}
|
||||
dcache_clean_invalidate_by_mva((void *)GPU_THERMAL_STAT_SRAM_BASE,
|
||||
GPU_THERMAL_STAT_SRAM_LEN);
|
||||
}
|
||||
|
||||
void thermal_sram_init(void)
|
||||
{
|
||||
thermal_cls_sram();
|
||||
thermal_stat_cls_sram();
|
||||
thermal_gpu_stat_cls_sram();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue