huayang duan has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/35555 )
Change subject: mediatek/mt8183: Save multiple frequency calibration result to shuffle ......................................................................
mediatek/mt8183: Save multiple frequency calibration result to shuffle
Save the calibration results of all frequency to shuffle for DVFS switch.
BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui.
Change-Id: I97c8e513dc3815a2d62b2904a246a1d8567704a4 Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/Kconfig M src/soc/mediatek/mt8183/dramc_init_setting.c M src/soc/mediatek/mt8183/dramc_pi_basic_api.c M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c M src/soc/mediatek/mt8183/emi.c 5 files changed, 221 insertions(+), 61 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/55/35555/1
diff --git a/src/soc/mediatek/mt8183/Kconfig b/src/soc/mediatek/mt8183/Kconfig index 5ded0d3..576f2d5 100644 --- a/src/soc/mediatek/mt8183/Kconfig +++ b/src/soc/mediatek/mt8183/Kconfig @@ -30,6 +30,13 @@ The eMCP platform should select this option to run at different DRAM frequencies.
+config MT8183_DRAM_DUAL_FREQ_K + bool + default y + help + Enable this option to do calibration low-frequency, middle-frequency, + high-frequency of DRAM for DVFS feature. + config MEMORY_TEST bool default y diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c index c4bedf2..c03263b 100644 --- a/src/soc/mediatek/mt8183/dramc_init_setting.c +++ b/src/soc/mediatek/mt8183/dramc_init_setting.c @@ -43,6 +43,40 @@ (0x1 << 6) | (0x1 << 7), (on << 6) | (off << 7)); }
+static void dvfs_settings(u8 freq_group) +{ + u8 dll_idle; + + switch (freq_group) { + case LP4X_DDR1600: + dll_idle = 0x18; + break; + case LP4X_DDR2400: + dll_idle = 0x10; + break; + case LP4X_DDR3200: + dll_idle = 0xc; + break; + case LP4X_DDR3600: + dll_idle = 0xa; + break; + default: + die("Invalid DDR frequency group %u\n", freq_group); + return; + } + + dll_idle = dll_idle << 1; + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { + setbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 5); + setbits_le32(&ch[chn].phy.dvfs_emi_clk, 0x1 << 29); + clrsetbits_le32(&ch[0].ao.shuctrl2, 0x7f, dll_idle); + + setbits_le32(&ch[0].phy.misc_ctrl0, 0x3 << 19); + setbits_le32(&ch[chn].phy.dvfs_emi_clk, 0x1 << 24); + setbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 7); + } +} + static void ddr_phy_pll_setting(u8 chn, u8 freq_group) { u8 cap_sel, mid_cap_sel; @@ -86,16 +120,16 @@ ca_dll_mode[CHANNEL_A] = DLL_MASTER; ca_dll_mode[CHANNEL_B] = DLL_SLAVE;
- clrbits_le32(&ch[chn].phy.shu[0].pll[4], 0xFFFF); - clrbits_le32(&ch[chn].phy.shu[0].pll[6], 0xFFFF); + clrbits_le32(&ch[chn].phy.shu[0].pll[4], 0xffff); + clrbits_le32(&ch[chn].phy.shu[0].pll[6], 0xffff); setbits_le32(&ch[chn].phy.misc_shu_opt, (chn + 1) << 18); clrsetbits_le32(&ch[chn].phy.ckmux_sel, 0x3 << 18 | 0x3 << 16, 0x0); clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[0], 0x3 << 18, 0x1 << 18);
if (ca_dll_mode[chn] == DLL_SLAVE) - clrsetbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 1, 0x1 << 1); + setbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 1); else - clrsetbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 1, 0x0 << 1); + clrbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 1);
bool is_master = (ca_dll_mode[chn] == DLL_MASTER); u8 phdet_out = is_master ? 0x0 : 0x1; @@ -120,8 +154,7 @@ (pd_ck_sel << 2) | (fastpj_ck_sel << 0));
clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[6], - 0x1 << 7, - (is_master ? 0x1 : 0x0) << 7); + 0x1 << 7, (is_master ? 0x1 : 0x0) << 7);
struct reg_value regs_bak[] = { {&ch[chn].phy.b[0].dq[7]}, @@ -132,10 +165,9 @@ for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) regs_bak[i].value = read32(regs_bak[i].addr);
- for (size_t b = 0; b < 2; b++) { + for (size_t b = 0; b < 2; b++) setbits_le32(&ch[chn].phy.b[b].dq[7], 0x1 << 6 | 0x1 << 4 | 0x1 << 2 | 0x1 << 0); - } setbits_le32(&ch[chn].phy.ca_cmd[7], 0x1 << 6 | 0x1 << 4 | 0x1 << 2 | 0x1 << 0); setbits_le32(&ch[chn].phy.ca_cmd[2], 0x1 << 21);
@@ -245,11 +277,11 @@ setbits_le32(&ch[chn].phy.b[1].dll_fine_tune[3], (0x1 << 11) | (0x1 << 13) | (0x1 << 14) | (0x1 << 15) | (0x1 << 17)); + clrbits_le32(&ch[chn].phy.ca_dll_fine_tune[2], (0x1 << 10) | (0x1 << 13) | (0x1 << 15) | (0x1 << 16) | (0x1 << 17) | (0x1 << 19) | (0x1 << 27) | (0x1 << 31)); - clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[2], (0x1 << 10) | (0x1 << 13) | (0x1 << 14) | (0x1 << 15) | (0x1 << 17) | @@ -323,7 +355,7 @@
static void update_initial_settings(u8 freq_group) { - u8 chn = 0, operate_fsp = get_freq_fsq(freq_group); + u8 operate_fsp = get_freq_fsq(freq_group); u16 rx_vref = 0x16;
if (operate_fsp == FSP_1) @@ -380,11 +412,9 @@ clrsetbits_le32(&ch[0].phy.b[b].dq[5], 0x3f << 8, rx_vref << 8); }
- for (chn = 0; chn < CHANNEL_MAX; chn++) { - setbits_le32(&ch[chn].phy.b[0].dq[8], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); - setbits_le32(&ch[chn].phy.b[1].dq[8], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); - setbits_le32(&ch[chn].phy.ca_cmd[9], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); - } + setbits_le32(&ch[0].phy.b[0].dq[8], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); + setbits_le32(&ch[0].phy.b[1].dq[8], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); + setbits_le32(&ch[0].phy.ca_cmd[9], (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); dramc_gating_mode(1);
setbits_le32(&ch[0].phy.ca_cmd[8], 0x1 << 19); @@ -398,7 +428,7 @@ clrbits_le32(&ch[0].phy.shu[0].ca_cmd[5], 0x3f << 8);
dramc_set_broadcast(DRAMC_BROADCAST_OFF); - for (chn = 0; chn < CHANNEL_MAX; chn++) { + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { clrbits_le32(&ch[chn].phy.shu[0].b[0].dq[6], 0x3f << 0); clrbits_le32(&ch[chn].phy.shu[0].b[1].dq[6], 0x3f << 0); clrbits_le32(&ch[chn].phy.shu[0].ca_cmd[6], 0x3f << 0); @@ -504,13 +534,8 @@ setbits_le32(&ch[0].ao.ckectrl, 0x1 << 22); clrsetbits_le32(&ch[0].phy.ca_tx_mck, (0x1 << 31) | (0x1f << 21) | (0x1f << 26), (0x1 << 31) | (0xa << 21) | (0xa << 26)); - setbits_le32(&ch[0].ao.ckectrl, 0x1 << 23); - - /* Gating error problem happened in M17 - * has been solved by setting this RG as 0 */ clrbits_le32(&ch[0].ao.shu[0].rodtenstb, 0x1 << 31); - }
static void dramc_power_on_sequence(void) @@ -671,9 +696,9 @@ const u32 TIMEOUT_US = 100;
struct reg_value regs_bak[] = { - {&ch[chn].ao.mrs, 0x0}, - {&ch[chn].ao.dramc_pd_ctrl, 0x0}, - {&ch[chn].ao.ckectrl, 0x0}, + {&ch[chn].ao.mrs}, + {&ch[chn].ao.dramc_pd_ctrl}, + {&ch[chn].ao.ckectrl}, };
for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) @@ -879,7 +904,7 @@ clrsetbits_le32(&ch[0].phy.b[0].dq[7], (0x3 << 4) | (0x1 << 7) | (0x1 << 13), (0x2 << 4) | (0x0 << 7) | (0x0 << 13)); clrsetbits_le32(&ch[0].phy.b[1].dq[5], 0x7 << 20, 0x4 << 20); - clrbits_le32(&ch[0].phy.b[0].dq[7], (0x1 << 7) | (0x1 << 13)); + clrbits_le32(&ch[0].phy.b[1].dq[7], (0x1 << 7) | (0x1 << 13));
for (size_t r = 0; r < 2; r++) { int value = ((r == 0) ? 0x1a : 0x26); @@ -941,7 +966,7 @@ clrsetbits_le32(&ch[0].phy.b[0].dq[7], (0x3 << 4) | (0x1 << 7) | (0x1 << 13), (0x1 << 4) | (0x1 << 7) | (0x1 << 13)); clrsetbits_le32(&ch[0].phy.b[1].dq[5], 0x7 << 20, 0x3 << 20); - clrsetbits_le32(&ch[0].phy.b[0].dq[7], + clrsetbits_le32(&ch[0].phy.b[1].dq[7], (0x1 << 7) | (0x1 << 13), (0x1 << 7) | (0x1 << 13));
for (size_t r = 0; r < 2; r++) { @@ -1075,11 +1100,7 @@
for (size_t b = 0; b < 2; b++) setbits_le32(&ch[0].phy.b[b].dq[3], (0x3 << 1) | (0x1 << 10)); - - dramc_set_broadcast(DRAMC_BROADCAST_OFF); setbits_le32(&ch[0].phy.shu[0].ca_dll[0], 0x1 << 0); - setbits_le32(&ch[1].phy.shu[0].ca_dll[0], 0x1 << 0); - dramc_set_broadcast(DRAMC_BROADCAST_ON);
for (size_t b = 0; b < 2; b++) clrsetbits_le32(&ch[0].phy.shu[0].b[b].dll[0], @@ -1102,26 +1123,25 @@ clrsetbits_le32(&ch[0].phy.shu[0].b[b].dq[6], 0xffff << 6, 0x1 << 6);
dramc_set_broadcast(DRAMC_BROADCAST_OFF); - for (size_t chan = 0; chan < 2; chan++) - clrsetbits_le32(&ch[chan].phy.misc_shu_opt, + for (chn = 0; chn < CHANNEL_MAX; chn++) + clrsetbits_le32(&ch[chn].phy.misc_shu_opt, (0x1 << 0) | (0x3 << 2) | (0x1 << 8) | (0x3 << 10) | (0x1 << 16) | (0x3 << 18), (0x1 << 0) | (0x2 << 2) | (0x1 << 8) | - (0x2 << 10) | (0x1 << 16) | ((0x1+chan) << 18)); + (0x2 << 10) | (0x1 << 16) | ((0x1 + chn) << 18));
udelay(9); clrsetbits_le32(&ch[0].phy.shu[0].ca_dll[1], (0x1 << 0) | (0x1 << 2), 0x1 << 2); clrsetbits_le32(&ch[1].phy.shu[0].ca_dll[1], (0x1 << 0) | (0x1 << 2), 0x1 << 0); dramc_set_broadcast(DRAMC_BROADCAST_ON);
- for (size_t b = 0; b < 2; b++) { + for (size_t b = 0; b < 2; b++) clrsetbits_le32(&ch[0].phy.shu[0].b[b].dll[1], (0x1 << 0) | (0x1 << 2), (0x1 << 0) | (0x0 << 2)); - } udelay(1);
clrbits_le32(&ch[0].phy.pll2, 0x1 << 31); - clrsetbits_le32(&ch[0].phy.misc_cg_ctrl0, 0xffffffff, 0xF); + clrsetbits_le32(&ch[0].phy.misc_cg_ctrl0, 0xffffffff, 0xf); udelay(1);
dramc_set_broadcast(DRAMC_BROADCAST_OFF); @@ -1177,9 +1197,8 @@ setbits_le32(&ch[0].phy.misc_ctrl0, (0xf << 0) | (0x1 << 9) | (0x1 << 24) | (0x1 << 31));
- for (chn = 0; chn < CHANNEL_MAX; chn++) - setbits_le32(&ch[chn].phy.misc_ctrl1, - (0x1 << 2) | (0x1 << 3) | (0x1 << 15) | (0x1 << 24)); + setbits_le32(&ch[0].phy.misc_ctrl1, + (0x1 << 2) | (0x1 << 3) | (0x1 << 15) | (0x1 << 24)); clrsetbits_le32(&ch[0].phy.b0_rxdvs[0], 0x1 << 24, 0x1 << 24); clrsetbits_le32(&ch[0].phy.b1_rxdvs[0], 0x1 << 24, 0x1 << 24); clrsetbits_le32(&ch[0].phy.ca_rxdvs0, 0x1 << 24, 0x0 << 24); @@ -1294,6 +1313,8 @@ setbits_le32(&ch[0].ao.dramc_pd_ctrl, 0x1 << 0); clrsetbits_le32(&ch[0].ao.eyescan, (0x1 << 1) | (0xf << 16), (0x0 << 1) | (0x1 << 16)); setbits_le32(&ch[0].ao.stbcal1, (0x1 << 10) | (0x1 << 11)); + clrsetbits_le32(&ch[0].ao.test2_1, 0xfffffff << 4, 0x10000 << 4); + clrsetbits_le32(&ch[0].ao.test2_2, 0xfffffff << 4, 0x400 << 4); clrsetbits_le32(&ch[0].ao.test2_3, (0x1 << 7) | (0x7 << 8) | (0x1 << 28), (0x1 << 7) | (0x4 << 8) | (0x1 << 28)); @@ -1303,15 +1324,14 @@ udelay(1); clrsetbits_le32(&ch[0].ao.hw_mrr_fun, (0xf << 0) | (0xf << 4), (0x8 << 0) | (0x6 << 4));
+ clrbits_le32(&ch[0].ao.dramctrl, 0x1 << 0); clrsetbits_le32(&ch[0].ao.perfctl0, (0x1 << 18) | (0x1 << 19), (0x0 << 18) | (0x1 << 19)); + setbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 28); clrbits_le32(&ch[0].ao.rstmask, 0x1 << 28); setbits_le32(&ch[0].ao.rkcfg, 0x1 << 11); - setbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 28); - setbits_le32(&ch[0].ao.eyescan, 0x1 << 2); - - clrbits_le32(&ch[0].ao.dramctrl, 0x1 << 0); setbits_le32(&ch[0].ao.mpc_option, 0x1 << 17); + setbits_le32(&ch[0].ao.eyescan, 0x1 << 2); setbits_le32(&ch[0].ao.shu[0].wodt, 0x1 << 29); setbits_le32(&ch[0].phy.shu[0].b[0].dq[7], 0x1 << 7); setbits_le32(&ch[0].phy.shu[0].b[1].dq[7], 0x1 << 7); @@ -1341,7 +1361,7 @@ clrsetbits_le32(&ch[0].ao.shu[0].stbcal, 0x7 << 4, 0x1 << 4);
if (freq_group == LP4X_DDR1600) - clrsetbits_le32(&ch[0].ao.shu[0].stbcal, 0x3 << 0, (0x0 << 0)); + clrsetbits_le32(&ch[0].ao.shu[0].stbcal, 0x3 << 0, 0x0 << 0); else clrsetbits_le32(&ch[0].ao.shu[0].stbcal, 0x3 << 0, 0x2 << 0); setbits_le32(&ch[0].ao.refctrl1, (0x1 << 0) | (0x1 << 5)); @@ -1725,6 +1745,7 @@ dramc_setting(params, freq_group);
dramc_duty_calibration(params, freq_group); + dvfs_settings(freq_group);
dramc_mode_reg_init(freq_group); ddr_update_ac_timing(freq_group); diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c index a194d7a..2f22a3c 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c @@ -88,7 +88,7 @@ udelay(1); imp_cal_result = (read32(&ch[0].phy_nao.misc_phy_rgs_cmd) >> 24) & 0x1; - dramc_show("1. OCD DRVP=%d CALOUT=%d\n", + dramc_dbg("1. OCD DRVP=%d CALOUT=%d\n", impx_drv, imp_cal_result);
if (imp_cal_result == 1 && DRVP_result == 0xff) { @@ -116,7 +116,7 @@ udelay(1); imp_cal_result = (read32(&ch[0].phy_nao.misc_phy_rgs_cmd) >> 24) & 0x1; - dramc_show("3. OCD ODTN=%d CALOUT=%d\n", + dramc_dbg("3. OCD ODTN=%d CALOUT=%d\n", impx_drv, imp_cal_result);
if (imp_cal_result == 0 && ODTN_result == 0xff) { diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index f401cf4..834a956 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -394,7 +394,7 @@ setbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 24); clrsetbits_le32(&ch[0].ao.shu[0].scintv, 0x1f << 1, 0x1b << 1);
- for (size_t shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + for (size_t shu = DRAM_DFS_SHUFFLE_1; shu < DRAM_DFS_SHUFFLE_MAX; shu++) setbits_le32(&ch[0].ao.shu[shu].conf[3], 0x1ff << 0);
clrbits_le32(&ch[0].ao.dramctrl, 0x1 << 18); @@ -409,29 +409,29 @@ for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { setbits_le32(&ch[chn].ao.spcmdctrl, 0x1 << 29); setbits_le32(&ch[chn].ao.dqsoscr, 0x1 << 24); - for (size_t shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + for (size_t shu = DRAM_DFS_SHUFFLE_1; shu < DRAM_DFS_SHUFFLE_MAX; shu++) setbits_le32(&ch[chn].ao.shu[shu].scintv, 0x1 << 30);
clrbits_le32(&ch[chn].ao.dummy_rd, (0x1 << 7) | (0x7 << 20)); dramc_hw_gating_onoff(chn, false); clrbits_le32(&ch[chn].ao.stbcal2, 0x1 << 28);
- setbits_le32(&ch[chn].phy.misc_ctrl1, - (0x1 << 7) | (0x1 << 11)); + setbits_le32(&ch[chn].phy.misc_ctrl1, (0x1 << 7) | (0x1 << 11)); clrbits_le32(&ch[chn].ao.refctrl0, 0x1 << 18); clrbits_le32(&ch[chn].ao.mrs, 0x3 << 24); setbits_le32(&ch[chn].ao.mpc_option, 0x1 << 17); clrsetbits_le32(&ch[chn].phy.b[0].dq[6], 0x3 << 0, 0x1 << 0); clrsetbits_le32(&ch[chn].phy.b[1].dq[6], 0x3 << 0, 0x1 << 0); clrsetbits_le32(&ch[chn].phy.ca_cmd[6], 0x3 << 0, 0x1 << 0); + + dramc_rx_input_delay_tracking_init_by_freq(chn); + setbits_le32(&ch[chn].ao.dummy_rd, 0x1 << 25); setbits_le32(&ch[chn].ao.drsctrl, 0x1 << 0); if (freq_group == LP4X_DDR3200 || freq_group == LP4X_DDR3600) clrbits_le32(&ch[chn].ao.shu[1].drving[1], 0x1 << 31); else setbits_le32(&ch[chn].ao.shu[1].drving[1], 0x1 << 31); - - dramc_rx_input_delay_tracking_init_by_freq(chn); }
for (size_t r = 0; r < 2; r++) { @@ -866,13 +866,13 @@ u32 debug_cnt[DQS_NUMBER];
struct reg_value regs_bak[] = { - {&ch[chn].ao.stbcal, 0x0}, - {&ch[chn].ao.stbcal1, 0x0}, - {&ch[chn].ao.ddrconf0, 0x0}, - {&ch[chn].ao.spcmd, 0x0}, - {&ch[chn].ao.refctrl0, 0x0}, - {&ch[chn].phy.b[0].dq[6], 0x0}, - {&ch[chn].phy.b[1].dq[6], 0x0}, + {&ch[chn].ao.stbcal}, + {&ch[chn].ao.stbcal1}, + {&ch[chn].ao.ddrconf0}, + {&ch[chn].ao.spcmd}, + {&ch[chn].ao.refctrl0}, + {&ch[chn].phy.b[0].dq[6]}, + {&ch[chn].phy.b[1].dq[6]}, }; for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) regs_bak[i].value = read32(regs_bak[i].addr); @@ -2075,17 +2075,18 @@ u8 rx_datlat[RANK_MAX] = {0}; for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { - dramc_show("Start K ch:%d, rank:%d\n", chn, rk); - dramc_auto_refresh_switch(chn, false); + dramc_show("Start K freq:%d, ch:%d, rank:%d\n", freq_group, chn, rk); dramc_cmd_bus_training(chn, rk, freq_group, pams); dramc_write_leveling(chn, rk, freq_group, pams->wr_level); dramc_auto_refresh_switch(chn, true); + dramc_rx_dqs_gating_cal(chn, rk, freq_group, pams); dramc_window_perbit_cal(chn, rk, freq_group, RX_WIN_RD_DQC, pams); dramc_window_perbit_cal(chn, rk, freq_group, TX_WIN_DQ_DQM, pams); dramc_window_perbit_cal(chn, rk, freq_group, TX_WIN_DQ_ONLY, pams); rx_datlat[rk] = dramc_rx_datlat_cal(chn, rk, freq_group, pams); dramc_window_perbit_cal(chn, rk, freq_group, RX_WIN_TEST_ENG, pams); + dramc_auto_refresh_switch(chn, false); }
dramc_rx_dqs_gating_post_process(chn, freq_group); diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 84a4853..f0a80bc 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -18,6 +18,7 @@ #include <soc/infracfg.h> #include <soc/dramc_pi_api.h> #include <soc/dramc_register.h> +#include <soc/spm.h>
#if CONFIG(MT8183_DRAM_EMCP) static u8 freq_tbl[DRAM_DFS_SHUFFLE_MAX] = { @@ -316,6 +317,15 @@ } }
+static void spm_pinmux_setting(void) +{ + clrsetbits_le32(&mtk_spm->poweron_config_set, + (0xffff << 16) | (0x1 << 0), (0xb16 << 16) | (0x1 << 0)); + clrbits_le32(&mtk_spm->pcm_pwr_io_en, (0xff << 0) | (0xff << 16)); + write32(&mtk_spm->dramc_dpy_clk_sw_con_sel, 0xffffffff); + write32(&mtk_spm->dramc_dpy_clk_sw_con_sel2, 0xffffffff); +} + static void dfs_init_for_calibration(const struct sdram_params *params, u8 freq_group) { dramc_init(params, freq_group); @@ -329,6 +339,8 @@
dramc_set_broadcast(DRAMC_BROADCAST_ON); dramc_init_pre_settings(); + spm_pinmux_setting(); + dramc_sw_impedance_cal(params, ODT_OFF); dramc_sw_impedance_cal(params, ODT_ON);
@@ -360,16 +372,135 @@ }
+#if CONFIG(MT8183_DRAM_DUAL_FREQ_K) +#define DRAMC_SHUFFLE_ADDR_NUM 4 +#define PHY_SHUFFLE_ADDR_NUM 14 +#define SHU_GRP_DRAMC_OFFSET 0x600 +#define SHU_GRP_DDRPHY_OFFSET 0x500 + +struct shuffle_reg_addr { + u32 start; + u32 end; +}; + +const struct shuffle_reg_addr dramc_regs[DRAMC_SHUFFLE_ADDR_NUM] = { + {0x0800, 0x08DC}, + {0x0A00, 0x0A50}, + {0x0B00, 0x0B50}, + {0x0C00, 0x0C54}, +}; + +const struct shuffle_reg_addr phy_regs[PHY_SHUFFLE_ADDR_NUM] = { + {0x0C00, 0x0C38}, + {0x0C80, 0x0CB8}, + {0x0D00, 0x0D38}, + {0x0D80, 0x0DBC}, + {0x0DD0, 0x0DF0}, + {0x0E00, 0x0E2C}, + {0x0E50, 0x0E7C}, + {0x0EA0, 0x0ECC}, + {0x0F00, 0x0F2C}, + {0x0F50, 0x0F7C}, + {0x0FA0, 0x0FCC}, + {0x1000, 0x102C}, + {0x1050, 0x107C}, + {0x10A0, 0x10CC}, +}; + +static void dramc_save_result_to_shuffle(u32 src_shuffle, u32 dst_shuffle) +{ + u32 offset, chn, index, value; + u8* src_addr, *dest_addr; + + dramc_show("save shuffle: src_shuffle %d, dst_shuffle:%d\n", src_shuffle, dst_shuffle); + + for(chn = 0; chn < CHANNEL_MAX; chn++) { + /* DRAMC */ + for(index = 0; index < DRAMC_SHUFFLE_ADDR_NUM; index++) { + for (offset = dramc_regs[index].start; + offset <= dramc_regs[index].end; offset += 4) { + src_addr = (u8 *)&ch[chn].ao + offset + + SHU_GRP_DRAMC_OFFSET * src_shuffle; + dest_addr = (u8 *)&ch[chn].ao + offset + + SHU_GRP_DRAMC_OFFSET * dst_shuffle; + write32(dest_addr, read32(src_addr)); + + } + } + dramc_show("the dramc register of chn %d saved!\n", chn); + + /* DRAMC-exception-1 */ + src_addr = (u8 *)&ch[chn].ao.shuctrl2; + dest_addr = (u8 *)&ch[chn].ao.dvfsdll; + value = read32(src_addr) & 0x7f; + + if (dst_shuffle == DRAM_DFS_SHUFFLE_2) + clrsetbits_le32(dest_addr, 0x7f << 0x8, value << 0x8); + else if (dst_shuffle == DRAM_DFS_SHUFFLE_3) + clrsetbits_le32(dest_addr, 0x7f << 0x16, value << 0x16); + + dramc_show("the dramc exception-1 register of chn %d saved!\n", chn); + + /* DRAMC-exception-2 */ + src_addr = (u8 *)&ch[chn].ao.dvfsdll; + value = (read32(src_addr) >> 1) & 0x1; + + if (dst_shuffle == DRAM_DFS_SHUFFLE_2) + clrsetbits_le32(src_addr, 0x1 << 2, value << 2); + else if (dst_shuffle == DRAM_DFS_SHUFFLE_3) + clrsetbits_le32(src_addr, 0x1 << 3, value << 3); + + dramc_show("the dramc exception-2 register of chn %d saved!\n", chn); + + /* PHY */ + for(index = 0; index < PHY_SHUFFLE_ADDR_NUM; index++) { + for (offset = phy_regs[index].start; + offset <= phy_regs[index].end; offset += 4) { + src_addr = (u8 *)&ch[chn].phy + offset + + SHU_GRP_DDRPHY_OFFSET * src_shuffle; + dest_addr = (u8 *)&ch[chn].phy + offset + + SHU_GRP_DDRPHY_OFFSET * dst_shuffle; + write32(dest_addr, read32(src_addr)); + + } + } + dramc_show("the phy register of chn %d saved!\n", chn); + } +} +static void dram_dual_freq_calibration(const struct sdram_params *freq_params, + int freq_shuffle) +{ + u8 current_freqsel = freq_tbl[freq_shuffle]; + const struct sdram_params *params = &freq_params[freq_shuffle]; + + dramc_show("dual frequency calibration with freqsel:%d\n", current_freqsel); + + dfs_init_for_calibration(params, current_freqsel); + do_calib(params, current_freqsel); +} +#endif + void mt_set_emi(const struct sdram_params *freq_params) { int freq_shuffle = DRAM_DFS_SHUFFLE_1; const struct sdram_params *params = NULL;
+#if (CONFIG(MT8183_DRAM_DUAL_FREQ_K)) + freq_shuffle = DRAM_DFS_SHUFFLE_3; +#endif + u8 current_freqsel = freq_tbl[freq_shuffle]; params = &freq_params[freq_shuffle];
init_dram(params, current_freqsel); do_calib(params, current_freqsel);
+#if (CONFIG(MT8183_DRAM_DUAL_FREQ_K)) + dramc_save_result_to_shuffle(DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_3); + dram_dual_freq_calibration(freq_params, DRAM_DFS_SHUFFLE_2); + + dramc_save_result_to_shuffle(DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_2); + dram_dual_freq_calibration(freq_params, DRAM_DFS_SHUFFLE_1); +#endif after_calib(); }