diff options
author | Shaoming Chen <shaoming.chen@mediatek.corp-partner.google.com> | 2020-12-04 17:00:56 +0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-01-15 11:29:17 +0000 |
commit | 5ff588dbc10bbf69f140cebf3a584f1ed563b1c5 (patch) | |
tree | fd72c40c3efe8160bb36f8c70ef14531c949de01 /src/soc/mediatek | |
parent | f296273692785da1bc88df8d28d955f8d79390e7 (diff) | |
download | coreboot-5ff588dbc10bbf69f140cebf3a584f1ed563b1c5.tar.xz |
soc/mediatek/mt8183: Support byte mode and single rank DDR
1. Add emi setting to support byte mode and single rank ddr sample
2. Modify initial setting for DDR with different architecture
BUG=b:165768895
BRANCH=kukui
TEST=DDR boot up correctly on Kukui
Signed-off-by: Shaoming Chen <shaoming.chen@mediatek.corp-partner.google.com>
Change-Id: Id2845b2b60e2c447486ee25259dc6a05a0bb619b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/48300
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Diffstat (limited to 'src/soc/mediatek')
-rw-r--r-- | src/soc/mediatek/mt8183/dramc_init_setting.c | 388 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/dramc_pi_basic_api.c | 10 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/dramc_pi_calibration_api.c | 145 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/emi.c | 30 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h | 7 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/dramc_param.h | 6 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h | 13 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/emi.h | 1 |
8 files changed, 459 insertions, 141 deletions
diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c index 8a5d319b29..99c87a5fbd 100644 --- a/src/soc/mediatek/mt8183/dramc_init_setting.c +++ b/src/soc/mediatek/mt8183/dramc_init_setting.c @@ -735,7 +735,8 @@ static u8 dramc_zq_calibration(u8 chn, u8 rank) return 0; } -static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) +static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr, + const struct sdram_params *params) { u8 *MR01Value = mr->MR01Value; u8 MR02Value[FSP_MAX] = {0x12, 0x12}; @@ -744,12 +745,13 @@ static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) u8 MR12Value[CHANNEL_MAX][RANK_MAX][FSP_MAX] = { {{0x5d, 0x5d}, {0x5d, 0x5d} }, {{0x5d, 0x5d}, {0x5d, 0x5d} }, }; - u8 MR13Value; + u8 MR13Value = 0x18; u8 MR14Value[CHANNEL_MAX][RANK_MAX][FSP_MAX] = { {{0x5d, 0x10}, {0x5d, 0x10} }, {{0x5d, 0x10}, {0x5d, 0x10} }, }; u8 MR22Value[FSP_MAX] = {0x38, 0x34}; + u32 cbt_mode = params->cbt_mode_extern; MR01Value[FSP_0] = 0x6; MR01Value[FSP_1] = 0x6; @@ -767,7 +769,7 @@ static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) MR01Value[FSP_0] |= (0x5 << 4); MR01Value[FSP_1] |= (0x5 << 4); } else if (freq_group == LP4X_DDR3200) { - MR02Value[0] = 0x12; + MR02Value[0] = 0x1a; MR02Value[1] = 0x2d; MR01Value[FSP_0] |= (0x5 << 4); @@ -780,6 +782,9 @@ static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) MR01Value[FSP_1] |= (0x6 << 4); } + if (cbt_mode) + MR11Value[FSP_1] = 0x13; + u8 operate_fsp = get_freq_fsq(freq_group); dramc_dbg("%s operate_fsp:%d, freq:%d\n", __func__, operate_fsp, freq_group); @@ -789,7 +794,7 @@ static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) dramc_power_on_sequence(); for (chn = 0; chn < CHANNEL_MAX; chn++) { - for (rank = 0; rank < 2; rank++) { + for (rank = 0; rank < params->rank_num; rank++) { clrsetbits32(&ch[chn].ao.mrs, 0x3 << 24, rank << 24); dramc_zq_calibration(chn, rank); @@ -808,6 +813,15 @@ static void dramc_mode_reg_init(u8 freq_group, struct mr_value *mr) dramc_mode_reg_write(chn, 0x2, MR02Value[fsp]); dramc_mode_reg_write(chn, 0xb, MR11Value[fsp]); + if (cbt_mode == CBT_R0_NORMAL_R1_BYTE) { + if (rank == 0) + MR22Value[FSP_1] = 0x3c; + else + MR22Value[FSP_1] = 0x34; + } else { + MR22Value[FSP_1] = 0x34; + } + dramc_mode_reg_write(chn, 0x16, MR22Value[fsp]); dramc_mode_reg_write(chn, 0xe, MR14Value[chn][rank][fsp]); @@ -856,7 +870,7 @@ static void auto_refresh_cke_off(void) dramc_set_broadcast(broadcast_bak); } -static void dramc_setting_DDR1600(void) +static void dramc_setting_DDR1600(u32 cbt_mode) { clrsetbits32(&ch[0].ao.shu[0].rankctl, (0xf << 20) | (0xf << 24) | (0xf << 28), @@ -869,8 +883,13 @@ static void dramc_setting_DDR1600(void) clrsetbits32(&ch[0].ao.shu[0].selph_dqs0, 0x77777777, SELPH_DQS0_1600); clrsetbits32(&ch[0].ao.shu[0].selph_dqs1, 0x77777777, SELPH_DQS1_1600); - clrsetbits32(&ch[0].ao.shu[0].wodt, (0x1 << 29) | (0x1 << 31), - (0x0 << 29) | (0x1 << 31)); + + if (cbt_mode) + clrsetbits32(&ch[0].ao.shu[0].wodt, (0x1 << 31), (0x1 << 31)); + else + clrsetbits32(&ch[0].ao.shu[0].wodt, (0x1 << 29) | (0x1 << 31), + (0x0 << 29) | (0x1 << 31)); + clrsetbits32(&ch[0].ao.shu[0].dqs2dq_tx, 0x1f << 0, 0x4 << 0); for (size_t rank = 0; rank < 2; rank++) { @@ -880,16 +899,21 @@ static void dramc_setting_DDR1600(void) (0x3f << 0) | (0x3f << 8) | (0x3f << 16) | (0x3f << 24), (value << 0) | (value << 8) | (value << 16) | (value << 24)); - clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[0], - (0x7 << 8) | (0x7 << 12) | - (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), - (0x2 << 8) | (0x2 << 12) | - (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28)); - clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[1], - (0x7 << 8) | (0x7 << 12) | - (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), - (0x2 << 8) | (0x2 << 12) | - (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28)); + for (size_t b = 0; b < 2; b++) { + if (cbt_mode) { + clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[b], + (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) | + (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), + (0x2 << 0) | (0x2 << 4) | (0x2 << 8) | (0x2 << 12) | + (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28)); + } else { + clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[b], + (0x7 << 8) | (0x7 << 12) | + (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), + (0x2 << 8) | (0x2 << 12) | + (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28)); + } + } clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[2], 0x77777777, _SELPH_DQS_BITS(0x1, 0x7)); clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[3], @@ -899,11 +923,20 @@ static void dramc_setting_DDR1600(void) clrsetbits32(&ch[0].ao.shu[0].dqsg_retry, (0x1 << 2) | (0xf << 8), (0x0 << 2) | (0x3 << 8)); clrsetbits32(&ch[0].phy.shu[0].b[0].dq[5], 0x7 << 20, 0x4 << 20); - clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], - (0x3 << 4) | (0x1 << 7) | (0x1 << 13), - (0x2 << 4) | (0x0 << 7) | (0x0 << 13)); + + if (cbt_mode) + clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], (0x3 << 4), + (0x2 << 4)); + else + clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], + (0x3 << 4) | (0x1 << 7) | (0x1 << 13), + (0x2 << 4) | (0x0 << 7) | (0x0 << 13)); + clrsetbits32(&ch[0].phy.shu[0].b[1].dq[5], 0x7 << 20, 0x4 << 20); - clrbits32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 7) | (0x1 << 13)); + + if (cbt_mode == 0) + clrbits32(&ch[0].phy.shu[0].b[1].dq[7], + (0x1 << 7) | (0x1 << 13)); for (size_t r = 0; r < 2; r++) { int value = ((r == 0) ? 0x1a : 0x26); @@ -914,7 +947,7 @@ static void dramc_setting_DDR1600(void) } } -static void dramc_setting_DDR2400(void) +static void dramc_setting_DDR2400(u32 cbt_mode) { clrsetbits32(&ch[0].ao.shu[0].rankctl, (0xf << 20) | (0xf << 24) | (0xf << 28), @@ -927,8 +960,13 @@ static void dramc_setting_DDR2400(void) clrsetbits32(&ch[0].ao.shu[0].selph_dqs0, 0x77777777, SELPH_DQS0_2400); clrsetbits32(&ch[0].ao.shu[0].selph_dqs1, 0x77777777, SELPH_DQS1_2400); - clrsetbits32(&ch[0].ao.shu[0].wodt, - (0x1 << 29) | (0x1 << 31), (0x1 << 29) | (0x0 << 31)); + + if (cbt_mode) + clrsetbits32(&ch[0].ao.shu[0].wodt, (0x1 << 31), (0x0 << 31)); + else + clrsetbits32(&ch[0].ao.shu[0].wodt, + (0x1 << 29) | (0x1 << 31), (0x1 << 29) | (0x0 << 31)); + clrsetbits32(&ch[0].ao.shu[0].dqs2dq_tx, 0x1f << 0, 0x7 << 0); for (size_t rank = 0; rank < 2; rank++) { @@ -939,16 +977,21 @@ static void dramc_setting_DDR2400(void) (0x3f << 0) | (0x3f << 8) | (0x3f << 16) | (0x3f << 24), (0x14 << 0) | (0x14 << 8) | (0x14 << 16) | (0x14 << 24)); - clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[0], - (0x7 << 8) | (0x7 << 12) | - (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), - (0x3 << 8) | (0x3 << 12) | - (0x3 << 16) | (0x3 << 20) | (0x3 << 24) | (0x3 << 28)); - clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[1], - (0x7 << 8) | (0x7 << 12) | - (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), - (0x3 << 8) | (0x3 << 12) | - (0x3 << 16) | (0x3 << 20) | (0x3 << 24) | (0x3 << 28)); + for (size_t b = 0; b < 2; b++) { + if (cbt_mode) { + clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[b], + (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) | + (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), + (0x3 << 0) | (0x3 << 4) | (0x3 << 8) | (0x3 << 12) | + (0x3 << 16) | (0x3 << 20) | (0x3 << 24) | (0x3 << 28)); + } else { + clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[b], + (0x7 << 8) | (0x7 << 12) | + (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28), + (0x3 << 8) | (0x3 << 12) | + (0x3 << 16) | (0x3 << 20) | (0x3 << 24) | (0x3 << 28)); + } + } clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[2], 0x77777777, _SELPH_DQS_BITS(0x2, 0x0)); clrsetbits32(&ch[0].ao.shu[0].rk[rank].selph_dq[3], @@ -958,12 +1001,19 @@ static void dramc_setting_DDR2400(void) clrsetbits32(&ch[0].ao.shu[0].dqsg_retry, (0x1 << 2) | (0xf << 8), (0x1 << 2) | (0x4 << 8)); clrsetbits32(&ch[0].phy.shu[0].b[0].dq[5], 0x7 << 20, 0x3 << 20); - clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], - (0x3 << 4) | (0x1 << 7) | (0x1 << 13), - (0x1 << 4) | (0x1 << 7) | (0x1 << 13)); + + if (cbt_mode) + clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], + (0x3 << 4), (0x1 << 4)); + else + clrsetbits32(&ch[0].phy.shu[0].b[0].dq[7], + (0x3 << 4) | (0x1 << 7) | (0x1 << 13), + (0x1 << 4) | (0x1 << 7) | (0x1 << 13)); + clrsetbits32(&ch[0].phy.shu[0].b[1].dq[5], 0x7 << 20, 0x3 << 20); - clrsetbits32(&ch[0].phy.shu[0].b[1].dq[7], - (0x1 << 7) | (0x1 << 13), (0x1 << 7) | (0x1 << 13)); + + if (cbt_mode == 0) + setbits32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 7) | (0x1 << 13)); for (size_t r = 0; r < 2; r++) { for (size_t b = 0; b < 2; b++) @@ -1288,11 +1338,13 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, (0x4 << 20) | (0x4 << 24) | (0x6 << 28)); udelay(2); - clrsetbits32(&ch[0].ao.shu[0].rk[0].dqsien, - (0x7f << 0) | (0x7f << 8), (0x19 << 0) | (0x19 << 8)); - clrsetbits32(&ch[0].ao.shu[0].rk[1].dqsien, - (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24), - (0x1b << 0) | (0x1b << 8) | (0x0 << 16) | (0x0 << 24)); + if (params->cbt_mode_extern == CBT_R0_R1_NORMAL) { + clrsetbits32(&ch[0].ao.shu[0].rk[0].dqsien, + (0x7f << 0) | (0x7f << 8), (0x19 << 0) | (0x19 << 8)); + clrsetbits32(&ch[0].ao.shu[0].rk[1].dqsien, + (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24), + (0x1b << 0) | (0x1b << 8) | (0x0 << 16) | (0x0 << 24)); + } setbits32(&ch[0].ao.dramctrl, 0x1 << 19); clrsetbits32(&ch[0].ao.zqcs, 0xff << 0, 0x56 << 0); @@ -1317,25 +1369,34 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, udelay(1); clrsetbits32(&ch[0].ao.hw_mrr_fun, (0xf << 0) | (0xf << 4), (0x8 << 0) | (0x6 << 4)); - clrbits32(&ch[0].ao.dramctrl, 0x1 << 0); - clrsetbits32(&ch[0].ao.perfctl0, - (0x1 << 18) | (0x1 << 19), (0x0 << 18) | (0x1 << 19)); - setbits32(&ch[0].ao.spcmdctrl, 0x1 << 28); - clrbits32(&ch[0].ao.rstmask, 0x1 << 28); - setbits32(&ch[0].ao.rkcfg, 0x1 << 11); - setbits32(&ch[0].ao.mpc_option, 0x1 << 17); - setbits32(&ch[0].ao.eyescan, 0x1 << 2); - setbits32(&ch[0].ao.shu[0].wodt, 0x1 << 29); - setbits32(&ch[0].phy.shu[0].b[0].dq[7], 0x1 << 7); - setbits32(&ch[0].phy.shu[0].b[1].dq[7], 0x1 << 7); - clrsetbits32(&ch[0].ao.shu[0].rankctl, 0xf << 20, 0x4 << 20); + if (params->cbt_mode_extern != CBT_R0_R1_NORMAL) { + clrsetbits32(&ch[0].ao.perfctl0, + (0x1 << 18) | (0x1 << 19) | (0x1 << 27), + (0x0 << 18) | (0x1 << 19) | (0x1 << 27)); + clrbits32(&ch[0].ao.rstmask, 0x1 << 28); + setbits32(&ch[0].ao.rkcfg, 0x1 << 11); + setbits32(&ch[0].ao.spcmdctrl, 0x1 << 28); + setbits32(&ch[0].ao.eyescan, 0x1 << 2); + } else { + clrbits32(&ch[0].ao.dramctrl, 0x1 << 0); + clrsetbits32(&ch[0].ao.perfctl0, + (0x1 << 18) | (0x1 << 19), (0x0 << 18) | (0x1 << 19)); + setbits32(&ch[0].ao.spcmdctrl, 0x1 << 28); + clrbits32(&ch[0].ao.rstmask, 0x1 << 28); + setbits32(&ch[0].ao.rkcfg, 0x1 << 11); + setbits32(&ch[0].ao.mpc_option, 0x1 << 17); + setbits32(&ch[0].ao.eyescan, 0x1 << 2); + setbits32(&ch[0].ao.shu[0].wodt, 0x1 << 29); + setbits32(&ch[0].phy.shu[0].b[0].dq[7], 0x1 << 7); + setbits32(&ch[0].phy.shu[0].b[1].dq[7], 0x1 << 7); + clrsetbits32(&ch[0].ao.shu[0].rankctl, 0xf << 20, 0x4 << 20); - for (size_t r = 0; r < 2; r++) { - clrsetbits32(&ch[0].ao.shu[0].rk[r].selph_dq[0], - (0x7 << 0) | (0x7 << 4), (0x2 << 0) | (0x2 << 4)); - clrsetbits32(&ch[0].ao.shu[0].rk[r].selph_dq[1], - (0x7 << 0) | (0x7 << 4), (0x2 << 0) | (0x2 << 4)); + for (size_t r = 0; r < 2; r++) + for (size_t b = 0; b < 2; b++) + clrsetbits32(&ch[0].ao.shu[0].rk[r].selph_dq[b], + (0x7 << 0) | (0x7 << 4), (0x2 << 0) | (0x2 << 4)); } + udelay(5); clrsetbits32(&ch[0].ao.stbcal1, 0xffff << 16, 0x3 << 16); @@ -1363,9 +1424,26 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, clrsetbits32(&ch[0].ao.rkcfg, 0x7 << 4, 0x1 << 4); udelay(12); - clrsetbits32(&ch[0].ao.shu[0].rankctl, - (0xf << 24) | (0xf << 28), (0x4 << 24) | 0x6 << 28); + if (params->cbt_mode_extern != CBT_R0_R1_NORMAL) + clrsetbits32(&ch[0].ao.shu[0].rankctl, + (0xf << 20) | (0xf << 24) | (0xf << 28), + (0x3 << 20) | (0x3 << 24) | (0x5 << 28)); + else + clrsetbits32(&ch[0].ao.shu[0].rankctl, + (0xf << 24) | (0xf << 28), + (0x4 << 24) | (0x6 << 28)); + clrbits32(&ch[0].ao.shu[0].wodt, 0x1 << 31); + + if (params->cbt_mode_extern != CBT_R0_R1_NORMAL) { + clrsetbits32(&ch[0].ao.shu[0].rk[0].dqsien, + (0x7f << 0) | (0x7f << 8), + (0x19 << 0) | (0x19 << 8)); + clrsetbits32(&ch[0].ao.shu[0].rk[1].dqsien, + (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24), + (0x1b << 0) | (0x1b << 8) | (0x0 << 16) | (0x0 << 24)); + } + clrsetbits32(&ch[0].ao.shu[0].rk[0].fine_tune, (0x3f << 0) | (0x3f << 8) | (0x3f << 16) | (0x3f << 24), (0x1a << 0) | (0x1a << 8) | (0x1a << 16) | (0x1a << 24)); @@ -1383,8 +1461,16 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, clrsetbits32(&ch[0].ao.shu[0].dqsg_retry, (0x1 << 2) | (0xf << 8) | (0x1 << 14) | (0x3 << 24), (0x1 << 2) | (0x5 << 8) | (0x0 << 14) | (0x1 << 24)); - setbits32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 12) | (0x1 << 13)); - setbits32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 12) | (0x1 << 13)); + + if (params->cbt_mode_extern != CBT_R0_R1_NORMAL) { + setbits32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 12)); + setbits32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 12)); + } else { + setbits32(&ch[0].phy.shu[0].b[0].dq[7], + (0x1 << 12) | (0x1 << 13)); + setbits32(&ch[0].phy.shu[0].b[1].dq[7], + (0x1 << 12) | (0x1 << 13)); + } clrbits32(&ch[0].ao.shu[0].dqs2dq_tx, 0x1f << 0); /* The default dramc init settings were tuned at frequency of 3200Mbps. @@ -1392,10 +1478,10 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, the default settings. */ switch (freq_group) { case LP4X_DDR1600: - dramc_setting_DDR1600(); + dramc_setting_DDR1600(params->cbt_mode_extern); break; case LP4X_DDR2400: - dramc_setting_DDR2400(); + dramc_setting_DDR2400(params->cbt_mode_extern); break; case LP4X_DDR3200: /* Do nothing */ @@ -1423,7 +1509,7 @@ static void dramc_setting(const struct sdram_params *params, u8 freq_group, (0x1 << 4) | (0x1 << 11) | (0x1 << 13) | (0x1 << 14) | (0x3 << 16) | (0x1 << 22), (0x1 << 4) | (0x1 << 11) | (0x1 << 13) | - (0x1 << 14) | (0x2 << 16) | (0x1 << 22)); + (0x1 << 14) | (params->rank_num << 16) | (0x1 << 22)); clrsetbits32(&ch[0].ao.test2_4, 0x7 << 28, 0x4 << 28); clrbits32(&ch[0].ao.dramctrl, 0x1 << 0); udelay(1); @@ -1630,7 +1716,150 @@ static const struct ac_time ac_timing_tbl[LP4X_DDRFREQ_MAX] = { }, }; -static void ddr_update_ac_timing(u8 freq_group) +static const struct ac_time ac_timing_cbt_tbl[LP4X_DDRFREQ_MAX] = { + /* LP4x-1600, 800MHz, RDBI_OFF, byte mode */ + [LP4X_DDR1600] = { + .tras = 0, .tras_05T = 0, + .trp = 2, .trp_05T = 0, + .trpab = 0, .trpab_05T = 1, + .trc = 4, .trc_05T = 0, + .trfc = 44, .trfc_05T = 0, + .trfcpb = 16, .trfcpb_05T = 0, + .txp = 0, .txp_05T = 0, + .trtp = 1, .trtp_05T = 1, + .trcd = 3, .trcd_05T = 0, + .twr = 7, .twr_05T = 0, + .twtr = 4, .twtr_05T = 0, + .trrd = 0, .trrd_05T = 0, + .tfaw = 0, .tfaw_05T = 0, + .trtw_odt_on = 4, .trtw_odt_on_05T = 0, + .refcnt = 48, + .refcnt_fr_clk = 101, + .txrefcnt = 62, + .tzqcs = 16, + .xrtw2w = 5, + .xrtw2r = 3, + .xrtr2w = 3, + .xrtr2r = 8, + .r_dmcatrain_intv = 8, + .r_dmmrw_intv = 0xf, + .r_dmfspchg_prdcnt = 50, + .trtpd = 7, .trtpd_05T = 0, + .twtpd = 7, .twtpd_05T = 1, + .tmrr2w_odt_on = 6, + .ckeprd = 1, + .ckelckcnt = 0, + .zqlat2 = 6, + .dqsinctl = 2, .datlat = 11, + }, + /* LP4x-2400, 1200MHz, RDBI_OFF, byte mode */ + [LP4X_DDR2400] = { + .tras = 4, .tras_05T = 1, + .trp = 3, .trp_05T = 1, + .trpab = 1, .trpab_05T = 0, + .trc = 10, .trc_05T = 0, + .trfc = 72, .trfc_05T = 0, + .trfcpb = 30, .trfcpb_05T = 0, + .txp = 0, .txp_05T = 1, + .trtp = 1, .trtp_05T = 0, + .trcd = 4, .trcd_05T = 1, + .twr = 10, .twr_05T = 1, + .twtr = 6, .twtr_05T = 1, + .trrd = 1, .trrd_05T = 0, + .tfaw = 3, .tfaw_05T = 0, + .trtw_odt_on = 7, .trtw_odt_on_05T = 0, + .refcnt = 73, + .refcnt_fr_clk = 101, + .txrefcnt = 91, + .tzqcs = 25, + .xrtw2w = 5, + .xrtw2r = 3, + .xrtr2w = 6, + .xrtr2r = 8, + .r_dmcatrain_intv = 9, + .r_dmmrw_intv = 0xf, + .r_dmfspchg_prdcnt = 75, + .trtpd = 10, .trtpd_05T = 0, + .twtpd = 10, .twtpd_05T = 0, + .tmrr2w_odt_on = 9, + .ckeprd = 2, + .ckelckcnt = 0, + .zqlat2 = 9, + .dqsinctl = 4, .datlat = 14, + }, + /* LP4x-3200, 1600MHz, RDBI_OFF, byte mode */ + [LP4X_DDR3200] = { + .tras = 8, .tras_05T = 1, + .trp = 5, .trp_05T = 1, + .trpab = 1, .trpab_05T = 0, + .trc = 16, .trc_05T = 1, + .trfc = 100, .trfc_05T = 0, + .trfcpb = 44, .trfcpb_05T = 0, + .txp = 1, .txp_05T = 0, + .trtp = 2, .trtp_05T = 1, + .trcd = 6, .trcd_05T = 1, + .twr = 13, .twr_05T = 1, + .twtr = 8, .twtr_05T = 0, + .trrd = 2, .trrd_05T = 0, + .tfaw = 7, .tfaw_05T = 0, + .trtw_odt_on = 8, .trtw_odt_on_05T = 0, + .refcnt = 97, + .refcnt_fr_clk = 101, + .txrefcnt = 119, + .tzqcs = 34, + .xrtw2w = 5, + .xrtw2r = 3, + .xrtr2w = 7, + .xrtr2r = 9, + .r_dmcatrain_intv = 11, + .r_dmmrw_intv = 0xf, + .r_dmfspchg_prdcnt = 100, + .trtpd = 12, .trtpd_05T = 0, + .twtpd = 12, .twtpd_05T = 0, + .tmrr2w_odt_on = 11, + .ckeprd = 2, + .ckelckcnt = 0, + .zqlat2 = 12, + .dqsinctl = 5, .datlat = 16, + }, + /* LP4x-3600, 1800MHz, RDBI_OFF, byte mode */ + [LP4X_DDR3600] = { + .tras = 11, .tras_05T = 1, + .trp = 6, .trp_05T = 1, + .trpab = 1, .trpab_05T = 1, + .trc = 20, .trc_05T = 1, + .trfc = 118, .trfc_05T = 1, + .trfcpb = 53, .trfcpb_05T = 1, + .txp = 1, .txp_05T = 1, + .trtp = 2, .trtp_05T = 0, + .trcd = 7, .trcd_05T = 1, + .twr = 15, .twr_05T = 1, + .twtr = 9, .twtr_05T = 0, + .trrd = 3, .trrd_05T = 0, + .tfaw = 10, .tfaw_05T = 0, + .trtw_odt_on = 9, .trtw_odt_on_05T = 0, + .refcnt = 113, + .refcnt_fr_clk = 101, + .txrefcnt = 138, + .tzqcs = 40, + .xrtw2w = 5, + .xrtw2r = 3, + .xrtr2w = 8, + .xrtr2r = 9, + .r_dmcatrain_intv = 13, + .r_dmmrw_intv = 0xf, + .r_dmfspchg_prdcnt = 117, + .trtpd = 13, .trtpd_05T = 0, + .twtpd = 14, .twtpd_05T = 0, + .tmrr2w_odt_on = 10, + .ckeprd = 3, + .ckelckcnt = 0, + .zqlat2 = 14, + .dqsinctl = 7, .datlat = 17, + }, +}; + +static void ddr_update_ac_timing(u8 freq_group, u32 cbt_mode) { struct ac_time ac_t; u32 temp, r2w_odt_onoff = ODT_ON; @@ -1638,8 +1867,12 @@ static void ddr_update_ac_timing(u8 freq_group) u8 root = 0, tx_rank_inctl = 0, tx_dly = 0; u8 trtw = 0, trtw_05t = 0, tmrr2w = 0; - memcpy(&ac_t, &ac_timing_tbl[freq_group], sizeof(struct ac_time)); - new_datlat = ac_timing_tbl[freq_group].datlat - 2; + if (cbt_mode) + memcpy(&ac_t, &ac_timing_cbt_tbl[freq_group], sizeof(struct ac_time)); + else + memcpy(&ac_t, &ac_timing_tbl[freq_group], sizeof(struct ac_time)); + + new_datlat = ac_t.datlat - 2; if (freq_group == LP4X_DDR1600) { root = 0; tx_rank_inctl = 0; tx_dly = 1; @@ -1729,10 +1962,13 @@ static void ddr_update_ac_timing(u8 freq_group) (root << 16) | (tx_rank_inctl << 12) | (tx_dly << 8)); } - u8 dram_cbt_mode = 0; clrsetbits32(&ch[0].ao.arbctl, 0x7 << 10, 0x3 << 10); - clrsetbits32(&ch[0].ao.rstmask, 0x3 << 13, dram_cbt_mode); - clrsetbits32(&ch[0].ao.arbctl, 0x1 << 13, dram_cbt_mode); + clrsetbits32(&ch[0].ao.rstmask, 0x3 << 13, cbt_mode << 13); + + if (cbt_mode == 0) + clrsetbits32(&ch[0].ao.arbctl, 0x1 << 13, 0 << 13); + else + clrsetbits32(&ch[0].ao.arbctl, 0x1 << 13, 1 << 13); } void dramc_init(const struct sdram_params *params, u8 freq_group, @@ -1743,6 +1979,6 @@ void dramc_init(const struct sdram_params *params, u8 freq_group, dramc_duty_calibration(params, freq_group); dvfs_settings(freq_group); - dramc_mode_reg_init(freq_group, &shared->mr); - ddr_update_ac_timing(freq_group); + dramc_mode_reg_init(freq_group, &shared->mr, params); + ddr_update_ac_timing(freq_group, params->cbt_mode_extern); } diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c index 4a884b1976..d992371fac 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c @@ -347,9 +347,9 @@ static void dramc_phy_low_power_enable(u8 chn) (chn == CHANNEL_A) ? 0xba000 : 0x3a000); } -static void dramc_dummy_read_for_tracking_enable(u8 chn) +static void dramc_dummy_read_for_tracking_enable(u8 chn, u32 rk_num) { - setbits32(&ch[chn].ao.dummy_rd, 0x3 << 16); + setbits32(&ch[chn].ao.dummy_rd, rk_num << 16); for (size_t r = 0; r < 2; r++) for (size_t i = 0; i < 4; i++) @@ -403,7 +403,7 @@ static void dramc_enable_dramc_dcm(void) } } -void dramc_runtime_config(void) +void dramc_runtime_config(u32 rk_num) { for (u8 chn = 0; chn < CHANNEL_MAX; chn++) clrbits32(&ch[chn].ao.refctrl0, 0x1 << 29); @@ -412,7 +412,7 @@ void dramc_runtime_config(void) setbits32(&mtk_spm->spm_power_on_val0, 0x1 << 25); for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { - dramc_hw_dqsosc(chn); + dramc_hw_dqsosc(chn, rk_num); /* RX_TRACKING: ON */ dramc_rx_input_delay_tracking(chn); @@ -426,7 +426,7 @@ void dramc_runtime_config(void) (0x3 << 4) | (0x3 << 8) | (0x1 << 28)); /* DUMMY_READ_FOR_TRACKING: ON */ - dramc_dummy_read_for_tracking_enable(chn); + dramc_dummy_read_for_tracking_enable(chn, rk_num); /* ZQCS_ENABLE_LP4: ON */ clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 30); diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index 17fa2306e3..ec39049a8a 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -266,7 +266,7 @@ static void cbt_set_perbit_delay_cell(u8 chn, u8 rank) } static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp, - u8 cbt_on, struct mr_value *mr) + bool cbt_on, struct mr_value *mr, u32 cbt_mode) { u8 MR13Value = mr->MR13Value; @@ -276,6 +276,9 @@ static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp, MR13Value &= 0x7f; else MR13Value |= 0x80; + + if (cbt_mode) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_BYTEMODECBTEN, 1); } else { MR13Value &= 0xfe; if (fsp == FSP_1) @@ -322,7 +325,7 @@ static void o1_path_on_off(u8 cbt_on) udelay(1); } -static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) +static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr, u32 cbt_mode) { SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_PHYCLKDYNGEN, 0, @@ -331,26 +334,31 @@ static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_MIOCKCTRLOFF, 1); dramc_cke_fix_onoff(CKE_FIXON, chn); - set_dram_mr_cbt_on_off(chn, rank, fsp, 1, mr); - SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_WRITE_LEVEL_EN, 1); + set_dram_mr_cbt_on_off(chn, rank, fsp, true, mr, cbt_mode); + + if (cbt_mode == 0) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_WRITE_LEVEL_EN, 1); udelay(1); dramc_cke_fix_onoff(CKE_FIXOFF, chn); o1_path_on_off(1); } -static void cbt_exit(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) +static void cbt_exit(u8 chn, u8 rank, u8 fsp, struct mr_value *mr, u32 cbt_mode) { dramc_cke_fix_onoff(CKE_FIXON, chn); udelay(1); - set_dram_mr_cbt_on_off(chn, rank, fsp, 0, mr); + set_dram_mr_cbt_on_off(chn, rank, fsp, false, mr, cbt_mode); o1_path_on_off(0); + + if (cbt_mode) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_BYTEMODECBTEN, 0); } -static void cbt_set_vref(u8 chn, u8 rank, u8 vref, bool is_final) +static void cbt_set_vref(u8 chn, u8 rank, u8 vref, bool is_final, u32 cbt_mode) { - if (!is_final) { + if (cbt_mode == 0 && !is_final) { SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DMVREFCA, vref); SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQS_SEL, 1); SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQSBX_G, 0xa); @@ -394,12 +402,18 @@ static void cbt_set_ca_clk_result(u8 chn, u8 rank, } } -static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level) +static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level, u32 cbt_mode) { u8 vref_bit, vref_new, vref_org; vref_new = 0; vref_org = BIT(6) | (vref_level & 0x3f); + + if (cbt_mode) { + dramc_dbg("vref_org: %#x for byte mode\n", vref_org); + + return vref_org; + } for (vref_bit = 0; vref_bit < 8; vref_bit++) { if (vref_org & (1 << vref_bit)) vref_new |= (1 << phy_mapping[chn][vref_bit]); @@ -410,11 +424,14 @@ static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level) return vref_new; } -static void cbt_dramc_dfs_direct_jump(u8 shu_level) +static void cbt_dramc_dfs_direct_jump(u8 shu_level, bool run_dvfs) { u8 shu_ack = 0; static bool phy_pll_en = true; + if (!run_dvfs) + return; + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) shu_ack |= (0x1 << chn); @@ -490,20 +507,21 @@ static void cbt_dramc_dfs_direct_jump(u8 shu_level) phy_pll_en = !phy_pll_en; } -static void cbt_switch_freq(cbt_freq freq) +static void cbt_switch_freq(cbt_freq freq, bool run_dvfs) { if (freq == CBT_LOW_FREQ) - cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_MAX - 1); + cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_MAX - 1, run_dvfs); else - cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_1); + cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_1, run_dvfs); } static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, - const struct sdram_params *params, const bool fast_calib, - struct mr_value *mr) + const struct sdram_params *params, struct mr_value *mr, + bool run_dvfs) { u8 final_vref, cs_dly; u8 fsp = get_freq_fsq(freq_group); + u32 cbt_mode = params->cbt_mode_extern; cs_dly = params->cbt_cs_dly[chn][rank]; final_vref = params->cbt_final_vref[chn][rank]; @@ -521,6 +539,7 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, regs_bak[i].value = read32(regs_bak[i].addr); dramc_auto_refresh_switch(chn, false); + if (rank == RANK_1) { SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSRK, rank); SET32_BITFIELDS(&ch[chn].ao.rkcfg, RKCFG_TXRANK, rank); @@ -530,16 +549,35 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, cbt_set_perbit_delay_cell(chn, rank); - if (fsp == FSP_1) - cbt_switch_freq(CBT_LOW_FREQ); - cbt_entry(chn, rank, fsp, mr); - if (fsp == FSP_1) - cbt_switch_freq(CBT_HIGH_FREQ); + if (cbt_mode == 0) { + cbt_mrr_pinmux_mapping(); + if (fsp == FSP_1) + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + cbt_entry(chn, rank, fsp, mr, cbt_mode); + udelay(1); + if (fsp == FSP_1) + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); + } - u8 new_vref = get_cbt_vref_pinmux_value(chn, final_vref); - cbt_set_vref(chn, rank, new_vref, 0); + u8 new_vref = get_cbt_vref_pinmux_value(chn, final_vref, cbt_mode); + + if (cbt_mode) { + if (fsp == FSP_1) + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + + cbt_set_fsp(chn, rank, fsp, mr); + cbt_set_vref(chn, rank, new_vref, true, cbt_mode); + cbt_entry(chn, rank, fsp, mr, cbt_mode); + udelay(1); + + if (fsp == FSP_1) + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); + } else { + cbt_set_vref(chn, rank, new_vref, false, cbt_mode); + } cbt_set_ca_clk_result(chn, rank, params); + udelay(1); for (u8 rk = 0; rk < rank + 1; rk++) { /* Set CLK and CS delay */ @@ -548,14 +586,16 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, } if (fsp == FSP_1) - cbt_switch_freq(CBT_LOW_FREQ); - cbt_exit(chn, rank, fsp, mr); + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + cbt_exit(chn, rank, fsp, mr, cbt_mode); - cbt_set_fsp(chn, rank, fsp, mr); - cbt_set_vref(chn, rank, final_vref, 1); + if (cbt_mode == 0) { + cbt_set_fsp(chn, rank, fsp, mr); + cbt_set_vref(chn, rank, final_vref, true, cbt_mode); + } if (fsp == FSP_1) - cbt_switch_freq(CBT_HIGH_FREQ); + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); /* restore MRR pinmux */ set_mrr_pinmux_mapping(); @@ -693,7 +733,7 @@ static void dramc_rx_input_delay_tracking_init_by_freq(u8 chn, u8 freq_group) clrbits32(&shu->b[1].dq[7], (0x1 << 12) | (0x1 << 13)); } -void dramc_apply_config_before_calibration(u8 freq_group) +void dramc_apply_config_before_calibration(u8 freq_group, u32 cbt_mode) { for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { dramc_enable_phy_dcm(chn, false); @@ -710,8 +750,20 @@ void dramc_apply_config_before_calibration(u8 freq_group) clrbits32(&ch[chn].ao.dramctrl, 0x1 << 18); clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 31); clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 30); - clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); - clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + + if (cbt_mode == CBT_R0_R1_NORMAL) { + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_R1_BYTE) { + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_NORMAL_R1_BYTE) { + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_BYTE_R1_NORMAL) { + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } dramc_write_dbi_onoff(chn, false); dramc_read_dbi_onoff(chn, false); @@ -751,9 +803,9 @@ void dramc_apply_config_before_calibration(u8 freq_group) } } -static void dramc_set_mr13_vrcg_to_Normal(u8 chn, const struct mr_value *mr) +static void dramc_set_mr13_vrcg_to_normal(u8 chn, const struct mr_value *mr, u32 rk_num) { - for (u8 rank = 0; rank < RANK_MAX; rank++) + for (u8 rank = 0; rank < rk_num; rank++) dramc_mode_reg_write_by_rank(chn, rank, 13, mr->MR13Value & ~(0x1 << 3)); @@ -761,14 +813,14 @@ static void dramc_set_mr13_vrcg_to_Normal(u8 chn, const struct mr_value *mr) clrbits32(&ch[chn].ao.shu[shu].hwset_vrcg, 0x1 << 19); } -void dramc_apply_config_after_calibration(const struct mr_value *mr) +void dramc_apply_config_after_calibration(const struct mr_value *mr, u32 rk_num) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { write32(&ch[chn].phy.misc_cg_ctrl4, 0x11400000); clrbits32(&ch[chn].ao.refctrl1, 0x1 << 7); clrbits32(&ch[chn].ao.shuctrl, 0x1 << 2); clrbits32(&ch[chn].phy.ca_cmd[6], 0x1 << 6); - dramc_set_mr13_vrcg_to_Normal(chn, mr); + dramc_set_mr13_vrcg_to_normal(chn, mr, rk_num); clrbits32(&ch[chn].phy.b[0].dq[6], 0x3); clrbits32(&ch[chn].phy.b[1].dq[6], 0x3); @@ -2358,7 +2410,7 @@ static void dramc_dual_rank_rx_datlat_cal(u8 chn, u8 freq_group, u8 datlat0, u8 dramc_dle_factor_handler(chn, final_datlat, freq_group); } -static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) +static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group, u32 rk_num) { s8 dqsinctl; u32 read_dqsinctl, rankinctl_root, reg_tx_dly_dqsgated_min = 3; @@ -2372,7 +2424,7 @@ static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) reg_tx_dly_dqsgated_min = 1; /* get TXDLY_Cal_min and TXDLY_Cal_max value */ - for (size_t rank = 0; rank < RANK_MAX; rank++) { + for (size_t rank = 0; rank < rk_num; rank++) { u32 dqsg0 = read32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0); for (size_t dqs = 0; dqs < DQS_NUMBER; dqs++) { best_coarse_tune2t[rank][dqs] = (dqsg0 >> (dqs * 8)) & 0x7; @@ -2397,7 +2449,7 @@ static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) txdly_cal_min += dqsinctl; txdly_cal_max += dqsinctl; - for (size_t rank = 0; rank < RANK_MAX; rank++) { + for (size_t rank = 0; rank < rk_num; rank++) { dramc_dbg("Rank: %zd\n", rank); for (size_t dqs = 0; dqs < DQS_NUMBER; dqs++) { best_coarse_tune2t[rank][dqs] += dqsinctl; @@ -2515,7 +2567,7 @@ static void dqsosc_auto(u8 chn, u8 rank, u8 freq_group, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1, dqsosc_cnt[1]); } -void dramc_hw_dqsosc(u8 chn) +void dramc_hw_dqsosc(u8 chn, u32 rk_num) { u32 freq_shu1 = get_shu_freq(DRAM_DFS_SHUFFLE_1); u32 freq_shu2 = get_shu_freq(DRAM_DFS_SHUFFLE_2); @@ -2544,7 +2596,10 @@ void dramc_hw_dqsosc(u8 chn) SET32_BITFIELDS(&ch[chn].ao.dqsoscr, DQSOSCR_DQSOSCRDIS, 1); SET32_BITFIELDS(&ch[chn].ao.rk[0].dqsosc, RK0_DQSOSC_DQSOSCR_RK0EN, 1); - SET32_BITFIELDS(&ch[chn].ao.rk[1].dqsosc, RK1_DQSOSC_DQSOSCR_RK1EN, 1); + + if (rk_num == RANK_MAX) + SET32_BITFIELDS(&ch[chn].ao.rk[1].dqsosc, RK1_DQSOSC_DQSOSCR_RK1EN, 1); + SET32_BITFIELDS(&ch[chn].ao.dqsoscr, DQSOSCR_DQSOSC_CALEN, 1); for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) @@ -2994,7 +3049,7 @@ void dramc_dqs_precalculation_preset(void) } } -void get_dram_info_after_cal(u8 *density_result) +void get_dram_info_after_cal(u8 *density_result, u32 rk_num) { u8 vendor_id, density, max_density = 0; u32 ddr_size, max_size = 0; @@ -3002,7 +3057,7 @@ void get_dram_info_after_cal(u8 *density_result) vendor_id = dramc_mode_reg_read_by_rank(CHANNEL_A, RANK_0, 5); dramc_show("Vendor id is %#x\n", vendor_id); - for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { + for (u8 rk = RANK_0; rk < rk_num; rk++) { density = dramc_mode_reg_read_by_rank(CHANNEL_A, rk, 8); dramc_dbg("MR8 %#x\n", density); density = (density >> 2) & 0xf; @@ -3044,7 +3099,7 @@ void get_dram_info_after_cal(u8 *density_result) } int dramc_calibrate_all_channels(const struct sdram_params *pams, - u8 freq_group, struct mr_value *mr) + u8 freq_group, struct mr_value *mr, bool run_dvfs) { bool fast_calib; switch (pams->source) { @@ -3064,11 +3119,11 @@ int dramc_calibrate_all_channels(const struct sdram_params *pams, u16 osc_thrd_inc[RANK_MAX]; u16 osc_thrd_dec[RANK_MAX]; for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { - for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { + for (u8 rk = RANK_0; rk < pams->rank_num; rk++) { dramc_dbg("Start K: freq=%d, ch=%d, rank=%d\n", freq_group, chn, rk); dramc_cmd_bus_training(chn, rk, freq_group, pams, - fast_calib, mr); + mr, run_dvfs); dramc_write_leveling(chn, rk, freq_group, pams->wr_level); dramc_auto_refresh_switch(chn, true); @@ -3092,7 +3147,7 @@ int dramc_calibrate_all_channels(const struct sdram_params *pams, } dqsosc_shu_settings(chn, freq_group, osc_thrd_inc, osc_thrd_dec); - dramc_rx_dqs_gating_post_process(chn, freq_group); + dramc_rx_dqs_gating_post_process(chn, freq_group, pams->rank_num); dramc_dual_rank_rx_datlat_cal(chn, freq_group, rx_datlat[0], rx_datlat[1]); } return 0; diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 8afbef00d8..5e4f01531a 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -157,6 +157,19 @@ static void set_rank_info_to_conf(const struct sdram_params *params) (is_dual_rank ? 0 : 1) << 12); } +void cbt_mrr_pinmux_mapping(void) +{ + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + const u8 *map = phy_mapping[chn]; + write32(&ch[chn].ao.mrr_bit_mux1, + (map[8] << 0) | (map[9] << 8) | + (map[10] << 16) | (map[11] << 24)); + + write32(&ch[chn].ao.mrr_bit_mux2, + (map[12] << 0) | (map[13] << 8)); + } +} + void set_mrr_pinmux_mapping(void) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { @@ -432,7 +445,7 @@ static void dfs_init_for_calibration(const struct sdram_params *params, struct dram_shared_data *shared) { dramc_init(params, freq_group, shared); - dramc_apply_config_before_calibration(freq_group); + dramc_apply_config_before_calibration(freq_group, params->cbt_mode_extern); } static void init_dram(const struct sdram_params *params, u8 freq_group, @@ -449,7 +462,7 @@ static void init_dram(const struct sdram_params *params, u8 freq_group, dramc_sw_impedance_cal(params, ODT_ON, &shared->impedance); dramc_init(params, freq_group, shared); - dramc_apply_config_before_calibration(freq_group); + dramc_apply_config_before_calibration(freq_group, params->cbt_mode_extern); emi_init2(params); } @@ -589,9 +602,10 @@ static int run_calib(const struct dramc_param *dparam, *first_run = false; dramc_dbg("Start K (current clock: %u\n", params->frequency); - if (dramc_calibrate_all_channels(params, freq_group, &shared->mr) != 0) + if (dramc_calibrate_all_channels(params, freq_group, &shared->mr, + !!(dparam->header.config & DRAMC_CONFIG_DVFS)) != 0) return -1; - get_dram_info_after_cal(&density); + get_dram_info_after_cal(&density, params->rank_num); dramc_ac_timing_optimize(freq_group, density); dramc_dbg("K finished (current clock: %u\n", params->frequency); @@ -599,10 +613,10 @@ static int run_calib(const struct dramc_param *dparam, return 0; } -static void after_calib(const struct mr_value *mr) +static void after_calib(const struct mr_value *mr, u32 rk_num) { - dramc_apply_config_after_calibration(mr); - dramc_runtime_config(); + dramc_apply_config_after_calibration(mr, rk_num); + dramc_runtime_config(rk_num); } int mt_set_emi(const struct dramc_param *dparam) @@ -623,6 +637,6 @@ int mt_set_emi(const struct dramc_param *dparam) if (run_calib(dparam, &shared, DRAM_DFS_SHUFFLE_1, &first_run) != 0) return -1; - after_calib(&shared.mr); + after_calib(&shared.mr, dparam->freq_params[DRAM_DFS_SHUFFLE_1].rank_num); return 0; } diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h index c630b5aa90..9ab889b8e1 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h @@ -48,6 +48,13 @@ enum { }; enum { + CBT_R0_R1_NORMAL = 0, /* Normal mode */ + CBT_R0_R1_BYTE, /* Byte mode */ + CBT_R0_NORMAL_R1_BYTE, /* Mixed mode R0: Normal R1: Byte */ + CBT_R0_BYTE_R1_NORMAL /* Mixed mode R0: Byte R1: Normal */ +}; + +enum { FSP_0 = 0, FSP_1, FSP_MAX diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_param.h b/src/soc/mediatek/mt8183/include/soc/dramc_param.h index f925162e4a..3758547d13 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_param.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_param.h @@ -10,7 +10,7 @@ enum { DRAMC_PARAM_HEADER_MAGIC = 0x44524d4b, - DRAMC_PARAM_HEADER_VERSION = 4, + DRAMC_PARAM_HEADER_VERSION = 5, }; enum DRAMC_PARAM_STATUS_CODES { @@ -38,9 +38,13 @@ enum DRAMC_PARAM_FLAGS { }; enum DRAMC_PARAM_GEOMETRY_TYPE { + DDR_TYPE_2CH_1RK_4GB_4, DDR_TYPE_2CH_2RK_4GB_2_2, DDR_TYPE_2CH_2RK_6GB_3_3, DDR_TYPE_2CH_2RK_8GB_4_4, + DDR_TYPE_2CH_RK0_RK1_BYTE_8GB_4_4, + DDR_TYPE_2CH_RK0_NORMAL_RK1_BYTE_8GB_4_4, + DDR_TYPE_2CH_RK0_BYTE_RK1_NORMAL_8GB_4_4, }; struct dramc_param_header { diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h index a0937d01c6..b1a0c74f14 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -97,7 +97,7 @@ enum { }; void dramc_get_rank_size(u64 *dram_rank_size); -void dramc_runtime_config(void); +void dramc_runtime_config(u32 rk_num); void dramc_set_broadcast(u32 onoff); u32 dramc_get_broadcast(void); u8 get_freq_fsq(u8 freq_group); @@ -107,18 +107,19 @@ void dramc_sw_impedance_save_reg(u8 freq_group, const struct dram_impedance *impedance); void dramc_sw_impedance_cal(const struct sdram_params *params, u8 term_option, struct dram_impedance *impedance); -void dramc_apply_config_before_calibration(u8 freq_group); -void dramc_apply_config_after_calibration(const struct mr_value *mr); +void dramc_apply_config_before_calibration(u8 freq_group, u32 cbt_mode); +void dramc_apply_config_after_calibration(const struct mr_value *mr, u32 rk_num); int dramc_calibrate_all_channels(const struct sdram_params *pams, - u8 freq_group, struct mr_value *mr); + u8 freq_group, struct mr_value *mr, bool run_dvfs); void dramc_hw_gating_onoff(u8 chn, bool onoff); void dramc_enable_phy_dcm(u8 chn, bool bEn); void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value); u32 get_shu_freq(u8 shu); -void dramc_hw_dqsosc(u8 chn); +void dramc_hw_dqsosc(u8 chn, u32 rk_num); void dramc_dqs_precalculation_preset(void); -void get_dram_info_after_cal(u8 *density); +void get_dram_info_after_cal(u8 *density, u32 rk_num); void set_mrr_pinmux_mapping(void); void dramc_cke_fix_onoff(enum cke_type option, u8 chn); +void cbt_mrr_pinmux_mapping(void); #endif /* _DRAMC_PI_API_MT8183_H */ diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h index 6931d5bb81..16f0b2e8f5 100644 --- a/src/soc/mediatek/mt8183/include/soc/emi.h +++ b/src/soc/mediatek/mt8183/include/soc/emi.h @@ -15,6 +15,7 @@ enum DRAMC_PARAM_SOURCE { struct sdram_params { u16 source; /* DRAMC_PARAM_SOURCE */ u16 frequency; + u32 rank_num; u32 ddr_geometry; /* DRAMC_PARAM_GEOMETRY_TYPE */ u8 wr_level[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; |