soc/meidatek/mt8196: Extract common thermal code for reuse

To promote code reuse and maintainability, move partial thermal driver
to common.

BUG=b:379008996
BRANCH=none
TEST=build passed.

Signed-off-by: Kai-chun Huang <kai-chun.huang@mediatek.corp-partner.google.com>
Change-Id: I6a52d1cb02d04308f1e833df0f318f93a8231fe1
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88440
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:
kai-chun.huang 2025-06-14 14:34:50 +08:00 committed by Yidi Lin
commit e583b2ffb7
8 changed files with 464 additions and 397 deletions

View file

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef __SOC_MEDIATEK_COMMON_INCLUDE_SOC_THERMAL_COMMON_H__
#define __SOC_MEDIATEK_COMMON_INCLUDE_SOC_THERMAL_COMMON_H__
#include <soc/thermal_internal.h>
#define CHECK_DEVICE_ACCESS_RETRY_CNT 100
#define LVTS_DEVICE_ACCESS_DELAY_US 3
#define LVTS_READ_ID_RETRY_CNT 5
#define LVTS_READ_ID_DELAY_US 3
enum sensor_switch_status {
SEN_OFF,
SEN_ON,
};
struct lvts_thermal_controller_speed {
u32 group_interval_delay;
u32 period_unit;
u32 filter_interval_delay;
u32 sensor_interval_delay;
};
struct lvts_thermal_controller {
enum lvts_sensor ts[MAX_TS_NUMBER]; /* sensor point */
enum sensor_switch_status sensor_on_off[MAX_TS_NUMBER];
size_t ts_number;
int reboot_temperature;
int dominator_ts_idx;
unsigned int reboot_msr_sram_idx;
bool has_reboot_temp_sram;
bool has_reboot_msr_sram;
struct lvts_thermal_controller_speed speed;
struct mtk_thermal_controller_regs *regs;
};
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);
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_tscpu_reset_thermal(void);
void lvts_thermal_cal_prepare(void);
void lvts_device_identification(void);
void lvts_device_enable_init_all_devices(void);
void lvts_efuse_setting(void);
void lvts_config_all_tc_hw_protect(void);
uint16_t lvts_temp_to_raw(int temp_mc, enum lvts_sensor ts_name);
void lvts_tscpu_thermal_read_tc_temp(const struct lvts_thermal_controller *tc, int order);
void thermal_cls_sram(void);
void thermal_stat_cls_sram(void);
void thermal_sram_init(void);
void thermal_init(void);
void thermal_write_reboot_temp_sram(uint32_t value);
void thermal_write_reboot_msr_sram(unsigned int idx, uint32_t value);
#endif /* __SOC_MEDIATEK_COMMON_INCLUDE_SOC_THERMAL_COMMON_H__ */

View file

