soc/mediatek/mt8183: Handle memory test failure
If DRAM calibration fails or mem test fails using the cached calibration results stored in flash, rerun DRAM full calibration. If partial calibration fails or the mem test following it fails, hang forever. Partial calibration acts as a fallback approach in case of full calibration failure. Therefore, if it fails, there would be no other ways to initialize DRAM. Instead of falling into reboot loop and draining out of battery, it is better to just hang so that the end user may notice that and send to RMA. BUG=b:80501386,b:139099592 BRANCH=kukui TEST=Boots correctly on Kukui Change-Id: I8e1d4f5bc7b45f45a8bfef74e86ec0ff6a556af4 Signed-off-by: Huayang Duan <huayang.duan@mediatek.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/35481 Reviewed-by: Hung-Te Lin <hungte@chromium.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
7689a0f792
commit
ffb5ea3dc4
|
@ -1969,11 +1969,13 @@ static void dramc_dle_factor_handler(u8 chn, u8 val, u8 freq_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 dramc_rx_datlat_cal(u8 chn, u8 rank, u8 freq_group,
|
static u8 dramc_rx_datlat_cal(u8 chn, u8 rank, u8 freq_group,
|
||||||
const struct sdram_params *params, const bool fast_calib)
|
const struct sdram_params *params, const bool fast_calib,
|
||||||
|
bool *test_passed)
|
||||||
{
|
{
|
||||||
u32 datlat, begin = 0, first = 0, sum = 0, best_step;
|
u32 datlat, begin = 0, first = 0, sum = 0, best_step;
|
||||||
u32 datlat_start = 7;
|
u32 datlat_start = 7;
|
||||||
|
|
||||||
|
*test_passed = true;
|
||||||
best_step = read32(&ch[chn].ao.shu[0].conf[1]) & SHU_CONF1_DATLAT_MASK;
|
best_step = read32(&ch[chn].ao.shu[0].conf[1]) & SHU_CONF1_DATLAT_MASK;
|
||||||
|
|
||||||
dramc_dbg("[DATLAT] start. CH%d RK%d DATLAT Default: 0x%x\n",
|
dramc_dbg("[DATLAT] start. CH%d RK%d DATLAT Default: 0x%x\n",
|
||||||
|
@ -2010,7 +2012,11 @@ static u8 dramc_rx_datlat_cal(u8 chn, u8 rank, u8 freq_group,
|
||||||
|
|
||||||
dramc_engine2_end(chn, dummy_rd_backup);
|
dramc_engine2_end(chn, dummy_rd_backup);
|
||||||
|
|
||||||
assert(sum != 0);
|
*test_passed = (sum != 0);
|
||||||
|
if (!*test_passed) {
|
||||||
|
dramc_show("DRAM memory test failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sum <= 3)
|
if (sum <= 3)
|
||||||
best_step = first + (sum >> 1);
|
best_step = first + (sum >> 1);
|
||||||
|
@ -2111,7 +2117,7 @@ static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group)
|
||||||
(0xff << 8) | (0x9 << 2) | ROEN);
|
(0xff << 8) | (0x9 << 2) | ROEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group)
|
int dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group)
|
||||||
{
|
{
|
||||||
bool fast_calib;
|
bool fast_calib;
|
||||||
switch (pams->source) {
|
switch (pams->source) {
|
||||||
|
@ -2123,9 +2129,10 @@ void dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
die("Invalid DRAM param source %u\n", pams->source);
|
die("Invalid DRAM param source %u\n", pams->source);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_passed;
|
||||||
u8 rx_datlat[RANK_MAX] = {0};
|
u8 rx_datlat[RANK_MAX] = {0};
|
||||||
for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
|
for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
|
||||||
for (u8 rk = RANK_0; rk < RANK_MAX; rk++) {
|
for (u8 rk = RANK_0; rk < RANK_MAX; rk++) {
|
||||||
|
@ -2144,7 +2151,9 @@ void dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group
|
||||||
dramc_window_perbit_cal(chn, rk, freq_group,
|
dramc_window_perbit_cal(chn, rk, freq_group,
|
||||||
TX_WIN_DQ_ONLY, pams, fast_calib);
|
TX_WIN_DQ_ONLY, pams, fast_calib);
|
||||||
rx_datlat[rk] = dramc_rx_datlat_cal(chn, rk, freq_group,
|
rx_datlat[rk] = dramc_rx_datlat_cal(chn, rk, freq_group,
|
||||||
pams, fast_calib);
|
pams, fast_calib, &test_passed);
|
||||||
|
if (!test_passed)
|
||||||
|
return -2;
|
||||||
dramc_window_perbit_cal(chn, rk, freq_group,
|
dramc_window_perbit_cal(chn, rk, freq_group,
|
||||||
RX_WIN_TEST_ENG, pams, fast_calib);
|
RX_WIN_TEST_ENG, pams, fast_calib);
|
||||||
}
|
}
|
||||||
|
@ -2152,4 +2161,5 @@ void dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group
|
||||||
dramc_rx_dqs_gating_post_process(chn, freq_group);
|
dramc_rx_dqs_gating_post_process(chn, freq_group);
|
||||||
dramc_dual_rank_rx_datlat_cal(chn, freq_group, rx_datlat[0], rx_datlat[1]);
|
dramc_dual_rank_rx_datlat_cal(chn, freq_group, rx_datlat[0], rx_datlat[1]);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,12 +342,14 @@ void enable_emi_dcm(void)
|
||||||
clrbits_le32(&ch[chn].emi.chn_conb, 0xff << 24);
|
clrbits_le32(&ch[chn].emi.chn_conb, 0xff << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_calib(const struct sdram_params *params, u8 freq_group)
|
static int do_calib(const struct sdram_params *params, u8 freq_group)
|
||||||
{
|
{
|
||||||
dramc_show("Start K, current clock is:%d\n", params->frequency);
|
dramc_show("Start K, current clock is:%d\n", params->frequency);
|
||||||
dramc_calibrate_all_channels(params, freq_group);
|
if (dramc_calibrate_all_channels(params, freq_group) != 0)
|
||||||
|
return -1;
|
||||||
dramc_ac_timing_optimize(freq_group);
|
dramc_ac_timing_optimize(freq_group);
|
||||||
dramc_show("K finish with clock:%d\n", params->frequency);
|
dramc_show("K finish with clock:%d\n", params->frequency);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void after_calib(void)
|
static void after_calib(void)
|
||||||
|
@ -356,7 +358,7 @@ static void after_calib(void)
|
||||||
dramc_runtime_config();
|
dramc_runtime_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_set_emi(const struct dramc_param *dparam)
|
int mt_set_emi(const struct dramc_param *dparam)
|
||||||
{
|
{
|
||||||
const u8 *freq_tbl;
|
const u8 *freq_tbl;
|
||||||
const int shuffle = DRAM_DFS_SHUFFLE_1;
|
const int shuffle = DRAM_DFS_SHUFFLE_1;
|
||||||
|
@ -372,7 +374,9 @@ void mt_set_emi(const struct dramc_param *dparam)
|
||||||
params = &dparam->freq_params[shuffle];
|
params = &dparam->freq_params[shuffle];
|
||||||
|
|
||||||
init_dram(params, current_freqsel);
|
init_dram(params, current_freqsel);
|
||||||
do_calib(params, current_freqsel);
|
if (do_calib(params, current_freqsel) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
after_calib();
|
after_calib();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ void dramc_sw_impedance_save_reg(u8 freq_group);
|
||||||
void dramc_sw_impedance_cal(const struct sdram_params *params, u8 term_option);
|
void dramc_sw_impedance_cal(const struct sdram_params *params, u8 term_option);
|
||||||
void dramc_apply_config_before_calibration(u8 freq_group);
|
void dramc_apply_config_before_calibration(u8 freq_group);
|
||||||
void dramc_apply_config_after_calibration(void);
|
void dramc_apply_config_after_calibration(void);
|
||||||
void dramc_calibrate_all_channels(const struct sdram_params *pams,
|
int dramc_calibrate_all_channels(const struct sdram_params *pams,
|
||||||
u8 freq_group);
|
u8 freq_group);
|
||||||
void dramc_hw_gating_onoff(u8 chn, bool onoff);
|
void dramc_hw_gating_onoff(u8 chn, bool onoff);
|
||||||
void dramc_enable_phy_dcm(bool bEn);
|
void dramc_enable_phy_dcm(bool bEn);
|
||||||
|
|
|
@ -88,7 +88,7 @@ int complex_mem_test(u8 *start, unsigned int len);
|
||||||
size_t sdram_size(void);
|
size_t sdram_size(void);
|
||||||
const struct sdram_params *get_sdram_config(void);
|
const struct sdram_params *get_sdram_config(void);
|
||||||
void enable_emi_dcm(void);
|
void enable_emi_dcm(void);
|
||||||
void mt_set_emi(const struct dramc_param *dparam);
|
int mt_set_emi(const struct dramc_param *dparam);
|
||||||
void mt_mem_init(struct dramc_param_ops *dparam_ops);
|
void mt_mem_init(struct dramc_param_ops *dparam_ops);
|
||||||
|
|
||||||
#endif /* SOC_MEDIATEK_MT8183_EMI_H */
|
#endif /* SOC_MEDIATEK_MT8183_EMI_H */
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
#include <soc/dramc_param.h>
|
#include <soc/dramc_param.h>
|
||||||
#include <soc/dramc_pi_api.h>
|
#include <soc/dramc_pi_api.h>
|
||||||
#include <soc/emi.h>
|
#include <soc/emi.h>
|
||||||
#include <string.h>
|
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
|
|
||||||
static void mt_mem_test(void)
|
static int mt_mem_test(void)
|
||||||
{
|
{
|
||||||
u64 rank_size[RANK_MAX];
|
u64 rank_size[RANK_MAX];
|
||||||
|
|
||||||
|
@ -43,11 +42,16 @@ static void mt_mem_test(void)
|
||||||
printk(BIOS_DEBUG, "[MEM] complex R/W mem test %s : %d\n",
|
printk(BIOS_DEBUG, "[MEM] complex R/W mem test %s : %d\n",
|
||||||
(i == 0) ? "pass" : "fail", i);
|
(i == 0) ? "pass" : "fail", i);
|
||||||
|
|
||||||
ASSERT(i == 0);
|
if (i != 0) {
|
||||||
|
dramc_show("DRAM memory test failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
addr += rank_size[r];
|
addr += rank_size[r];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_param_header(const struct dramc_param *dparam)
|
static void dump_param_header(const struct dramc_param *dparam)
|
||||||
|
@ -147,9 +151,8 @@ void mt_mem_init(struct dramc_param_ops *dparam_ops)
|
||||||
if (dram_run_fast_calibration(dparam, config) == 0) {
|
if (dram_run_fast_calibration(dparam, config) == 0) {
|
||||||
printk(BIOS_INFO,
|
printk(BIOS_INFO,
|
||||||
"DRAM calibraion params loaded from flash\n");
|
"DRAM calibraion params loaded from flash\n");
|
||||||
mt_set_emi(dparam);
|
if (mt_set_emi(dparam) == 0 && mt_mem_test() == 0)
|
||||||
mt_mem_test();
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printk(BIOS_WARNING,
|
printk(BIOS_WARNING,
|
||||||
|
@ -174,6 +177,8 @@ void mt_mem_init(struct dramc_param_ops *dparam_ops)
|
||||||
|
|
||||||
/* Init params from sdram configs and run partial calibration */
|
/* Init params from sdram configs and run partial calibration */
|
||||||
init_sdram_params(dparam->freq_params, get_sdram_config());
|
init_sdram_params(dparam->freq_params, get_sdram_config());
|
||||||
mt_set_emi(dparam);
|
if (mt_set_emi(dparam) != 0)
|
||||||
mt_mem_test();
|
die("Set emi failed with params from sdram config\n");
|
||||||
|
if (mt_mem_test() != 0)
|
||||||
|
die("Memory test failed with params from sdram config\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue