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>
diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c
index 8a5d319..99c87a5 100644
--- a/src/soc/mediatek/mt8183/dramc_init_setting.c
+++ b/src/soc/mediatek/mt8183/dramc_init_setting.c
@@ -735,7 +735,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
(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 @@
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_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 @@
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 @@
(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 @@
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 @@
(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 @@
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 @@
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 @@
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 @@
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 @@
(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 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 @@
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 @@
(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 @@
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 4a884b1..d992371 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 @@
(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 @@
}
}
-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 @@
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 @@
(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 17fa230..ec39049 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 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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
}
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 @@
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 @@
}
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 8afbef0..5e4f01531 100644
--- a/src/soc/mediatek/mt8183/emi.c
+++ b/src/soc/mediatek/mt8183/emi.c
@@ -157,6 +157,19 @@
(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 @@
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 @@
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 @@
*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 @@
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 @@
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 c630b5a..9ab889b 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 {
+ 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 f925162..3758547 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_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 a0937d0..b1a0c74 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 @@
};
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 @@
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 6931d5b..16f0b2e 100644
--- a/src/soc/mediatek/mt8183/include/soc/emi.h
+++ b/src/soc/mediatek/mt8183/include/soc/emi.h
@@ -15,6 +15,7 @@
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];