mediatek/mt8183: Support more DRAM frequency bootup

Add more DRAM frequency bootup to support DRAM frequencies 1600Mbps,
2400Mbps, 3200Mbps and 3600Mbps.

BUG=b:80501386
BRANCH=none
TEST=Memory test passes on eMCP platform

Change-Id: Ic1378ca43fb333c445ca77e7dc0844cdf65f2207
Signed-off-by: Huayang Duan <huayang.duan@mediatek.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/34332
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Huayang Duan 2019-07-14 15:46:08 +08:00 committed by Patrick Georgi
parent 7378015b74
commit c157ee97d4
5 changed files with 955 additions and 776 deletions

View File

@ -223,7 +223,7 @@ void dramc_sw_impedance_save_reg(u8 freq_group)
static void transfer_pll_to_spm_control(void) static void transfer_pll_to_spm_control(void)
{ {
u8 shu_lev = (read32(&ch[0].ao.shustatus) & 0x00000006) >> 1; u8 shu_lev = (read32(&ch[0].ao.shustatus) >> 1) & 0x3;
clrsetbits_le32(&mtk_spm->poweron_config_set, clrsetbits_le32(&mtk_spm->poweron_config_set,
(0xffff << 16) | (0x1 << 0), (0xffff << 16) | (0x1 << 0),
@ -264,6 +264,7 @@ static void dramc_rx_input_delay_tracking(u8 chn)
for (size_t r = 0; r < 2; r++) for (size_t r = 0; r < 2; r++)
for (size_t b = 0; b < 2; b++) { for (size_t b = 0; b < 2; b++) {
clrbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[2], 1 << 29);
clrsetbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[7], clrsetbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[7],
(0x3f << 0) | (0x3f << 8) | (0x3f << 0) | (0x3f << 8) |
(0x7f << 16) | (0x7f << 24), (0x7f << 16) | (0x7f << 24),
@ -286,7 +287,6 @@ static void dramc_rx_input_delay_tracking(u8 chn)
clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0], clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0],
(0x1 << 29) | (0xf << 4) | (0x1 << 0), (0x1 << 29) | (0xf << 4) | (0x1 << 0),
(0x1 << 29) | (0x0 << 4) | (0x1 << 0)); (0x1 << 29) | (0x0 << 4) | (0x1 << 0));
clrbits_le32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24));
for (u8 b = 0; b < 2; b++) { for (u8 b = 0; b < 2; b++) {
clrsetbits_le32(&ch[chn].phy.b[b].dq[9], clrsetbits_le32(&ch[chn].phy.b[b].dq[9],
@ -294,6 +294,7 @@ static void dramc_rx_input_delay_tracking(u8 chn)
(0x1 << 28) | (0x0 << 24)); (0x1 << 28) | (0x0 << 24));
setbits_le32(&ch[chn].phy.b[b].dq[5], 0x1 << 31); setbits_le32(&ch[chn].phy.b[b].dq[5], 0x1 << 31);
} }
clrbits_le32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24));
setbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 28) | (0x1 << 31)); setbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 28) | (0x1 << 31));
setbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 28) | (0x1 << 31)); setbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 28) | (0x1 << 31));
@ -346,16 +347,12 @@ static void dramc_impedance_tracking_enable(void)
setbits_le32(&ch[chn].ao.impcal, 0x1 << 19); setbits_le32(&ch[chn].ao.impcal, 0x1 << 19);
} }
setbits_le32(&ch[0].ao.impcal, 0x1 << 14); setbits_le32(&ch[0].ao.impcal, 0x1 << 14);
setbits_le32(&ch[1].ao.refctrl0, 0x1 << 2);
for (size_t chn = 0; chn < CHANNEL_MAX; chn++) for (size_t chn = 0; chn < CHANNEL_MAX; chn++)
setbits_le32(&ch[chn].ao.refctrl0, 0x1 << 3); setbits_le32(&ch[chn].ao.refctrl0, (0x1 << 2) | (0x1 << 3));
} }
static void dramc_phy_low_power_enable(void) static void dramc_phy_low_power_enable(void)
{ {
u32 broadcast_bak = dramc_get_broadcast();
dramc_set_broadcast(DRAMC_BROADCAST_OFF);
for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
for (size_t b = 0; b < 2; b++) { for (size_t b = 0; b < 2; b++) {
clrbits_le32(&ch[chn].phy.b[b].dll_fine_tune[2], clrbits_le32(&ch[chn].phy.b[b].dll_fine_tune[2],
@ -367,8 +364,6 @@ static void dramc_phy_low_power_enable(void)
} }
write32(&ch[0].phy.ca_dll_fine_tune[3], 0xba000); write32(&ch[0].phy.ca_dll_fine_tune[3], 0xba000);
write32(&ch[1].phy.ca_dll_fine_tune[3], 0x3a000); write32(&ch[1].phy.ca_dll_fine_tune[3], 0x3a000);
dramc_set_broadcast(broadcast_bak);
} }
static void dramc_dummy_read_for_tracking_enable(u8 chn) static void dramc_dummy_read_for_tracking_enable(u8 chn)
@ -384,8 +379,8 @@ static void dramc_dummy_read_for_tracking_enable(u8 chn)
for (size_t r = 0; r < 2; r++) { for (size_t r = 0; r < 2; r++) {
clrsetbits_le32(&ch[chn].ao.rk[r].dummy_rd_adr, clrsetbits_le32(&ch[chn].ao.rk[r].dummy_rd_adr,
(0x1ffff << 0) | (0x7ff << 17) | (0xf << 28), (0x1ffff << 0) | (0x7ff << 17) | (0xf << 28),
(0x7fff << 0) | (0x3f0 << 17)); (0xffff << 0) | (0x3f0 << 17));
setbits_le32(&ch[chn].ao.rk[r].dummy_rd_bk, 0x7 << 0); clrbits_le32(&ch[chn].ao.rk[r].dummy_rd_bk, 0x7 << 0);
} }
clrbits_le32(&ch[chn].ao.dummy_rd, 0x1 << 25 | 0x1 << 20); clrbits_le32(&ch[chn].ao.dummy_rd, 0x1 << 25 | 0x1 << 20);
@ -433,7 +428,7 @@ void dramc_runtime_config(void)
clrbits_le32(&ch[1].ao.refctrl0, 0x1 << 29); clrbits_le32(&ch[1].ao.refctrl0, 0x1 << 29);
transfer_pll_to_spm_control(); transfer_pll_to_spm_control();
setbits_le32(&mtk_spm->spm_power_on_val0, 0x3 << 25); setbits_le32(&mtk_spm->spm_power_on_val0, 0x1 << 25);
/* RX_TRACKING: ON */ /* RX_TRACKING: ON */
for (u8 chn = 0; chn < CHANNEL_MAX; chn++) for (u8 chn = 0; chn < CHANNEL_MAX; chn++)

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,17 @@
#include <soc/dramc_pi_api.h> #include <soc/dramc_pi_api.h>
#include <soc/dramc_register.h> #include <soc/dramc_register.h>
#define LP4X_HIGH_FREQ LP4X_DDR3200
#define LP4X_MIDDLE_FREQ LP4X_DDR2400
#define LP4X_LOW_FREQ LP4X_DDR1600
u32 frequency_table[LP4X_DDRFREQ_MAX] = {
[LP4X_DDR1600] = 1600,
[LP4X_DDR2400] = 2400,
[LP4X_DDR3200] = 3200,
[LP4X_DDR3600] = 3600,
};
struct emi_regs *emi_regs = (void *)EMI_BASE; struct emi_regs *emi_regs = (void *)EMI_BASE;
const u8 phy_mapping[CHANNEL_MAX][16] = { const u8 phy_mapping[CHANNEL_MAX][16] = {
[CHANNEL_A] = { [CHANNEL_A] = {
@ -32,6 +43,12 @@ const u8 phy_mapping[CHANNEL_MAX][16] = {
} }
}; };
struct optimize_ac_time {
u8 rfc;
u8 rfc_05t;
u16 tx_ref_cnt;
};
void dramc_set_broadcast(u32 onoff) void dramc_set_broadcast(u32 onoff)
{ {
write32(&mt8183_infracfg->dramc_wbr, onoff); write32(&mt8183_infracfg->dramc_wbr, onoff);
@ -268,17 +285,31 @@ static void dramc_init_pre_settings(void)
setbits_le32(&ch[0].phy.misc_ctrl1, 0x1 << 31); setbits_le32(&ch[0].phy.misc_ctrl1, 0x1 << 31);
} }
static void dramc_ac_timing_optimize(void) static void dramc_ac_timing_optimize(u8 freq_group)
{ {
struct optimize_ac_time rf_cab_opt[LP4X_DDRFREQ_MAX] = {
[LP4X_DDR1600] = {.rfc = 44, .rfc_05t = 0, .tx_ref_cnt = 62},
[LP4X_DDR2400] = {.rfc = 44, .rfc_05t = 0, .tx_ref_cnt = 62},
[LP4X_DDR3200] = {.rfc = 100, .rfc_05t = 0, .tx_ref_cnt = 119},
[LP4X_DDR3600] = {.rfc = 118, .rfc_05t = 1, .tx_ref_cnt = 138},
};
for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
clrsetbits_le32(&ch[chn].ao.shu[0].actim[3], clrsetbits_le32(&ch[chn].ao.shu[0].actim[3],
0xff << 16, 0x64 << 16); 0xff << 16, rf_cab_opt[freq_group].rfc << 16);
clrbits_le32(&ch[chn].ao.shu[0].ac_time_05t, 0x1 << 2); clrbits_le32(&ch[chn].ao.shu[0].ac_time_05t,
rf_cab_opt[freq_group].rfc_05t << 2);
clrsetbits_le32(&ch[chn].ao.shu[0].actim[4], clrsetbits_le32(&ch[chn].ao.shu[0].actim[4],
0x3ff << 0, 0x77 << 0); 0x3ff << 0, rf_cab_opt[freq_group].tx_ref_cnt << 0);
} }
} }
static void dfs_init_for_calibration(const struct sdram_params *params, u8 freq_group)
{
dramc_init(params, freq_group);
dramc_apply_config_before_calibration(freq_group);
}
static void init_dram(const struct sdram_params *params, u8 freq_group) static void init_dram(const struct sdram_params *params, u8 freq_group)
{ {
global_option_init(params); global_option_init(params);
@ -289,7 +320,7 @@ static void init_dram(const struct sdram_params *params, u8 freq_group)
dramc_sw_impedance_cal(params, ODT_OFF); dramc_sw_impedance_cal(params, ODT_OFF);
dramc_sw_impedance_cal(params, ODT_ON); dramc_sw_impedance_cal(params, ODT_ON);
dramc_init(params, freq_group); dfs_init_for_calibration(params, freq_group);
emi_init2(params); emi_init2(params);
} }
@ -302,17 +333,25 @@ 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) static void do_calib(const struct sdram_params *params, u8 freq_group)
{
dramc_show("Start K freq group:%d\n", frequency_table[freq_group]);
dramc_calibrate_all_channels(params, freq_group);
dramc_ac_timing_optimize(freq_group);
dramc_show("%s K freq group:%d finish!\n", __func__, frequency_table[freq_group]);
}
static void after_calib(void)
{ {
dramc_apply_config_before_calibration();
dramc_calibrate_all_channels(params);
dramc_ac_timing_optimize();
dramc_apply_config_after_calibration(); dramc_apply_config_after_calibration();
dramc_runtime_config(); dramc_runtime_config();
} }
void mt_set_emi(const struct sdram_params *params) void mt_set_emi(const struct sdram_params *params)
{ {
init_dram(params, LP4X_DDR3200); u32 current_freq = LP4X_HIGH_FREQ;
do_calib(params);
init_dram(params, current_freq);
do_calib(params, current_freq);
after_calib();
} }