@ -0,0 +1,332 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <delay.h>
#include <device/mmio.h>
#include <soc/thermal.h>
#include <timer.h>
#define LVTS_SINGLE_SENSE_MODE_EN BIT(9)
#define LVTS_SENSOR_POINT_SELECTION_SETTING 0x13121110
#define LVTS_CALCULATION_SCALING_RULE 0x300
static int lvts_raw_to_temp(uint16_t msr_raw, enum lvts_sensor ts_name, uint32_t golden_temp)
{
int temp_mc;
int64_t temp1, coeff_a;
coeff_a = LVTS_COEFF_A;
temp1 = (coeff_a * msr_raw) / (1 << 14);
temp_mc = temp1 + golden_temp * 500 - coeff_a;
return temp_mc;
}
int lvts_read_tc_raw_and_temp(void *msr_reg, enum lvts_sensor ts_name, uint32_t golden_temp)
{
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, golden_temp);
} 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_initial_all_tc(void)
{
u32 i = 0;
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);
/* 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);
}
}
void lvts_configure_polling_speed_and_filter(const struct lvts_thermal_controller *tc)
{
u32 lvtsMonCtl1, lvtsMonCtl2;
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
lvtsMonCtl1 = ((tc->speed.group_interval_delay << 20) &
LVTS_GROUP_INTERVAL_DELAY_MASK) | (tc->speed.period_unit & GENMASK(9, 0));
lvtsMonCtl2 = ((tc->speed.filter_interval_delay << 16) & GENMASK(25, 16)) |
(tc->speed.sensor_interval_delay & GENMASK(9, 0));
/*
* Calculating 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, lvtsMonCtl1);
/*
* Filt interval is 1 * 46.545us = 46.545us,
* sen interval is 429 * 46.545us = 19.968ms
*/
write32(&tc->regs->lvtsmonctl2_0, lvtsMonCtl2);
/* Temperature sampling control, 1 sample */
write32(&tc->regs->lvtsmsrctl0_0, 0);
udelay(1);
printk(BIOS_INFO,
"%s,LVTSMONCTL1_0= %#x,LVTSMONCTL2_0= %#x,LVTSMSRCTL0_0= %#x\n",
__func__,
read32(&tc->regs->lvtsmonctl1_0),
read32(&tc->regs->lvtsmonctl2_0),
read32(&tc->regs->lvtsmsrctl0_0));
}
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 < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
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_DEVICE_ACCESS_RETRY_CNT,
lvts_check_all_sensing_points_idle() == 0,
udelay(2)))
printk(BIOS_ERR, "%s timeout\n", __func__);
}
static bool lvts_lk_init_check(void)
{
int i;
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
/* Check LVTS device ID */
if ((read32(&tc->regs->lvtsspare[0]) & GENMASK(11, 0)) != LVTS_MAGIC)
return false;
}
return true;
}
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_get_controller(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_BIT = 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_BIT didn't ready, reg0x%x\n",
dev_reg_idx);
}
return 1;
}
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;
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);
write32(&tc->regs->lvtsmonctl0_0, LVTS_SINGLE_SENSE_MODE_EN);
}
}
static void lvts_enable_all_sensing_points(void)
{
int i = 0;
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);
lvts_enable_sensing_points(tc);
}
}
static void lvts_set_init_flag(void)
{
u32 i;
printk(BIOS_INFO, "===== %s begin ======\n", __func__);
/*write init done flag to inform kernel */
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
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_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);
}
if (tc->has_reboot_msr_sram)
thermal_write_reboot_msr_sram(tc->reboot_msr_sram_idx, raw_high);
if (tc->has_reboot_temp_sram)
thermal_write_reboot_temp_sram(tc->reboot_temperature);
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);
}
void lvts_config_all_tc_hw_protect(void)
{
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);
lvts_set_tc_trigger_hw_protect(tc);
}
}
static void read_all_tc_lvts_temperature(void)
{
int i, j;
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
for (j = 0; j < tc->ts_number; j++)
lvts_tscpu_thermal_read_tc_temp(tc, j);
}
}
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();
}

View file

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cache.h>
#include <soc/thermal.h>
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);
}
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);
}
__weak void thermal_write_reboot_temp_sram(uint32_t value)
{
}
__weak void thermal_write_reboot_msr_sram(unsigned int idx, uint32_t value)
{
}

View file

@ -50,8 +50,8 @@ romstage-y += ../common/pmif.c pmif_init.c
romstage-y += ../common/rtc.c ../common/rtc_osc_init.c
romstage-y += ../common/pmif_spmi_v2.c pmif_spmi.c
romstage-y += ../common/srclken_rc.c srclken_rc.c
romstage-y += thermal.c
romstage-y += thermal_sram.c
romstage-y += ../common/thermal.c thermal.c
romstage-y += ../common/thermal_sram.c thermal_sram.c
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c
ramstage-y += dcc.c

View file

@ -3,9 +3,6 @@
#ifndef SOC_MEDIATEK_MT8196_THERMAL_H
#define SOC_MEDIATEK_MT8196_THERMAL_H
void thermal_sram_init(void);
void thermal_init(void);
void thermal_write_reboot_temp_sram(uint32_t value);
void thermal_write_reboot_msr_sram(unsigned int idx, uint32_t value);
#include <soc/thermal_common.h>
#endif /* SOC_MEDIATEK_MT8196_THERMAL_H */

View file

@ -3,16 +3,20 @@
#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
/* SRAM for Thermal */
#define THERMAL_SRAM_BASE (_mcufw_reserved + 0x1000)
#define THERMAL_SRAM_LEN 0x400
/* SRAM for Thermal state */
#define THERMAL_STAT_SRAM_BASE ((uintptr_t)_sram + 0x0001A800)
#define THERMAL_STAT_SRAM_LEN 0x400
/* private thermal sensor enum */
enum lvts_sensor {
L_TS_LVTS11_0 = 0, /* LVTS11-0 SOC-TOP */
@ -37,30 +41,6 @@ enum lvts_tc_offset {
TS_OFFSET_AP_CONTROLLER1 = 0x100,
};
enum sensor_switch_status {
SEN_OFF,
SEN_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];
size_t ts_number;
int reboot_temperature;
int dominator_ts_idx;
unsigned int reboot_msr_sram_idx;
bool has_reboot_temp_sram;
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);
@ -154,8 +134,10 @@ check_member(mtk_thermal_controller_regs, lvtsspare, 0x0f0);
#define AP_RST_CLR (INFRACFG_AO_SEC_BASE + 0xf34)
#define LVTS_COF_T_SLP_GLD 391460
#define LVTS_COEFF_A LVTS_COF_T_SLP_GLD
#define LVTS_COF_COUNT_R_GLD 34412
#define LVTS_COF_T_CONST_OFS 0
#define LVTS_GROUP_INTERVAL_DELAY_MASK GENMASK(31, 17)
#define DEFAULT_EFUSE_GOLDEN_TEMP 60
#define DEFAULT_EFUSE_COUNT 34389