View File

@ -50,16 +50,6 @@ enum {
}; };
enum { enum {
TX_DQ_DQS_MOVE_DQ_ONLY = 0,
TX_DQ_DQS_MOVE_DQM_ONLY,
TX_DQ_DQS_MOVE_DQ_DQM
};
enum {
MAX_CA_FINE_TUNE_DELAY = 63,
MAX_CS_FINE_TUNE_DELAY = 63,
MAX_CLK_FINE_TUNE_DELAY = 31,
CATRAINING_NUM = 6,
PASS_RANGE_NA = 0x7fff PASS_RANGE_NA = 0x7fff
}; };
@ -76,10 +66,8 @@ enum {
enum { enum {
DQS_GW_COARSE_STEP = 1, DQS_GW_COARSE_STEP = 1,
DQS_GW_FINE_START = 0,
DQS_GW_FINE_END = 32, DQS_GW_FINE_END = 32,
DQS_GW_FINE_STEP = 4, DQS_GW_FINE_STEP = 4,
DQS_GW_FREQ_DIV = 4,
RX_DQS_CTL_LOOP = 8, RX_DQS_CTL_LOOP = 8,
RX_DLY_DQSIENSTB_LOOP = 32 RX_DLY_DQSIENSTB_LOOP = 32
}; };
@ -102,10 +90,6 @@ enum {
DQ_DIV_MASK = BIT(DQ_DIV_SHIFT) - 1, DQ_DIV_MASK = BIT(DQ_DIV_SHIFT) - 1,
OEN_SHIFT = 16, OEN_SHIFT = 16,
DQS_DELAY_2T = 3,
DQS_DELAY_0P5T = 4,
DQS_DELAY = ((DQS_DELAY_2T << DQ_DIV_SHIFT) + DQS_DELAY_0P5T) << 5,
SELPH_DQS0 = _SELPH_DQS_BITS(0x3, 0x3), SELPH_DQS0 = _SELPH_DQS_BITS(0x3, 0x3),
SELPH_DQS1 = _SELPH_DQS_BITS(0x4, 0x1), SELPH_DQS1 = _SELPH_DQS_BITS(0x4, 0x1),
SELPH_DQS0_1600 = _SELPH_DQS_BITS(0x2, 0x1), SELPH_DQS0_1600 = _SELPH_DQS_BITS(0x2, 0x1),
@ -124,9 +108,10 @@ u8 get_freq_fsq(u8 freq_group);
void dramc_init(const struct sdram_params *params, u8 freq_group); void dramc_init(const struct sdram_params *params, u8 freq_group);
void dramc_sw_impedance_save_reg(u8 freq_group); 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(void); 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 *params); void dramc_calibrate_all_channels(const struct sdram_params *pams,
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);
void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value); void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value);