View file

@ -3,11 +3,10 @@
#include <assert.h>
#include <console/console.h>
#include <delay.h>
#include <device/mmio.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
@ -44,6 +43,7 @@ static const struct lvts_thermal_controller lvts_tscpu_g_tc[LVTS_CONTROLLER_NUM]
.reboot_temperature = 118800,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 0,
.has_reboot_msr_sram = true,
.has_reboot_temp_sram = true,
.speed = {
.group_interval_delay = 0x7fff,
@ -60,6 +60,7 @@ static const struct lvts_thermal_controller lvts_tscpu_g_tc[LVTS_CONTROLLER_NUM]
.reboot_temperature = 118800,
.dominator_ts_idx = 0,
.reboot_msr_sram_idx = 1,
.has_reboot_msr_sram = true,
.has_reboot_temp_sram = false,
.speed = {
.group_interval_delay = 0x7fff,
@ -75,58 +76,24 @@ 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 *lvts_get_controller(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;
assert(tc_num < LVTS_CONTROLLER_NUM);
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;
return &lvts_tscpu_g_tc[tc_num];
}
/*
* 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)
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;
coff_a = LVTS_COEFF_A;
temp1 = (int64_t)temp_mc - (golden_temp * 500) + coff_a;
assert(temp1 > 0);
@ -137,7 +104,7 @@ static uint16_t lvts_temp_to_raw(int temp_mc, enum lvts_sensor ts_name)
return msr_raw;
}
static void lvts_efuse_setting(void)
void lvts_efuse_setting(void)
{
int i, j, s_index;
uint32_t efuse_data;
@ -145,8 +112,8 @@ static void lvts_efuse_setting(void)
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];
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
const struct lvts_thermal_controller *tc = lvts_get_controller(i);
val_0 = 0;
val_1 = 0;
for (j = 0; j < tc->ts_number; j++) {
@ -196,14 +163,14 @@ static void lvts_efuse_setting(void)
}
}
static void lvts_device_identification(void)
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];
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);
@ -228,12 +195,12 @@ static void lvts_device_identification(void)
}
}
static void lvts_device_enable_init_all_devices(void)
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++) {
for (i = 0; i < LVTS_CONTROLLER_NUM; i++) {
/* Stop Counting (RG_TSFM_ST=0) */
lvts_write_device(LVTS_DEVICE_WRITE_CONFIG, 0x03, 0x00, i);
@ -252,7 +219,7 @@ static void lvts_device_enable_init_all_devices(void)
}
}
static void lvts_thermal_cal_prepare(void)
void lvts_thermal_cal_prepare(void)
{
uint32_t temp[7];
int i, j;
@ -316,38 +283,7 @@ static void lvts_thermal_cal_prepare(void)
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)
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];
@ -355,163 +291,16 @@ static void lvts_tscpu_thermal_read_tc_temp(const struct lvts_thermal_controller
ASSERT(order < ARRAY_SIZE(tc->regs->lvtsatp));
temperature = lvts_read_tc_raw_and_temp(&tc->regs->lvtsatp[order], ts_name);
temperature = lvts_read_tc_raw_and_temp(&tc->regs->lvtsatp[order],
ts_name,
golden_temp);
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];
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];
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];
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];
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];
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];
/* 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)
void lvts_tscpu_reset_thermal(void)
{
/* Enable thermal control software reset */
write32p(AP_RST_SET, BIT(11));
@ -520,104 +309,6 @@ static void lvts_tscpu_reset_thermal(void)
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);
}
thermal_write_reboot_msr_sram(tc->reboot_msr_sram_idx, raw_high);
if (tc->has_reboot_temp_sram)
thermal_write_reboot_temp_sram(tc->reboot_temperature);
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];
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];
/* 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);

View file

@ -2,44 +2,14 @@
#include <arch/cache.h>
#include <assert.h>
#include <soc/thermal_internal.h>
#include <string.h>
#include <device/mmio.h>
#include <soc/thermal.h>
/* SRAM for Thermal */
#define THERMAL_SRAM_BASE (_mcufw_reserved + 0x1000)
#define THERMAL_SRAM_LEN 0x400
#define THERMAL_REBOOT_TEMP_SRAM_OFFSET 0x39C
#define THERMAL_REBOOT_MSR_SRAM_OFFSET 0x340
#define THERMAL_REBOOT_MSR_SRAM_LEN (6 * 4)
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