View File

@ -945,14 +945,11 @@ enum {
}; };
enum { enum {
MISC_STATUSA_SREF_STATE = 16,
MISC_STATUSA_REFRESH_QUEUE_CNT_SHIFT = 24, MISC_STATUSA_REFRESH_QUEUE_CNT_SHIFT = 24,
MISC_STATUSA_REFRESH_QUEUE_CNT_MASK = 0x0f000000, MISC_STATUSA_REFRESH_QUEUE_CNT_MASK = 0x0f000000,
}; };
enum {
SPCMDRESP_RDDQC_RESPONSE_SHIFT = 7,
};
enum { enum {
DDRCONF0_DM4TO1MODE_SHIFT = 22, DDRCONF0_DM4TO1MODE_SHIFT = 22,
DDRCONF0_RDATRST_SHIFT = 0, DDRCONF0_RDATRST_SHIFT = 0,
@ -974,6 +971,8 @@ enum {
}; };
enum { enum {
MRS_MPCRK_SHIFT = 28,
MRS_MPCRK_MASK = 0x30000000,
MRS_MRSRK_SHIFT = 24, MRS_MRSRK_SHIFT = 24,
MRS_MRSRK_MASK = 0x03000000, MRS_MRSRK_MASK = 0x03000000,
MRS_MRSMA_SHIFT = 8, MRS_MRSMA_SHIFT = 8,