Tristan Hsieh has uploaded this change for review.

View Change

mediatek/mt8183: Add MediaTek DDR driver

Add DDR driver to initialize memory.

BUG=b:80501386
BRANCH=none
TEST=Boots correctly on Kukui, and inits DRAM successfully with related
patches.

Change-Id: Iaaa1db170c168a58b020095ae45d98355d8dfcb0
Signed-off-by: Junzhi Zhao <junzhi.zhao@mediatek.com>
---
M src/soc/mediatek/mt8183/Kconfig
M src/soc/mediatek/mt8183/Makefile.inc
A src/soc/mediatek/mt8183/dramc_pi_basic_api.c
A src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
M src/soc/mediatek/mt8183/emi.c
M src/soc/mediatek/mt8183/include/soc/addressmap.h
A src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
A src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h
A src/soc/mediatek/mt8183/include/soc/dramc_register.h
M src/soc/mediatek/mt8183/include/soc/emi.h
M src/soc/mediatek/mt8183/include/soc/memlayout.ld
A src/soc/mediatek/mt8183/memory.c
M src/soc/mediatek/mt8183/pll.c
13 files changed, 6,648 insertions(+), 5 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/37/28437/1
diff --git a/src/soc/mediatek/mt8183/Kconfig b/src/soc/mediatek/mt8183/Kconfig
index b58be7f..1c78b18 100644
--- a/src/soc/mediatek/mt8183/Kconfig
+++ b/src/soc/mediatek/mt8183/Kconfig
@@ -19,4 +19,14 @@
select VBOOT_STARTS_IN_BOOTBLOCK
select VBOOT_SEPARATE_VERSTAGE

+config DEBUG_DRAM
+ bool "Output verbose DRAM related debug message"
+ default n
+ help
+ This option enables additional DRAM related debug messages.
+
+config MEMORY_TEST
+ bool
+ default y
+
endif
diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc
index 8fece79..2c128f9 100644
--- a/src/soc/mediatek/mt8183/Makefile.inc
+++ b/src/soc/mediatek/mt8183/Makefile.inc
@@ -21,6 +21,10 @@
verstage-y += ../common/wdt.c

romstage-y += ../common/cbmem.c emi.c
+romstage-y += dramc_pi_basic_api.c
+romstage-y += dramc_pi_calibration_api.c
+romstage-y += memory.c
+romstage-$(CONFIG_MEMORY_TEST) += ../common/memory_test.c
romstage-y += ../common/gpio.c gpio.c
romstage-y += ../common/mmu_operations.c mmu_operations.c
romstage-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c
diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c
new file mode 100644
index 0000000..6619540
--- /dev/null
+++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c
@@ -0,0 +1,1852 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <delay.h>
+#include <soc/infracfg.h>
+#include <soc/spm.h>
+#include <soc/pll.h>
+#include <soc/dramc_register.h>
+#include <soc/dramc_pi_api.h>
+#include <soc/emi.h>
+
+void dramc_broadcast_onoff(u32 bOnOff)
+{
+ write32(&mt8183_infracfg->dramc_wbr, bOnOff);
+}
+
+u32 get_dramc_broadcast(void)
+{
+ return read32(&mt8183_infracfg->dramc_wbr);
+}
+
+static void transfer_pll_to_spm_control(void)
+{
+ u8 shu_level;
+ shu_level = read32(&ch[0].ao.shustatus);
+ shu_level = (shu_level & 0x00000006) >> 1;
+
+ /* set SPM project code and enable clock enable */
+ clrsetbits_le32(&mtk_spm->poweron_config_set,
+ (0xffff << 16) | (0x1 << 0),
+ (0xb16 << 16) | (0x1 << 0));
+
+ /* set SPM pinmux */
+ clrbits_le32(&mtk_spm->pcm_pwr_io_en, (0xff << 0) | (0xff << 16));
+ setbits_le32(&mtk_spm->dramc_dpy_clk_sw_con_sel,
+ 0xffffffff << 0);
+ setbits_le32(&mtk_spm->dramc_dpy_clk_sw_con_sel2,
+ 0xffffffff << 0);
+
+ setbits_le32(&mtk_spm->spm_power_on_val0,
+ (0x1 << 8) | (0xf << 12));
+ setbits_le32(&mtk_spm->spm_s1_mode_ch, (0x3 << 0));
+
+ shu_level = (shu_level == 1) ? 2 : 1;
+ clrsetbits_le32(&mtk_spm->spm_power_on_val0,
+ (0x3 << 28), (shu_level << 28));
+ clrsetbits_le32(&mtk_spm->dramc_dpy_clk_sw_con2,
+ (0x3 << 2), (shu_level << 2));
+
+ udelay(1);
+ for (u8 chn = CHANNEL_A; chn < CHANNEL_NUM; chn++) {
+ clrbits_le32(&ch[chn].phy.pll1, (0x1 << 31));
+ clrbits_le32(&ch[chn].phy.pll2, (0x1 << 31));
+ }
+}
+
+static void dramc_hw_dqs_gating_tracking(u8 chn)
+{
+ setbits_le32(&ch[chn].ao.stbcal,
+ (0x3 << 26) | (0x1 << 0));
+ clrsetbits_le32(&ch[chn].ao.stbcal1,
+ (0xffff << 16) | (0x1 << 8) | (0x1 << 6),
+ (0x1 << 16) | (0x1 << 8) | (0x0 << 6));
+
+ clrsetbits_le32(&ch[chn].phy.misc_ctrl0,
+ (0x1 << 24) | (0x1f << 11) | (0xf << 0),
+ (0x1 << 24) | (0x0 << 11) | (0x0 << 0));
+
+ clrbits_le32(&ch[chn].phy.b[0].dq[6], (0x1 << 31));
+ clrbits_le32(&ch[chn].phy.b[1].dq[6], (0x1 << 31));
+ clrbits_le32(&ch[chn].phy.ca_cmd[6], (0x1 << 31));
+}
+
+static void dramc_hw_gating_init(void)
+{
+ for (u8 chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrbits_le32(&ch[chn].ao.stbcal,
+ (0x7 << 22) | (0x3 << 14) | (0x1 << 19) | (0x1 << 21));
+ setbits_le32(&ch[chn].ao.stbcal,
+ (0x1 << 20) | (0x3 << 28));
+ setbits_le32(&ch[chn].phy.misc_ctrl1, (0x1 << 24));
+
+ dramc_hw_dqs_gating_tracking(chn);
+ }
+}
+
+static void dramc_rx_input_delay_tracking_init(u8 chn)
+{
+ /* Enable RX_FIFO macro DIV4 clock CG */
+ write32(&ch[chn].phy.misc_cg_ctrl1, 0xffffffff);
+
+ /* DVS mode to RG mode */
+ clrbits_le32(&ch[chn].phy.r[0].b[0].rxdvs[2], (0x3 << 30));
+ clrbits_le32(&ch[chn].phy.r[0].b[1].rxdvs[2], (0x3 << 30));
+ clrbits_le32(&ch[chn].phy.r[1].b[0].rxdvs[2], (0x3 << 30));
+ clrbits_le32(&ch[chn].phy.r[1].b[1].rxdvs[2], (0x3 << 30));
+
+ clrbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 19));
+ clrbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 19));
+ setbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 9));
+ setbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 9));
+
+ for (size_t b = 0; b < 2; b++) {
+ /* tracking rising and update rising/falling together */
+ clrbits_le32(&ch[chn].phy.r[0].b[b].rxdvs[2], (0x1 << 29));
+ clrbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[2], (0x1 << 29));
+
+ /* DQS, DQ, DQM (DQ, DQM are tied together now)
+ * -> controlled using DQM MAX_MIN */
+ clrsetbits_le32(&ch[chn].phy.r[0].b[b].rxdvs[7],
+ (0x3f << 0) | (0x3f << 8) | (0x7f << 16) | (0x7f << 24),
+ (0x0 << 0) | (0x3f << 8) | (0x0 << 16) | (0x7f << 24));
+ clrsetbits_le32(&ch[chn].phy.r[0].b[b].rxdvs[1],
+ (0xffff << 16) | (0xffff << 0),
+ (0x2 << 16) | (0x2 << 0));
+
+ /* DQ/DQS Rx DLY adjustment for tracking mode */
+ clrbits_le32(&ch[chn].phy.r[0].b[b].rxdvs[2],
+ (0x3 << 26) | (0x3 << 24) | (0x3 << 18) | (0x3 << 16));
+
+ /* DQS, DQ, DQM (DQ, DQM are tied together now)
+ * -> controlled using DQM MAX_MIN */
+ clrsetbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[7],
+ (0x3f << 0) | (0x3f << 8) | (0x7f << 16) | (0x7f << 24),
+ (0x0 << 0) | (0x3f << 8) | (0x0 << 16) | (0x7f << 24));
+ clrsetbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[1],
+ (0xffff << 16) | (0xffff << 0),
+ (0x2 << 16) | (0x2 << 0));
+
+ /* DQ/DQS Rx DLY adjustment for tracking mode */
+ clrbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[2],
+ (0x3 << 26) | (0x3 << 24));
+ clrbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[2],
+ (0x3 << 18) | (0x3 << 16));
+ }
+}
+
+static void dramc_rx_input_delay_tracking(u8 chn)
+{
+ clrbits_le32(&ch[chn].phy.ca_cmd[10],
+ (0x7 << 28) | (0x7 << 24));
+
+ /* Rx DLY tracking setting (Static) */
+ clrsetbits_le32(&ch[chn].phy.b0_rxdvs[0],
+ (0x1 << 29) | (0xf << 4) | (0x1 << 0),
+ (0x1 << 29) | (0x0 << 4) | (0x1 << 0));
+ clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0],
+ (0x1 << 29) | (0xf << 4) | (0x1 << 0),
+ (0x1 << 29) | (0x0 << 4) | (0x1 << 0));
+
+ for (u8 b = 0; b < 2; b++) {
+ clrsetbits_le32(&ch[chn].phy.b[b].dq[9],
+ (0x7 << 28) | (0x7 << 24),
+ (0x1 << 28) | (0x0 << 24));
+ setbits_le32(&ch[chn].phy.b[b].dq[5], (0x1 << 31));
+ }
+
+ setbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 28) | (0x1 << 31));
+ setbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 28) | (0x1 << 31));
+
+ for (u8 rank = RANK_0; rank < RANK_MAX; rank++) {
+ /* Rx DLY tracking update enable (HW mode) */
+ clrsetbits_le32(&ch[chn].phy.r[rank].b[0].rxdvs[2],
+ (0x3 << 30) | (0x1 << 28) | (0x1 << 23),
+ (0x2 << 30) | (0x1 << 28) | (0x1 << 23));
+
+ clrsetbits_le32(&ch[chn].phy.r[rank].b[1].rxdvs[2],
+ (0x3 << 30) | (0x1 << 28) | (0x1 << 23),
+ (0x2 << 30) | (0x1 << 28) | (0x1 << 23));
+ }
+}
+
+static void dramc_impedance_tracking_enable(void)
+{
+ u8 chn;
+
+ setbits_le32(&ch[0].phy.misc_ctrl0, (0x1 << 10));
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ setbits_le32(&ch[chn].ao.impcal, (0x1 << 31) | (0x1 << 29) |
+ (0x1 << 26) | (0x1 << 17) | (0x7 << 11));
+ clrbits_le32(&ch[chn].ao.impcal, (0x1 << 30));
+ setbits_le32(&ch[chn].phy.misc_ctrl0, (0x1 << 18));
+ setbits_le32(&ch[chn].ao.impcal, (0x1 << 19));
+ }
+ setbits_le32(&ch[0].ao.impcal, (0x1 << 14));
+ setbits_le32(&ch[1].ao.refctrl0, (0x1 << 2));
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].ao.refctrl0, (0x1 << 3));
+}
+
+void dramc_runtime_config(void)
+{
+ u8 chn = 0, shu = 0, shuCnt = DRAM_DFS_SHUFFLE_MAX;
+
+ clrbits_le32(&ch[0].ao.refctrl0, (0x1 << 29));
+ clrbits_le32(&ch[1].ao.refctrl0, (0x1 << 29));
+
+ transfer_pll_to_spm_control();
+
+ setbits_le32(&mtk_spm->spm_power_on_val0, (0x3 << 25));
+
+ dramc_dbg("TX_TRACKING: OFF\n");
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ dramc_rx_input_delay_tracking_init(chn);
+ dramc_rx_input_delay_tracking(chn);
+ }
+ dramc_dbg("RX_TRACKING: ON\n");
+
+ dramc_hw_gating_init();
+ dramc_hw_gating_onoff(CHANNEL_A, GATING_ON);
+ dramc_dbg("HW_GATING: ON\n");
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrbits_le32(&ch[chn].ao.stbcal2,
+ (0x3 << 4) | (0x3 << 8) | (0x1 << 28));
+ }
+ dramc_dbg("HW_GATING DBG: OFF\n");
+
+ /* ZQCS_ENABLE_LP4 */
+ clrbits_le32(&ch[0].ao.spcmdctrl, (0x1 << 30));
+ clrbits_le32(&ch[1].ao.spcmdctrl, (0x1 << 30));
+ dramc_dbg("ZQCS_ENABLE_LP4: OFF\n");
+
+ enable_dramc_phy_dcm(0);
+ dramc_dbg("LOWPOWER_GOLDEN_SETTINGS(DCM): OFF\n");
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ for (shu = 0; shu < shuCnt; shu++)
+ clrbits_le32(&ch[chn].ao.shu[shu].dqsg_retry,
+ (0x1 << 1) | (0x3 << 13));
+ }
+ dramc_dbg("DUMMY_READ_FOR_DQS_GATING_RETRY: OFF\n");
+
+ write32(&ch[0].phy.misc_spm_ctrl0, 0xfbffefff);
+ write32(&ch[1].phy.misc_spm_ctrl0, 0xfbffefff);
+ write32(&ch[0].phy.misc_spm_ctrl2, 0xffffffef);
+ write32(&ch[1].phy.misc_spm_ctrl2, 0x7fffffef);
+ dramc_dbg("SPM_CONTROL_AFTERK: ON\n");
+
+ dramc_impedance_tracking_enable();
+ dramc_dbg("IMPEDANCE_TRACKING: ON\n");
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrbits_le32(&ch[chn].ao.spcmdctrl, (0x3 << 28));
+ setbits_le32(&ch[chn].ao.hw_mrr_fun,
+ (0x1 << 0) | (0x1 << 11));
+ dramc_dbg("TEMP_SENSOR: ON\n");
+
+
+ clrbits_le32(&ch[0].ao.refctrl0, (0x1 << 18));
+ dramc_dbg("PER_BANK_REFRESH: OFF\n");
+
+ setbits_le32(&ch[chn].phy.dvfs_emi_clk, (0x1 << 24));
+ setbits_le32(&ch[chn].ao.dvfsdll, (0x1 << 7));
+ }
+}
+
+void cke_fix_onoff(int option, u8 chn)
+{
+ u8 on, off;
+
+ /* if CKE is dynamic, set both CKE fix On and Off as 0 */
+ if (option == CKE_DYNAMIC) {
+ /* After CKE FIX on/off,
+ * CKE should be returned to dynamic (control by HW) */
+ on = off = 0;
+ } else {
+ /* if CKE fix on is set as 1,
+ * CKE fix off should also be set as 0; vice versa */
+ on = option;
+ off = (1 - option);
+ }
+
+ clrsetbits_le32(&ch[chn].ao.ckectrl,
+ (0x1 << 6) | (0x1 << 7), (on << 6) | (off << 7));
+}
+
+static void auto_refresh_cke_off(void)
+{
+ u8 chn;
+ u32 broadcast_bak = get_dramc_broadcast();
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].ao.refctrl0, (0x1 << 29));
+
+ udelay(3);
+ cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
+ cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
+
+ dramc_broadcast_onoff(broadcast_bak);
+}
+
+static void dramc_set_rank_engine2(u8 chn, u8 u1RankSel)
+{
+ setbits_le32(&ch[chn].ao.dramctrl,
+ 0x1 << DRAMCTRL_ADRDECEN_TARKMODE_SHIFT);
+ clrbits_le32(&ch[chn].ao.test2_4, TEST2_4_TESTAGENTRKSEL_MASK);
+ clrsetbits_le32(&ch[chn].ao.test2_4, TEST2_4_TESTAGENTRK_MASK,
+ (u1RankSel << TEST2_4_TESTAGENTRK_SHIFT));
+}
+
+static void save_restore_dummyrd(u8 chn, u8 type)
+{
+ static u32 uiReg0D0h = 0;
+
+ if (type == SAVE_VALUE)
+ uiReg0D0h = read32(&ch[chn].ao.dummy_rd);
+ else
+ write32(&ch[chn].ao.dummy_rd, uiReg0D0h);
+}
+
+void save_restore_multi_reg(u8 type, u32 **reg_addr, u32 reg_count)
+{
+ static u32 u4gpRegBackupVlaue[MAX_BACKUP_REG_CNT];
+ if (reg_count > MAX_BACKUP_REG_CNT) {
+ dramc_dbg("save restore count over %d\n", MAX_BACKUP_REG_CNT);
+ return;
+ }
+
+ if (type == SAVE_VALUE) {
+ for (int i = 0; i < reg_count; i++)
+ u4gpRegBackupVlaue[i] = read32(reg_addr[i]);
+ } else {
+ for (int i = 0; i < reg_count; i++)
+ write32(reg_addr[i], u4gpRegBackupVlaue[i]);
+ }
+}
+
+void dramc_engine2_init(u8 chn, u8 u1RankSel, u32 test2_1, u32 test2_2,
+ u8 testaudpat, u8 log2loopcount)
+{
+ dramc_set_rank_engine2(chn, u1RankSel);
+
+ save_restore_dummyrd(chn, SAVE_VALUE);
+ clrbits_le32(&ch[chn].ao.dummy_rd,
+ (0x1 << DUMMY_RD_DQSG_DMYRD_EN_SHIFT) |
+ (0x1 << DUMMY_RD_DQSG_DMYWR_EN_SHIFT) |
+ (0x1 << DUMMY_RD_DUMMY_RD_EN_SHIFT) |
+ (0x1 << DUMMY_RD_SREF_DMYRD_EN_SHIFT) |
+ (0x1 << DUMMY_RD_DMY_RD_DBG_SHIFT) |
+ (0x1 << DUMMY_RD_DMY_WR_DBG_SHIFT));
+ clrbits_le32(&ch[chn].nao.testchip_dma1,
+ 0x1 << TESTCHIP_DMA1_DMA_LP4MATAB_OPT_SHIFT);
+
+ clrbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TEST2W_SHIFT) |
+ (0x1 << TEST2_3_TEST2R_SHIFT) |
+ (0x1 << TEST2_3_TEST1_SHIFT));
+ clrsetbits_le32(&ch[chn].ao.test2_0,
+ TEST2_0_PAT0_MASK | TEST2_0_PAT1_MASK,
+ (((test2_1 >> 24) & 0xff) << TEST2_0_PAT0_SHIFT) |
+ (((test2_2 >> 24) & 0xff) << TEST2_0_PAT1_SHIFT));
+
+ write32(&ch[chn].ao.test2_1, (test2_1 << 4) & 0x00ffffff);
+ write32(&ch[chn].ao.test2_2, (test2_2 << 4) & 0x00ffffff);
+
+ if (testaudpat == TEST_XTALK_PATTERN) {
+ clrsetbits_le32(&ch[chn].ao.test2_4,
+ 0x1 << TEST2_4_TEST_REQ_LEN1_SHIFT |
+ (0x1 << TEST2_4_TESTAUDMODE_SHIFT) |
+ (0x1 << TEST2_4_TESTAUDBITINV_SHIFT) |
+ (0x1 << TEST2_4_TESTSSOPAT_SHIFT) |
+ (0x1 << TEST2_4_TESTSSOXTALKPAT_SHIFT),
+ 0x1 << TEST2_4_TESTXTALKPAT_SHIFT);
+ setbits_le32(&ch[chn].ao.perfctl0,
+ 0x1 << PERFCTL0_RWOFOEN_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TESTAUDPAT_SHIFT) |
+ TEST2_3_TESTCNT_MASK,
+ log2loopcount << TEST2_3_TESTCNT_SHIFT);
+ } else if (testaudpat == TEST_AUDIO_PATTERN) {
+ clrsetbits_le32(&ch[chn].ao.test2_4,
+ TEST2_4_TESTAUDINIT_MASK |
+ TEST2_4_TESTAUDINC_MASK |
+ (0x1 << TEST2_4_TESTXTALKPAT_SHIFT),
+ (0x00000011 << TEST2_4_TESTAUDINIT_SHIFT) |
+ (0x0000000d << TEST2_4_TESTAUDINC_SHIFT) |
+ (0x1 << TEST2_4_TESTAUDMODE_SHIFT) |
+ (0x1 << TEST2_4_TESTAUDBITINV_SHIFT));
+ clrsetbits_le32(&ch[chn].ao.test2_3, TEST2_3_TESTCNT_MASK,
+ (0x1 << TEST2_3_TESTAUDPAT_SHIFT) |
+ (log2loopcount << TEST2_3_TESTCNT_SHIFT));
+ } else {
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TESTAUDPAT_SHIFT) |
+ TEST2_3_TESTCNT_MASK,
+ (log2loopcount << TEST2_3_TESTCNT_SHIFT));
+ clrbits_le32(&ch[chn].ao.test2_4,
+ (0x1 << TEST2_4_TESTXTALKPAT_SHIFT));
+ }
+}
+
+static void dramc_engine2_check_complete(u8 chn)
+{
+ u32 u4loop_count = 0;
+ while ((read32(&ch[chn].nao.testrpt) &
+ (0x1 << TESTRPT_DM_CMP_CPT_RK0_SHIFT)) == 0) {
+ udelay(1);
+ u4loop_count++;
+
+ if (u4loop_count > MAX_CMP_CPT_WAIT_LOOP) {
+ dramc_dbg("MEASURE_A timeout\n");
+ break;
+ }
+ }
+
+}
+
+u32 dramc_engine2_run(u8 chn, enum dram_te_op wr, u8 testaudpat)
+{
+ u32 u4result = 0xffffffff;
+
+ if (wr == TE_OP_READ_CHECK) {
+ if ((testaudpat == TEST_AUDIO_PATTERN) ||
+ (testaudpat == TEST_XTALK_PATTERN))
+ clrbits_le32(&ch[chn].ao.test2_4,
+ (0x1 << TEST2_4_TESTAUDMODE_SHIFT));
+ } else if (wr == TE_OP_WRITE_READ_CHECK) {
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TEST2R_SHIFT) |
+ (0x1 << TEST2_3_TEST1_SHIFT),
+ (0x1 << TEST2_3_TEST2W_SHIFT));
+
+ dramc_engine2_check_complete(chn);
+ clrbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TEST2W_SHIFT) |
+ (0x1 << TEST2_3_TEST2R_SHIFT) |
+ (0x1 << TEST2_3_TEST1_SHIFT));
+ udelay(1);
+ }
+
+ /* do Read test */
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TEST2W_SHIFT) |
+ (0x1 << TEST2_3_TEST1_SHIFT),
+ (0x1 << TEST2_3_TEST2R_SHIFT));
+
+ dramc_engine2_check_complete(chn);
+
+ udelay(1);
+ u4result = read32(&ch[chn].nao.cmp_err);
+ clrbits_le32(&ch[chn].ao.test2_3,
+ (0x1 << TEST2_3_TEST2W_SHIFT) |
+ (0x1 << TEST2_3_TEST2R_SHIFT) |
+ (0x1 << TEST2_3_TEST1_SHIFT));
+
+ return u4result;
+}
+
+void dramc_engine2_end(u8 chn)
+{
+ clrbits_le32(&ch[chn].ao.test2_4, (0x1 << 17));
+
+ save_restore_dummyrd(chn, RESTORE_VALUE);
+}
+
+static void ddr_phy_pll_setting(u8 chn)
+{
+ u8 u1CAP_SEL;
+ u8 u1MID_FINE_TUNE_SEL;
+ u8 u1VTH_SEL;
+
+ u1VTH_SEL = 0x2;
+ u1CAP_SEL = 0x0;
+ u1MID_FINE_TUNE_SEL = 0x2;
+
+ clrbits_le32(&ch[chn].phy.shu[0].pll[4], 0xFFFF);
+ clrbits_le32(&ch[chn].phy.shu[0].pll[6], 0xFFFF);
+
+ if (chn == 0)
+ setbits_le32(&ch[chn].phy.misc_shu_opt, 0x1 << 18);
+ else if (chn == 1)
+ setbits_le32(&ch[chn].phy.misc_shu_opt, 0x2 << 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);
+
+ clrsetbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 1, 0x0 << 1);
+
+ if (chn == DLL_MASTER_CH) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_dll[0],
+ 0x1 << 31 | 0x1 << 30 | 0xf << 20 | 0xf << 16 |
+ 0xf << 12 | 0x1 << 10 | 0x1 << 9 | 0x1 << 4,
+ 0x0 << 31 | 0x0 << 30 | 0x6 << 20 | 0x9 << 16 |
+ 0x8 << 12 | 0x1 << 10 | 0x1 << 9 | 0x1 << 4);
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_dll[1],
+ 0x1 << 2 | 0x1 << 0, 0x1 << 2 | 0x0 << 0);
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[6],
+ 0x1 << 7, 0x1 << 7);
+ } else {
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_dll[0],
+ 0x1 << 31 | 0x1 << 30 | 0xf << 20 | 0xf << 16 |
+ 0xf << 12 | 0x1 << 10 | 0x1 << 9 | 0x1 << 4,
+ 0x1 << 31 | 0x1 << 30 | 0x7 << 20 | 0x7 << 16 |
+ 0x8 << 12 | 0x1 << 10 | 0x1 << 9 | 0x0 << 4);
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_dll[1],
+ 0x1 << 2 | 0x1 << 0, 0x0 << 2 | 0x1 << 0);
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[6],
+ 0x1 << 7, 0x0 << 7);
+ }
+
+ u32 *u4RegBackup[] = {
+ &ch[chn].phy.b[0].dq[7],
+ &ch[chn].phy.b[1].dq[7],
+ &ch[chn].phy.ca_cmd[7],
+ };
+
+ save_restore_multi_reg(SAVE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ 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);
+
+ /* 26M */
+ clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl0, (0x3<<4), 0x0 << 4);
+
+ /* MID FINE_TUNE */
+ clrbits_le32(&ch[chn].phy.shu[0].b[0].dq[6], (0x1<<26)|(0x1<<27));
+ clrbits_le32(&ch[chn].phy.shu[0].b[1].dq[6], (0x1<<26)|(0x1<<27));
+ clrbits_le32(&ch[chn].phy.shu[0].ca_cmd[6], (0x1<<26)|(0x1<<27));
+ clrbits_le32(&ch[chn].phy.pll4, (0x1<<16)|(0x1<<22));
+
+ /* PLL */
+ clrbits_le32(&ch[chn].phy.pll1, (0x1<<31));
+ clrbits_le32(&ch[chn].phy.pll2, (0x1<<31));
+
+ /* DLL */
+ clrbits_le32(&ch[chn].phy.ca_dll_fine_tune[2], (0x0<<0));
+ clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[2], (0x0<<0));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[2], (0x0<<0));
+ setbits_le32(&ch[chn].phy.b[0].dll_fine_tune[2],
+ (0x1<<10) | (0x1<<11) | (0x1<<13) | (0x1<<14) | (0x1<<15) |
+ (0x1<<17) | (0x1<<19) | (0x1<<27) | (0x1<<31));
+ setbits_le32(&ch[chn].phy.b[1].dll_fine_tune[2],
+ (0x1<<10) | (0x1<<11) | (0x1<<13) | (0x1<<14) | (0x1<<15) |
+ (0x1<<17) | (0x1<<19) | (0x1<<27) | (0x1<<31));
+ setbits_le32(&ch[chn].phy.ca_dll_fine_tune[2],
+ (0x1<<10) | (0x1<<11) | (0x1<<13) | (0x1<<15) | (0x1<<16) |
+ (0x1<<17) | (0x1<<19) | (0x1<<27) | (0x1<<31));
+
+ /* RESETB */
+ clrbits_le32(&ch[chn].phy.ca_dll_fine_tune[0], (0x1<<3));
+ clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[0], (0x1<<3));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[0], (0x1<<3));
+
+ udelay(1);
+
+ /* MPLL 52M */
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[8],
+ (0x7<<0)|(0x3<<18), (0x0<<0)|(0x1<<18));
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[10],
+ (0x7<<0)|(0x3<<18), (0x0<<0)|(0x1<<18));
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[5],
+ (0xffff<<16) | 0x1 << 0, (0x7b00<<16));
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[7],
+ (0xffff<<16) | 0x1 << 0, (0x7b00<<16));
+
+ setbits_le32(&ch[chn].phy.ca_dll_fine_tune[0], (0x1<<1));
+ setbits_le32(&ch[chn].phy.b[0].dll_fine_tune[0], (0x1<<1));
+ setbits_le32(&ch[chn].phy.b[1].dll_fine_tune[0], (0x1<<1));
+
+ clrbits_le32(&ch[chn].phy.ca_dll_fine_tune[1], (0x1<<11));
+ clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[1], (0x1<<19));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[1], (0x1<<19));
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[6],
+ (0x3<<22) | (0x3<<24) | (0x3<<28),
+ (u1MID_FINE_TUNE_SEL<<22) | (u1VTH_SEL<<24) | (u1CAP_SEL<<28));
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[6],
+ (0x3<<22) | (0x3<<24) | (0x3<<28),
+ (u1MID_FINE_TUNE_SEL<<22)|(u1VTH_SEL<<24) | (u1CAP_SEL<<28));
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[6],
+ (0x3<<22) | (0x3<<24) | (0x3<<28),
+ (u1MID_FINE_TUNE_SEL<<22) | (u1VTH_SEL<<24) | (u1CAP_SEL<<28));
+
+ /* RESETB */
+ setbits_le32(&ch[chn].phy.ca_dll_fine_tune[0], (0x1<<3));
+ setbits_le32(&ch[chn].phy.b[0].dll_fine_tune[0], (0x1<<3));
+ setbits_le32(&ch[chn].phy.b[1].dll_fine_tune[0], (0x1<<3));
+ udelay(1);
+
+ /* PLL EN */
+ setbits_le32(&ch[chn].phy.pll1, (0x1<<31));
+ setbits_le32(&ch[chn].phy.pll2, (0x1<<31));
+ udelay(100);
+
+ /* MID FINE_TUNE Init 1 */
+ setbits_le32(&ch[chn].phy.pll4, (0x1<<16)|(0x1<<22));
+ udelay(1);
+
+ /* MID FINE_TUNE Init 2 */
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[6],
+ (0x1<<26) | (0x1<<27), (0x1<<26) | (0x0<<27));
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[6],
+ (0x1<<26) | (0x1<<27), (0x1<<26) | (0x0<<27));
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[6],
+ (0x1<<26) | (0x1<<27), (0x1<<26) | (0x0<<27));
+ udelay(1);
+ if (chn == 0)
+ clrsetbits_le32(&ch[chn].phy.ca_dll_fine_tune[3],
+ (0x1<<13) | (0x1<<15) | (0x1<<16) |
+ (0x1<<17) | (0x1<<19),
+ (0x1<<13) | (0x1<<15) | (0x1<<16) |
+ (0x1<<17) | (0x1<<19));
+ else if (chn == 1)
+ clrsetbits_le32(&ch[chn].phy.ca_dll_fine_tune[3],
+ (0x1<<13) | (0x1<<15) | (0x1<<16) |
+ (0x1<<17) | (0x1<<19),
+ (0x1<<13) | (0x1<<15) | (0x1<<16) | (0x1<<17));
+
+ setbits_le32(&ch[chn].phy.b[0].dll_fine_tune[3],
+ (0x1<<11) | (0x1<<13) | (0x1<<14) | (0x1<<15) | (0x1<<17));
+ 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) |
+ (0x1 << 19) | (0x1 << 27) | (0x1 << 31));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[2],
+ (0x1 << 10) | (0x1 << 13) |
+ (0x1 << 14) | (0x1 << 15) | (0x1 << 17) |
+ (0x1 << 19) | (0x1 << 27) | (0x1 << 31));
+
+ setbits_le32(&ch[chn].phy.ca_dll_fine_tune[2], (0x1 << 11));
+ clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[2], (0x1 << 11));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[2], (0x1 << 11));
+ udelay(2);
+
+ setbits_le32(&ch[chn].phy.misc_cg_ctrl0, (0x1 << 4));
+ udelay(1);
+
+ /* DLL */
+ setbits_le32(&ch[chn].phy.ca_dll_fine_tune[2], (0x1 << 0));
+ udelay(1);
+ setbits_le32(&ch[chn].phy.b[0].dll_fine_tune[2], (0x1 << 0));
+ udelay(1);
+ setbits_le32(&ch[chn].phy.b[1].dll_fine_tune[2], (0x1 << 0));
+ udelay(1);
+
+ clrbits_le32(&ch[chn].phy.ca_cmd[2], 0x1 << 21);
+
+ save_restore_multi_reg(RESTORE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ cke_fix_onoff(CKE_DYNAMIC, CHANNEL_A);
+ cke_fix_onoff(CKE_DYNAMIC, CHANNEL_B);
+
+ setbits_le32(&ch[chn].phy.shu[0].pll[5], (0x1<<0));
+ setbits_le32(&ch[chn].phy.shu[0].pll[7], (0x1<<0));
+ setbits_le32(&ch[chn].phy.shu[0].pll[14], (0x1<<1));
+ setbits_le32(&ch[chn].phy.shu[0].pll20, (0x1<<1));
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[14],
+ (0xffff<<16), 0x0208 << 16);
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll20,
+ (0xffff<<16), 0x0208 << 16);
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll[15],
+ (0xffffffff<<0), 0xC03 << 16);
+ clrsetbits_le32(&ch[chn].phy.shu[0].pll21,
+ (0xffffffff<<0), 0xC03 << 16);
+}
+
+static void update_initial_settings(void)
+{
+ u16 u2RXVrefDefault = 0x8;
+ u8 chn = 0;
+
+ setbits_le32(&ch[0].ao.shu[0].odtctrl, (0x1 << 0));
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 15));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 15));
+
+ for (size_t b = 0; b < 2; b++)
+ for (size_t r = 0; r < 2; r++)
+ clrbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x1 << 23) | (0x1 << 28) | (0x3 << 30));
+ clrbits_le32(&ch[0].phy.shu[0].ca_cmd[7], (0xf << 0));
+
+ setbits_le32(&ch[0].phy.ca_cmd[3], (0x1 << 10));
+ setbits_le32(&ch[0].phy.ca_cmd[10], (0x1 << 5));
+ clrsetbits_le32(&ch[0].phy.ca_cmd[6], 0x3 << 14, 0x1 << 14);
+ setbits_le32(&ch[0].phy.b[0].dq[3],
+ (0x1 << 5) | (0x1 << 6) | (0x1 << 7));
+ setbits_le32(&ch[0].phy.b[1].dq[3],
+ (0x1 << 5) | (0x1 << 6) | (0x1 << 7));
+ setbits_le32(&ch[0].phy.ca_cmd[3], (0x1 << 5) | (0x1 << 7));
+ clrbits_le32(&ch[0].phy.b[0].dq[3], (0x1 << 1));
+ clrbits_le32(&ch[0].phy.b[1].dq[3], (0x1 << 1));
+ setbits_le32(&ch[0].phy.b[0].dq[5], (0x1 << 31));
+ setbits_le32(&ch[0].phy.b[1].dq[5], (0x1 << 31));
+ setbits_le32(&ch[0].phy.ca_cmd[5], (0x1 << 31));
+
+ clrsetbits_le32(&ch[0].phy.ca_cmd[6], 0xf << 16, 0x3 << 16);
+ clrsetbits_le32(&ch[0].phy.misc_imp_ctrl0,
+ (0x1 << 5) | (0x1 << 6),
+ (0x1 << 5) | (0x0 << 6));
+ setbits_le32(&ch[0].phy.b[0].dq[6], (0x1 << 9));
+ setbits_le32(&ch[0].phy.b[1].dq[6], (0x1 << 9));
+ setbits_le32(&ch[0].phy.ca_cmd[6], (0x1 << 9));
+ clrsetbits_le32(&ch[0].phy.b[0].dq[6], (0x3 << 0), (0x1 << 0));
+ clrsetbits_le32(&ch[0].phy.b[1].dq[6], (0x1 << 0), (0x1 << 0));
+ clrsetbits_le32(&ch[0].phy.ca_cmd[6], (0x3 << 0), (0x1 << 0));
+
+ setbits_le32(&ch[0].phy.ca_cmd[6], (0x1 << 6));
+ setbits_le32(&ch[0].phy.b[0].dq[6], (0x1 << 3));
+ setbits_le32(&ch[0].phy.b[1].dq[6], (0x1 << 3));
+ setbits_le32(&ch[0].phy.ca_cmd[6], (0x1 << 3));
+ setbits_le32(&ch[0].phy.b[0].dq[6], (0x1 << 5));
+ setbits_le32(&ch[0].phy.b[1].dq[6], (0x1 << 5));
+ setbits_le32(&ch[0].phy.ca_cmd[6], (0x1 << 5));
+
+ u2RXVrefDefault = 0xE;
+ for (u8 b = 0; b < 2; b++) {
+ clrsetbits_le32(&ch[0].phy.shu[0].b[b].dq[5],
+ (0x3f << 0), (u2RXVrefDefault << 0));
+ clrsetbits_le32(&ch[0].phy.b[b].dq[5],
+ (0x3f << 8), (u2RXVrefDefault << 8));
+ }
+
+ for (chn = 0; chn < CHANNEL_NUM; 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));
+
+ dramc_gating_mode(chn, 1);
+ }
+
+ setbits_le32(&ch[0].phy.ca_cmd[8], (0x1 << 19));
+ clrbits_le32(&ch[0].phy.ca_cmd[8], (0x1 << 18));
+ clrsetbits_le32(&ch[0].ao.shu[0].misc, (0xf << 0), (0x2 << 0));
+ clrsetbits_le32(&ch[0].ao.shu[0].dqsg, (0x3f << 20) | (0x1 << 16),
+ (0x2a << 20) | (0x1 << 16));
+
+ clrbits_le32(&ch[0].phy.shu[0].b[0].dq[5], (0x3f << 8));
+ clrbits_le32(&ch[0].phy.shu[0].b[1].dq[5], (0x3f << 8));
+ clrbits_le32(&ch[0].phy.shu[0].ca_cmd[5], (0x3f << 8));
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ for (chn = 0; chn < CHANNEL_NUM; 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));
+ }
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ /* IMP Tracking Init Settings */
+ clrsetbits_le32(&ch[0].ao.shu[0].impcal1,
+ (0x7 << 0) | (0x7 << 17) | (0xff << 20) | (0xf << 28),
+ (0x4 << 0) | (0x4 << 17) | (0x10 << 20) | (0x8 << 28));
+
+ setbits_le32(&ch[0].ao.srefctrl, (0xf << 12));
+ setbits_le32(&ch[0].ao.pre_tdqsck[0], (0x1 << 17));
+
+ setbits_le32(&ch[0].ao.shu[0].misc, (0xf << 12));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dq[8],
+ (0xffff << 0) | (0x1 << 15) | (0x3ff << 22),
+ (0x7fff << 0) | (0x0 << 15) | (0x3ff << 22));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[1].dq[8],
+ (0xffff << 0) | (0x1 << 15) | (0x3ff << 22),
+ (0x7fff << 0) | (0x0 << 15) | (0x3ff << 22));
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[8],
+ (0xffff << 0) | (0x1 << 15) | (0x3ff << 22),
+ (0x7fff << 0) | (0x0 << 15) | (0x3ff << 22));
+ setbits_le32(&ch[0].phy.misc_ctrl3, (0x1 << 26));
+ clrbits_le32(&ch[0].phy.shu[0].b[0].dq[7],
+ (0xf << 8) | (0x1 << 12) | (0x1 << 13));
+ clrbits_le32(&ch[0].phy.shu[0].b[1].dq[7],
+ (0xf << 8) | (0x1 << 12) | (0x1 << 13));
+ clrsetbits_le32(&ch[0].ao.clkar,
+ (0xffff << 0) | (0x1 << 15),
+ (0x7fff << 0) | (0x1 << 15));
+
+ clrbits_le32(&ch[0].ao.shu[0].dqsg_retry, (0x1 << 29));
+ clrbits_le32(&ch[0].ao.write_lev, (0x1 << 2));
+ setbits_le32(&ch[0].ao.dummy_rd, (0x1 << 24));
+ clrbits_le32(&ch[0].ao.stbcal2, (0x1 << 0) | (0x1 << 1));
+ setbits_le32(&ch[0].ao.eyescan,
+ (0x1 << 8) | (0x1 << 9) | (0x1 << 10));
+ setbits_le32(&ch[0].ao.shu[0].odtctrl, (0x1 << 2) | (0x1 << 3));
+
+ setbits_le32(&ch[0].phy.shu[0].b[0].dll[0], (0x1 << 0));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dll[0], (0x1 << 0));
+ setbits_le32(&ch[0].phy.ca_dll_fine_tune[1], (0x1 << 21));
+
+ setbits_le32(&ch[0].ao.perfctl0,
+ (0x1 << 15) | (0x1 << 19) | (0x1 << 26));
+ setbits_le32(&ch[0].ao.srefctrl, (0x1 << 22));
+ clrsetbits_le32(&ch[0].ao.shuctrl1, (0xff << 0), (0x1a << 0));
+ setbits_le32(&ch[0].phy.b[0].dq[6],
+ (0x1 << 7) | (0x1 << 12));
+ setbits_le32(&ch[0].phy.b[1].dq[6],
+ (0x1 << 7) | (0x1 << 12));
+ setbits_le32(&ch[0].phy.ca_cmd[6], (0x1 << 7) | (0x1 << 12));
+ setbits_le32(&ch[0].ao.stbcal2, (0x1 << 16));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dq[7],
+ (0x7 << 29) | (0x1 << 28) | (0x7 << 25) | (0x1 << 24),
+ (0x0 << 29) | (0x1 << 28) | (0x1 << 25) | (0x1 << 24));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[1].dq[7],
+ (0x7 << 29) | (0x1 << 28) | (0x7 << 25) | (0x1 << 24),
+ (0x0 << 29) | (0x1 << 28) | (0x1 << 25) | (0x1 << 24));
+
+ /* Disable RODT tracking */
+ clrbits_le32(&ch[0].ao.shu[0].rodtenstb, (0x1 << 0));
+
+ /* Rx Gating tracking settings */
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].ao.shu[0].dqsg,
+ (0x1 << 11) | (0xf << 12),
+ (0x1 << 11) | (0x9 << 12));
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[0].dqscal,
+ (0x1 << 7) | (0x1 << 15),
+ (0x0 << 7) | (0x0 << 15));
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[1].dqscal,
+ (0x1 << 7) | (0x1 << 15),
+ (0x0 << 7) | (0x0 << 15));
+ clrsetbits_le32(&ch[chn].ao.shu[0].stbcal,
+ (0x7 << 4) | (0x1 << 8),
+ (0x1 << 4) | (0x1 << 8));
+ }
+
+ clrsetbits_le32(&ch[0].phy.b[0].dq[9],
+ (0xff << 8), (0x4 << 8));
+ clrsetbits_le32(&ch[0].phy.b[1].dq[9],
+ (0xff << 8), (0x4 << 8));
+ clrbits_le32(&ch[0].phy.ca_cmd[10], (0xff << 8));
+
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[8], (0x1 << 24));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[8], (0x1 << 24));
+
+ /* Enable WDQS */
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dll[1],
+ (0x1 << 16) | (0x1 << 17),
+ (0x0 << 16) | (0x1 << 17));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[1].dll[1],
+ (0x1 << 16) | (0x1 << 17),
+ (0x0 << 16) | (0x1 << 17));
+ setbits_le32(&ch[0].ao.shu[0].odtctrl,
+ (0x1 << 0) | (0x1 << 30) | (0x1 << 31));
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 15));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 15));
+
+ setbits_le32(&ch[0].ao.drsctrl, (0x1 << 19));
+ setbits_le32(&ch[0].ao.refctrl0, (0x1 << 28));
+ setbits_le32(&ch[0].ao.zqcs, (0x1 << 19));
+ setbits_le32(&ch[0].ao.dummy_rd, (0x3 << 26));
+ setbits_le32(&ch[0].ao.shuctrl2, (0x1 << 8));
+ clrsetbits_le32(&ch[0].ao.shuctrl3,
+ (0xff << 24), (0xb << 24));
+ setbits_le32(&ch[0].phy.misc_ctrl3, (0x1 << 27));
+
+ setbits_le32(&ch[0].phy.b[0].dll_fine_tune[1], (0x3 << 20));
+ setbits_le32(&ch[0].phy.b[1].dll_fine_tune[1], (0x3 << 20));
+ setbits_le32(&ch[0].phy.ca_dll_fine_tune[1], (0x1 << 20));
+ clrbits_le32(&ch[0].phy.misc_ctrl0, (0x1 << 27));
+ setbits_le32(&ch[0].phy.misc_rxdvs[2], (0x1 << 8));
+ setbits_le32(&ch[0].ao.clkctrl, (0x1 << 7));
+ setbits_le32(&ch[0].ao.refctrl1, (0x1 << 7));
+ clrsetbits_le32(&ch[0].ao.shuctrl,
+ (0x1 << 2) | (0x3 << 6) | (0x3 << 26),
+ (0x0 << 2) | (0x3 << 6) | (0x3 << 26));
+ setbits_le32(&ch[0].ao.shuctrl2, (0x1 << 31) | (0x3 << 10));
+ clrbits_le32(&ch[0].ao.stbcal2, (0xf << 4));
+ clrbits_le32(&ch[0].ao.pre_tdqsck[0], (0x3 << 19));
+
+ 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));
+
+ /* MP setting should set CKECTRL_CKELCKFIX as 1 */
+ 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)
+{
+ u8 chn;
+
+ /* reset dram = low */
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ clrbits_le32(&ch[chn].phy.misc_ctrl1, (0x1 << 13));
+
+ /* CKE low */
+ cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
+ cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
+
+ /* delay tINIT1=200us(min) & tINIT2=10ns(min)*/
+ udelay(200);
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].phy.misc_ctrl1, (0x1 << 13));
+
+ /* Disable HW MIOCK control to make CLK always on */
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].ao.dramc_pd_ctrl, (0x1 << 26));
+
+ udelay(2000);
+
+ /* CKE high */
+ cke_fix_onoff(CKE_FIXON, CHANNEL_A);
+ cke_fix_onoff(CKE_FIXON, CHANNEL_B);
+
+ udelay(2);
+ dramc_dbg("APPLY_LP4_POWER_INIT_SEQUENCE\n");
+}
+
+static void ddr_phy_reserved_rg_setting(void)
+{
+ u8 chn;
+
+ /* fine tune */
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[6],
+ (0xFFFF << 6), (0x3 << 6) | (0x4 << 8) | (0x3 << 17));
+ clrsetbits_le32(&ch[1].phy.shu[0].ca_cmd[6],
+ (0xFFFF << 6), (0x1 << 6) | (0x4 << 8) | (0x3 << 17));
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_dll[1],
+ (0xf << 9) | (0x1f << 16) | (0x7ff << 21),
+ (0x1 << 8) | (0x7 << 13) | (0x4 << 16));
+
+ for (u8 b = 0; b < 2; b++) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[b].dq[6],
+ (0x3f << 11) | (0x7 << 19),
+ (0x1 << 6) | (0x1 << 10) | (0x3 << 17));
+
+ /* TX */
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[b].dll[1],
+ (0x3 << 8) | (0x3 << 11) |
+ (0x7 << 14) | (0x3fff << 18),
+ (0x1 << 10) | (0x1 << 13) | (0x1 << 17));
+ }
+ }
+}
+
+static void dramc_duty_set_clk_delay(u8 chn, s8 clkDelay)
+{
+ size_t rank;
+ u8 delay, delayb, revb0, revb1;
+
+ delay = (clkDelay < 0) ? -clkDelay : 0;
+ delayb = (clkDelay < 0) ? 0 : clkDelay;
+ revb0 = (delay) ? 1 : 0;
+ revb1 = (delayb) ? 1 : 0;
+
+ for (rank = 0; rank < RANK_MAX; rank++) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[1],
+ (0xf << 24) | (0xf << 28),
+ (delay << 24) | (delay << 28));
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[0],
+ (0xf << 24) | (0xf << 28),
+ (delayb << 24) | (delayb << 28));
+ }
+ clrsetbits_le32(&ch[chn].phy.shu[0].ca_cmd[3],
+ (0x3 << 8), (revb0 << 8) | (revb1 << 9));
+}
+
+static void dramc_duty_set_dqs_delay(u8 chn, s8 dqsDelay)
+{
+ size_t rank, dqs;
+ u8 delay, delayb, revb0, revb1;
+
+ delay = (dqsDelay < 0) ? -dqsDelay : 0;
+ delayb = (dqsDelay < 0) ? 0 : dqsDelay;
+ revb0 = (delay) ? 1 : 0;
+ revb1 = (delayb) ? 1 : 0;
+
+ for (rank = 0; rank < RANK_MAX; rank++) {
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ clrsetbits_le32(
+ &ch[chn].phy.shu[0].rk[rank].b[dqs].dq[1],
+ (0xf << 24) | (0xf << 28) |
+ (0xf << 16) | (0xf << 20),
+ (delay << 24) | (delay << 28) |
+ (delayb << 16) | (delayb << 20));
+
+ }
+ }
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dll[1],
+ (0x3 << 8), (revb0 << 8) | (revb1 << 9));
+}
+
+static void dramc_duty_calibration(u8 chn, s8 clkDelay, s8 dqsDelay)
+{
+ dramc_duty_set_clk_delay(chn, clkDelay);
+ dramc_duty_set_dqs_delay(chn, dqsDelay);
+}
+
+static void dramc_mode_reg_init(void)
+{
+ u8 u1MR12Value[CHANNEL_NUM][RANK_MAX][FSP_MAX] = {
+ {{0x5d, 0x5d}, {0x5d, 0x5d} },
+ {{0x5d, 0x5d}, {0x5d, 0x5d} },
+ };
+
+ u8 u1MR14Value_06VDDQ[CHANNEL_NUM][RANK_MAX][FSP_MAX] = {
+ {{0x5d, 0x10}, {0x5d, 0x10} },
+ {{0x5d, 0x10}, {0x5d, 0x10} },
+ };
+
+ u8 chn, rank;
+ u32 broadcast_bak = get_dramc_broadcast();
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+
+ dramc_power_on_sequence();
+
+ /* Fix nWR value to 30 (MR01[6:4] = 101B) for DDR3200
+ * Other vendors: Use default MR01 for each FSP
+ * (Set in vInitGlobalVariablesByCondition() )
+ */
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ u8 u1MR2Value[FSP_MAX] = { 0x0b, 0x2d};
+ u8 u1MR13Value_t = 0xc0 | (MR13_RRO << 4) | (1 << 3);
+ u8 u1MR01Value[FSP_MAX] = { 0x56, 0x56};
+ u8 u1MR11Value[FSP_MAX] = { 0x0, 0x23};
+ u8 u1MR13Value[FSP_MAX] = { 0x0 | (MR13_RRO << 4) | (1 << 3),
+ 0x40 | (MR13_RRO << 4) | (1 << 3)};
+ u8 u1MR22Value[FSP_MAX] = {0x38, 0x34};
+ for (rank = 0; rank < 2; rank++) {
+ dramc_dbg("%s CH%u RK%u\n", __func__, chn, rank);
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ (0x3 << 24), (rank << 24));
+
+ /* ZQ calobration should be done before CBT calibration
+ * by switching to low frequency */
+ dramc_zq_calibration(chn, rank);
+
+ for (uint32_t fsp = FSP_0; fsp < FSP_MAX; fsp++) {
+ dramc_dbg("chn:%d,rank:%d,fsp%d\n",
+ chn, rank, fsp);
+
+ dramc_mode_reg_write(chn,
+ 0xd, u1MR13Value[fsp]);
+
+ /* MR12 use previous value
+ * MR12 VREF-CA */
+ dramc_mode_reg_write(chn,
+ 0xc, u1MR12Value[chn][rank][fsp]);
+ dramc_mode_reg_write(chn,
+ 0x1, u1MR01Value[fsp]);
+ dramc_mode_reg_write(chn,
+ 0x2, u1MR2Value[fsp]);
+ dramc_mode_reg_write(chn,
+ 0xb, u1MR11Value[fsp]); /* ODT */
+
+ /* SOC-ODT, ODTE-CK, ODTE-CS, Disable ODTD-CA */
+ dramc_mode_reg_write(chn,
+ 0x16, u1MR22Value[fsp]);
+
+ /* MR14 use previous value
+ * MR14 VREF-DQ */
+ dramc_mode_reg_write(chn, 0xe,
+ u1MR14Value_06VDDQ[chn][rank][fsp]);
+
+ /* MR3 set write-DBI and read-DBI */
+ u8 u1MR03Value = 0x30;
+ dramc_mode_reg_write(chn, 0x3, u1MR03Value);
+ }
+ }
+
+ /* FSP-1 */
+ u1MR13Value_t = 0xc0 | (MR13_RRO<<4) | (1<<3);
+ dramc_mode_reg_write_by_rank(chn, RANK_0,
+ 0xd, u1MR13Value_t);
+ dramc_mode_reg_write_by_rank(chn, RANK_1,
+ 0xd, u1MR13Value_t);
+
+ clrsetbits_le32(&ch[chn].ao.shu[0].hwset_mr13,
+ (0x1fff << 0) | (0xff << 16),
+ (13 << 0) | ((u1MR13Value_t | 0x1 << 3) << 16));
+
+ clrsetbits_le32(&ch[chn].ao.shu[0].hwset_vrcg,
+ (0x1fff << 0) | (0xff << 16),
+ (13 << 0) | ((u1MR13Value_t | (0x1 << 3)) << 16));
+
+ clrsetbits_le32(&ch[chn].ao.shu[0].hwset_mr2,
+ (0x1fff << 0) | (0xff << 16),
+ (2 << 0) | (u1MR2Value[FSP_1] << 16));
+ }
+
+ clrsetbits_le32(&ch[0].ao.mrs, (0x3 << 24), (RANK_0 << 24));
+ clrsetbits_le32(&ch[1].ao.mrs, (0x3 << 24), (RANK_0 << 24));
+
+ dramc_broadcast_onoff(broadcast_bak);
+}
+
+static u8 get_cbt_mode(const struct sdram_params *params)
+{
+ return params->cbt_mode_extern;
+}
+
+static void dramc_setting(const struct sdram_params *params)
+{
+ u8 chn;
+
+ auto_refresh_cke_off();
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+
+ /* before switch clock from 26M to PHY, need to init PHY clock first
+ * move CKMUX_SEL_R_PHYCTRLMUX to here (it was originally between
+ * MISC_CG_CTRL0_CLK_MEM_SEL and MISC_CTRL0_R_DMRDSEL_DIV2_OPT)
+ * PHYCTRLDCM 1: follow DDRPHY_conf DCM settings,
+ * 0: follow infra DCM settings */
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].phy.ckmux_sel,
+ (0x1 << 0) | (0x1 << 1));
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ setbits_le32(&ch[0].phy.misc_cg_ctrl0, (0x1 << 0));
+
+ /* 26M */
+ clrbits_le32(&ch[0].phy.misc_cg_ctrl0, (0x3 << 4));
+ clrbits_le32(&ch[0].phy.misc_ctrl0, (0x1 << 17));
+
+ /* LP4_3200_initial_setting_shu1 begin */
+ clrbits_le32(&ch[0].phy.misc_spm_ctrl1, (0x0000000f << 0));
+ write32(&ch[0].phy.misc_spm_ctrl2, ~(0xffffffff << 0));
+ write32(&ch[0].phy.misc_spm_ctrl0, ~(0xffffffff << 0));
+
+ write32(&ch[0].phy.misc_cg_ctrl2, 0x6003bf);
+ write32(&ch[0].phy.misc_cg_ctrl4, 0x333f3f00);
+ setbits_le32(&ch[0].phy.shu[0].pll[1], (0x1 << 4)|(0x7 << 1));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dq[7],
+ (0x3f << 0), (0x10 << 0)); /* combine */
+ clrbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x0f << 0));
+
+ clrsetbits_le32(&ch[0].phy.shu[0].pll[4],
+ (0x3 << 18) | (0x3 << 24) | (0x3 << 26),
+ (0x2 << 18) | (0x1 << 24) | (0x1 << 26));
+ clrsetbits_le32(&ch[0].phy.shu[0].pll[6],
+ (0x3 << 18) | (0x3 << 24) | (0x3 << 26),
+ (0x2 << 18) | (0x1 << 24) | (0x1 << 26));
+
+ clrbits_le32(&ch[0].phy.shu[0].pll[14], (0x1 << 1));
+ clrbits_le32(&ch[0].phy.shu[0].pll20, (0x1 << 1));
+ clrbits_le32(&ch[0].phy.ca_cmd[2], (0x3 << 16) | (0x3 << 20));
+ for (size_t b = 0; b < 2; b++)
+ clrbits_le32(&ch[0].phy.b[b].dq[2],
+ (0x3 << 16) | (0x3 << 20));
+ for (size_t b = 0; b < 2; b++)
+ clrsetbits_le32(&ch[0].phy.b[b].dq[9],
+ (0x7 << 28), (0x1 << 28));
+ clrbits_le32(&ch[0].phy.ca_cmd[10], (0x7 << 28));
+
+ setbits_le32(&ch[0].phy.b0_rxdvs[0], (0x1 << 28));
+ setbits_le32(&ch[0].phy.b1_rxdvs[0], (0x1 << 28));
+ setbits_le32(&ch[0].phy.b0_rxdvs[0], (0x1 << 9));
+ setbits_le32(&ch[0].phy.b1_rxdvs[0], (0x1 << 9));
+
+ for (size_t b = 0; b < 2; b++) {
+ for (size_t r = 0; r < 2; r++)
+ setbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x1 << 29));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[b].dq[5],
+ (0x7 << 20), (0x3 << 20));
+
+ for (size_t r = 0; r < 2; r++) {
+ clrsetbits_le32(&ch[0].phy.r[r].b[b].rxdvs[1],
+ (0xffff << 0) | (0xffff << 16),
+ (0x2 << 0) | (0x2 << 16));
+ clrsetbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x1 << 23) | (0x1 << 28) | (0x3 << 30),
+ (0x1 << 23) | (0x1 << 28) | (0x2 << 30));
+ }
+ }
+
+ clrbits_le32(&ch[0].phy.b0_rxdvs[0], (0x1 << 28));
+ clrbits_le32(&ch[0].phy.b1_rxdvs[0], (0x1 << 28));
+
+ for (size_t b = 0; b < 2; b++) {
+ setbits_le32(&ch[0].phy.b[b].dq[9], (0x1 << 0));
+
+ for (size_t r = 0; r < 2; r++)
+ clrsetbits_le32(&ch[0].phy.shu[0].rk[r].b[b].dq[7],
+ (0x3f << 8) | (0x3f << 16),
+ (0x1f << 8) | (0x1f << 16));
+
+ clrsetbits_le32(&ch[0].phy.b[b].dq[4],
+ (0x7f << 0) | (0x7f << 8),
+ (0x10 << 0) | (0x10 << 8));
+ clrsetbits_le32(&ch[0].phy.b[b].dq[5],
+ (0xff << 0) | (0x3f << 8) | (0x1 << 16) | (0xf << 20) |
+ (0x1 << 24),
+ (0x10 << 0) | (0xe << 8) | (0x1 << 16) | (0x1 << 20) |
+ (0x0 << 24));
+ clrsetbits_le32(&ch[0].phy.b[b].dq[6],
+ (0x1 << 4) | (0x1 << 7) | (0x1 << 12) | (0x3 << 14) |
+ (0xf << 16) | (0x1 << 24),
+ (0x0 << 4) | (0x1 << 7) | (0x1 << 12) | (0x0 << 14) |
+ (0x3 << 16) | (0x1 << 24));
+ clrsetbits_le32(&ch[0].phy.b[b].dq[5],
+ (0xff << 0) | (0x1 << 25),
+ (0x0 << 0) | (0x1 << 25));
+ }
+
+ setbits_le32(&ch[0].phy.ca_cmd[3],
+ (0x1 << 2) | (0x1 << 3) | (0x1 << 7));
+ clrsetbits_le32(&ch[0].phy.ca_cmd[6],
+ (0x1 << 6) | (0x3 << 14) | (0x1 << 16),
+ (0x0 << 6) | (0x0 << 14) | (0x0 << 16));
+
+ clrbits_le32(&ch[0].phy.pll3, (0x1 < 0));
+ setbits_le32(&ch[0].phy.b[0].dq[3], (0x1 << 3));
+ setbits_le32(&ch[0].phy.b[1].dq[3], (0x1 << 3));
+
+ udelay(1);
+ clrsetbits_le32(&ch[0].phy.shu[0].pll[8],
+ (0x7 << 0) | (0x3 << 18),
+ (0x0 << 0) | (0x1 << 18));
+
+ udelay(1);
+ clrbits_le32(&ch[0].phy.shu[0].pll[9],
+ (0x3 << 8) | (0x1 << 12) | (0x3 << 14) | (0x1 << 16));
+ clrbits_le32(&ch[0].phy.shu[0].pll[11],
+ (0x3 << 8) | (0x1 << 12) | (0x3 << 14) | (0x1 << 16));
+ udelay(1);
+
+ clrsetbits_le32(&ch[0].phy.shu[0].pll[10],
+ (0x7 << 0) | (0x3 << 18), (0x0 << 0) | (0x1 << 18));
+ udelay(1);
+
+ /* PLL EN */
+ /* MID FINE_TUNE Init 1 */
+ clrsetbits_le32(&ch[0].phy.pll4,
+ (0x3 << 18) | (0x1 << 21), (0x3 << 18) | (0x0 << 21));
+
+ udelay(1);
+ clrsetbits_le32(&ch[0].phy.shu[0].pll[0],
+ (0xffff << 0), (0x3 << 0));
+
+ udelay(1);
+ setbits_le32(&ch[0].phy.ca_dll_fine_tune[1], (0x1 << 21));
+
+ for (size_t b = 0; b < 2; b++) {
+ setbits_le32(&ch[0].phy.b[b].dq[3],
+ (0x3 << 1) | (0x1 << 10));
+ }
+
+ dramc_broadcast_onoff(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_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ for (size_t b = 0; b < 2; b++)
+ clrsetbits_le32(&ch[0].phy.shu[0].b[b].dll[0],
+ (0x1 << 4) | (0x3 << 9) | (0xf << 12) |
+ (0xf << 16) | (0xf << 20) | (0x1 << 30),
+ (0x0 << 4) | (0x3 << 9) | (0x8 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x1 << 30));
+
+ clrbits_le32(&ch[0].phy.shu[0].ca_cmd[5], (0x3f << 0));
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[0],
+ (0x1 << 4) | (0x7 << 12) | (0x1 << 20),
+ (0x1 << 4) | (0x4 << 12) | (0x1 << 20));
+
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[6],
+ (0xffff << 6), (0x3 << 6));
+ clrsetbits_le32(&ch[1].phy.shu[0].ca_cmd[6],
+ (0xffff << 6), (0x1 << 6));
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ for (size_t b = 0; b < 2; b++)
+ clrsetbits_le32(&ch[0].phy.shu[0].b[b].dq[6],
+ (0xffff << 6), 0x1 << 6);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ clrsetbits_le32(&ch[0].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 << 18));
+ clrsetbits_le32(&ch[1].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) | (0x2 << 18));
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+ udelay(9);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ 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_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ 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);
+
+ udelay(1);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ ddr_phy_reserved_rg_setting();
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ ddr_phy_pll_setting(chn);
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ setbits_le32(&ch[0].ao.drsctrl, (0x1 << 29));
+ /* Set Run time MRR CKE fix to 1 in tMRRI old mode
+ * to avoid no ACK from precharge all */
+ setbits_le32(&ch[0].ao.ckectrl, (0x1 << 27));
+ clrsetbits_le32(&ch[0].ao.dramctrl,
+ (0x1 << 15) | (0x1 << 17) | (0x1 << 23),
+ (0x0 << 15) | (0x1 << 17) | (0x1 << 23));
+ setbits_le32(&ch[0].ao.spcmdctrl,
+ (0x1 << 1) | (0x1 << 8) | (0x1 << 9) | (0x1 << 10));
+ setbits_le32(&ch[0].phy.b[0].dq[9], (0x1 << 4));
+ setbits_le32(&ch[0].phy.b[1].dq[9], (0x1 << 4));
+
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].dqsien,
+ (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24),
+ (0xf << 0) | (0xf << 8) | (0xf << 16) | (0xf << 24));
+ clrsetbits_le32(&ch[0].ao.stbcal1,
+ (0x1 << 4) | (0x1 << 8) | (0x1 << 12),
+ (0x1 << 4) | (0x1 << 8) | (0x0 << 12));
+ clrsetbits_le32(&ch[0].ao.shu[0].dqsg_retry,
+ (0x1 << 3) | (0xf << 8) | (0x1 << 21) | (0x1 << 31),
+ (0x1 << 3) | (0x6 << 8) | (0x1 << 21) | (0x1 << 31));
+
+ for (size_t i = 0; i < 4; i++) {
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[i],
+ (0x1f << 0) | (0x1f << 5) | (0x1f << 10)
+ | (0x1f << 15) | (0x1f << 20) | (0x1f << 25),
+ (0xa << 0) | (0xa << 5) | (0xa << 10)
+ | (0xa << 15) | (0xa << 20) | (0xa << 25));
+ }
+
+ clrsetbits_le32(&ch[0].ao.shuctrl2,
+ (0x3f << 0) | (0x1 << 12) | (0x1 << 14) |
+ (0x1 << 15) | (0xff << 16) | (0x1 << 24),
+ (0xa << 0) | (0x1 << 12) | (0x1 << 14) |
+ (0x1 << 15) | (0x1 << 16) | (0x0 << 24));
+ setbits_le32(&ch[0].ao.dvfsdll, (0x1 << 0));
+ setbits_le32(&ch[0].ao.ddrconf0,
+ (0x1 << 12) | (0x1 << 15) | (0x1 << 20) | (0x1 << 26));
+ setbits_le32(&ch[0].ao.stbcal2,
+ (0x1 << 4) | (0x1 << 28) | (0x1 << 30));
+ setbits_le32(&ch[0].ao.stbcal2, (0x1 << 29));
+ clrbits_le32(&ch[0].ao.stbcal2, (0x1 << 29));
+ setbits_le32(&ch[0].ao.clkar, (0x1 << 19));
+
+ for (size_t b = 0; b < 2; b++)
+ clrsetbits_le32(&ch[0].phy.b[b].dq[9],
+ (0x7 << 20), (0x1 << 20));
+ clrsetbits_le32(&ch[0].phy.ca_cmd[10],
+ (0x7 << 20), (0x0 << 20));
+
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1)
+ clrsetbits_le32(&ch[0].phy.misc_ctrl0,
+ (0xf << 0) | (0x1 << 9) | (0x7 << 18) |
+ (0x1 << 24) | (0x1 << 31),
+ (0xf << 0) | (0x1 << 9) | (0x1 << 18) |
+ (0x1 << 24) | (0x1 << 31));
+ else
+ setbits_le32(&ch[0].phy.misc_ctrl0,
+ (0xf << 0) | (0x1 << 9) | (0x1 << 24) | (0x1 << 31));
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++)
+ setbits_le32(&ch[chn].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));
+
+ clrbits_le32(&ch[0].phy.ca_cmd[7], (0x1 << 4)|(0x1 << 6));
+ clrbits_le32(&ch[0].phy.b[0].dq[7], (0x1 << 6));
+ clrbits_le32(&ch[0].phy.b[1].dq[7], (0x1 << 6));
+
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[0],
+ (0x3f << 0) | (0x1 << 7) | (0xf << 12) | (0x1 << 24) |
+ (0x1 << 29) | (0x3 << 30),
+ (0x3f << 0) | (0x1 << 7) | (0x1 << 12) | (0x1 << 24) |
+ (0x1 << 29) | (0x2 << 30));
+ clrsetbits_le32(&ch[0].ao.shu[0].odtctrl,
+ (0x1 << 0) | (0x1 << 1) | (0x7f << 16) | (0x1 << 30) |
+ (0x1 << 31),
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 16) | (0x1 << 30) |
+ (0x1 << 31));
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 15));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 15));
+
+ clrsetbits_le32(&ch[0].ao.refctrl0, (0xf << 24), (0x5 << 24));
+ clrbits_le32(&ch[0].ao.shu[0].selph_ca1,
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28));
+ clrsetbits_le32(&ch[0].ao.shu[0].selph_ca2,
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 16) |
+ (0x7 << 24),
+ (0x0 << 0) | (0x0 << 4) | (0x0 << 8) | (0x7 << 16) |
+ (0x0 << 24));
+ clrbits_le32(&ch[0].ao.shu[0].selph_ca3,
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28));
+ clrbits_le32(&ch[0].ao.shu[0].selph_ca4,
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28));
+ clrbits_le32(&ch[0].ao.shu[0].selph_ca5, (0x7 << 8));
+ clrsetbits_le32(&ch[0].ao.shu[0].selph_dqs0,
+ (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));
+ clrsetbits_le32(&ch[0].ao.shu[0].selph_dqs1,
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x5 << 0) | (0x5 << 4) | (0x5 << 8) | (0x5 << 12) |
+ (0x2 << 16) | (0x2 << 20) | (0x2 << 24) | (0x2 << 28));
+
+ for (size_t i = 0; i < 2; i++) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[i].selph_dq[0],
+ (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));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[i].selph_dq[1],
+ (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));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[i].selph_dq[2],
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x3 << 0) | (0x3 << 4) | (0x3 << 8) | (0x3 << 12) |
+ (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[i].selph_dq[3],
+ (0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x3 << 0) | (0x3 << 4) | (0x3 << 8) | (0x3 << 12) |
+ (0x1 << 16) | (0x1 << 20) | (0x1 << 24) | (0x1 << 28));
+ }
+
+ for (int b = 0; b < 2; b++) {
+ clrsetbits_le32(&ch[0].phy.shu[0].rk[0].b[b].dq[7],
+ (0x3f << 8) | (0x3f << 16),
+ (0x1a << 8) | (0x1a << 16));
+ clrsetbits_le32(&ch[0].phy.shu[0].rk[1].b[b].dq[7],
+ (0x3f << 8) | (0x3f << 16),
+ (0x14 << 8) | (0x14 << 16));
+ }
+
+ udelay(1);
+
+ for (size_t b = 0; b < 2; b++) {
+ setbits_le32(&ch[0].phy.b[b].dq[9], (0x1 << 5));
+ clrsetbits_le32(&ch[0].phy.b[b].dq[6],
+ (0x3 << 14), (0x1 << 14));
+ }
+ setbits_le32(&ch[0].ao.stbcal, (0x1 << 31));
+ clrsetbits_le32(&ch[0].ao.srefctrl,
+ (0xf << 24) | (0x1 << 30), (0x8 << 24) | (0x0 << 30));
+ clrsetbits_le32(&ch[0].ao.shu[0].ckectrl,
+ (0x3 << 24) | (0x3 << 28),
+ (0x3 << 24) | (0x3 << 28));
+ setbits_le32(&ch[0].ao.shu[0].pipe, (0x1 << 30) | (0x1 << 31));
+ setbits_le32(&ch[0].ao.ckectrl, (0x1 << 13) | (0x1 << 31));
+ setbits_le32(&ch[0].ao.rkcfg, (0x1 << 2));
+
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[2],
+ (0x7 << 16) | (0x1 << 28), (0x7 << 16) | (0x1 << 28));
+ clrsetbits_le32(&ch[0].ao.spcmdctrl,
+ (0x1 << 26), (0x1 << 26));
+ clrsetbits_le32(&ch[0].ao.shuctrl1, (0xff << 0), (0x40 << 0));
+ } else {
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[2],
+ (0x7 << 16) | (0x1 << 28), (0x7 << 16) | (0x1 << 28));
+ clrsetbits_le32(&ch[0].ao.spcmdctrl,
+ (0x1 << 26), (0x1 << 26));
+ clrsetbits_le32(&ch[0].ao.shuctrl1, (0xff << 0), (0x40 << 0));
+ }
+
+ setbits_le32(&ch[0].ao.shuctrl, (0x1 << 16));
+ clrbits_le32(&ch[0].ao.refctrl1,
+ (0x1 << 1) | (0x1 << 2) | (0x1 << 3) | (0x1 << 6));
+
+ clrsetbits_le32(&ch[0].ao.refratre_filter, (0x1 << 15) | (0x1 << 23),
+ (0x1 << 15) | (0x0 << 23));
+
+ clrbits_le32(&ch[0].ao.dramctrl, (0x1 << 9));
+ setbits_le32(&ch[0].ao.misctl0,
+ (0x1 << 19) | (0x1 << 24) | (0x1 << 31));
+ setbits_le32(&ch[0].ao.perfctl0,
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 4) | (0x1 << 8) |
+ (0x1 << 9) | (0x1 << 10) | (0x1 << 11) |
+ (0x1 << 14) | (0x1 << 17));
+ clrsetbits_le32(&ch[0].ao.arbctl, (0xff << 0), (0x80 << 0));
+ clrsetbits_le32(&ch[0].ao.padctrl,
+ (0x3 << 0) | (0x1 << 3), (0x1 << 0) | (0x1 << 3));
+ setbits_le32(&ch[0].ao.dramc_pd_ctrl, (0x1 << 8));
+ setbits_le32(&ch[0].ao.clkctrl, (0x1 << 29));
+ clrsetbits_le32(&ch[0].ao.refctrl0,
+ (0x1 << 0) | (0x7 << 12), (0x1 << 0) | (0x4 << 12));
+
+ clrsetbits_le32(&ch[0].ao.shu[0].rankctl,
+ (0xf << 20) | (0xf << 24) | (0xf << 28),
+ (0x4 << 20) | (0x4 << 24) | (0x6 << 28));
+
+ udelay(2);
+
+ if (get_cbt_mode(params) == CBT_NORMAL_MODE) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[0].dqsien,
+ (0x7f << 0) | (0x7f << 8), (0x19 << 0) | (0x19 << 8));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].dqsien,
+ (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24),
+ (0x1b << 0) | (0x1b << 8) | (0x0 << 16) | (0x0 << 24));
+ }
+
+ setbits_le32(&ch[0].ao.dramctrl, (0x1 << 19));
+ clrsetbits_le32(&ch[0].ao.zqcs, (0xff << 0), (0x56 << 0));
+ udelay(1);
+
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[3],
+ (0x1ff << 16), (0xff << 16));
+ setbits_le32(&ch[0].ao.refctrl0, (0x1 << 30));
+ setbits_le32(&ch[0].ao.srefctrl, (0x1 << 30));
+ setbits_le32(&ch[0].ao.mpc_option, (0x1 << 17));
+ setbits_le32(&ch[0].ao.dramc_pd_ctrl, (0x1 << 30));
+ 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));
+ clrbits_le32(&ch[0].ao.rstmask, (0x1 << 29));
+ clrbits_le32(&ch[0].ao.rstmask, (0x1 << 30));
+
+ udelay(1);
+ clrsetbits_le32(&ch[0].ao.hw_mrr_fun, (0xf << 0) | (0xf << 4),
+ (0x8 << 0) | (0x6 << 4));
+
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ setbits_le32(&ch[0].ao.perfctl0, (0x1 << 27));
+ clrsetbits_le32(&ch[0].ao.perfctl0,
+ (0x1 << 18) | (0x1 << 19), (0x0 << 18) | (0x1 << 19));
+ 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));
+ } else {
+ 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.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));
+ clrsetbits_le32(&ch[0].ao.shu[0].rankctl, (0xf << 20),
+ (0x4 << 20));
+
+ for (size_t r = 0; r < 2; r++) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[r].selph_dq[0],
+ (0x7 << 0) | (0x7 << 4),
+ (0x2 << 0) | (0x2 << 4));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[r].selph_dq[1],
+ (0x7 << 0) | (0x7 << 4),
+ (0x2 << 0) | (0x2 << 4));
+ }
+ }
+ udelay(5);
+
+ clrsetbits_le32(&ch[0].ao.stbcal1, (0xffff << 16), (0x3 << 16));
+ clrsetbits_le32(&ch[0].ao.stbcal1, (0xffff << 16), (0x1 << 16));
+ clrsetbits_le32(&ch[0].ao.stbcal,
+ (0x1 << 0) | (0x1 << 22) | (0x1 << 24) |
+ (0x1 << 26) | (0x1 << 27),
+ (0x1 << 0) | (0x0 << 22) | (0x0 << 24) |
+ (0x1 << 26) | (0x1 << 27));
+ setbits_le32(&ch[0].ao.stbcal1, (0x1 << 6));
+ clrsetbits_le32(&ch[0].ao.shu[0].dqsg,
+ (0x1 << 11) | (0xf << 12), (0x1 << 11) | (0x9 << 12));
+ clrbits_le32(&ch[0].phy.misc_ctrl0, (0xf << 0));
+ setbits_le32(&ch[0].ao.shu[0].stbcal, (0x1 << 8));
+ setbits_le32(&ch[0].ao.stbcal, (0x1 << 17));
+
+ clrbits_le32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 14));
+ clrbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 14));
+ clrsetbits_le32(&ch[0].ao.shu[0].stbcal, (0x7 << 4), (0x1 << 4));
+
+ clrsetbits_le32(&ch[0].ao.shu[0].stbcal, (0x3 << 0), (0x2 << 0));
+
+ setbits_le32(&ch[0].ao.refctrl1, (0x1 << 0) | (0x1 << 5));
+ setbits_le32(&ch[0].ao.dqsoscr, (0x1 << 23) | (0x1 << 27));
+ clrbits_le32(&ch[0].ao.rstmask,
+ (0x1 << 24) | (0x1 << 25) | (0x1 << 26));
+ clrsetbits_le32(&ch[0].ao.rkcfg, (0x7 << 4), (0x1 << 4));
+
+ udelay(12);
+
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rankctl,
+ (0xf << 20) | (0xf << 24) | (0xf << 28),
+ (0x3 << 20) | (0x3 << 24) | (0x5 << 28));
+ } else {
+ clrsetbits_le32(&ch[0].ao.shu[0].rankctl,
+ (0xf << 24) | (0xf << 28),
+ (0x4 << 24) | (0x6 << 28));
+ }
+
+ clrbits_le32(&ch[0].ao.shu[0].wodt, (0x1 << 31));
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[0].dqsien,
+ (0x7f << 0) | (0x7f << 8), (0x19 << 0) | (0x19 << 8));
+ }
+ clrsetbits_le32(&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));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[0].selph_dq[2],
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x4 << 16) | (0x4 << 20) | (0x4 << 24) | (0x4 << 28));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[0].selph_dq[3],
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x4 << 16) | (0x4 << 20) | (0x4 << 24) | (0x4 << 28));
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].dqsien,
+ (0x7f << 0) | (0x7f << 8) | (0x7f << 16) | (0x7f << 24),
+ (0x1b << 0) | (0x1b << 8) | (0x0 << 16) | (0x0 << 24));
+ }
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].fine_tune,
+ (0x3f << 0) | (0x3f << 8) | (0x3f << 16) | (0x3f << 24),
+ (0x14 << 0) | (0x14 << 8) | (0x14 << 16) | (0x14 << 24));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].selph_dq[2],
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x4 << 16) | (0x4 << 20) | (0x4 << 24) | (0x4 << 28));
+ clrsetbits_le32(&ch[0].ao.shu[0].rk[1].selph_dq[3],
+ (0x7 << 16) | (0x7 << 20) | (0x7 << 24) | (0x7 << 28),
+ (0x4 << 16) | (0x4 << 20) | (0x4 << 24) | (0x4 << 28));
+ clrsetbits_le32(&ch[0].ao.shu[0].dqsg_retry,
+ (0x1 << 2) | (0xf << 8) | (0x1 << 14) | (0x3 << 24),
+ (0x1 << 2) | (0x5 << 8) | (0x0 << 14) | (0x1 << 24));
+
+ if (get_cbt_mode(params) == CBT_BYTE_MODE1) {
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[7], (0x1 << 12));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[7], (0x1 << 12));
+ } else {
+ setbits_le32(&ch[0].phy.shu[0].b[0].dq[7],
+ (0x1 << 12) | (0x1 << 13));
+ setbits_le32(&ch[0].phy.shu[0].b[1].dq[7],
+ (0x1 << 12) | (0x1 << 13));
+ }
+
+ clrbits_le32(&ch[0].ao.shu[0].dqs2dq_tx, (0x1f << 0));
+ update_initial_settings();
+
+ clrbits_le32(&ch[0].ao.test2_4, (0x1 << 17));
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[3], (0x1ff << 0), (0x5 << 0));
+ delay(1);
+
+ setbits_le32(&ch[0].ao.refctrl0, (0x1 << 17) | (0x1 << 18));
+ setbits_le32(&ch[0].ao.shuctrl2, (0x1 << 24) | (0x1 << 25));
+ setbits_le32(&ch[0].ao.refctrl0, (0x1 << 29));
+ setbits_le32(&ch[0].ao.dramctrl, (0x1 << 26));
+ clrsetbits_le32(&ch[0].ao.dummy_rd,
+ (0x1 << 4) | (0x1 << 11) | (0x1 << 13) |
+ (0x1 << 14) | (0x3 << 16) | (0x1 << 22),
+ (0x1 << 4) | (0x1 << 11) | (0x1 << 13) |
+ (0x1 << 14) | (0x2 << 16) | (0x1 << 22));
+ clrsetbits_le32(&ch[0].ao.test2_4, (0x7 << 28), (0x4 << 28));
+ clrbits_le32(&ch[0].ao.dramctrl, (0x1 << 0));
+
+ udelay(1);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+
+ clrsetbits_le32(&ch[0].ao.shuctrl,
+ (0x1 << 5)|(0x1 << 17), (0x0 << 5)|(0x1 << 17));
+ setbits_le32(&ch[0].ao.shuctrl2, (0x1 << 12));
+
+ clrsetbits_le32(&ch[1].ao.shuctrl,
+ (0x1 << 5)|(0x1 << 17), (0x1 << 5)|(0x0 << 17));
+ clrbits_le32(&ch[1].ao.shuctrl2, (0x1 << 12));
+
+ s8 clkDelay = params->clk_delay;
+ s8 dqsDelay[CHANNEL_NUM] = {params->dqs_delay[CHANNEL_A],
+ params->dqs_delay[CHANNEL_B]};
+ dramc_dbg("%s param: clkdelay:0x%x,"
+ " dqsDelay[0]:0x%x, dqsDelay[1]:0x%x\n", __func__,
+ clkDelay, dqsDelay[0], dqsDelay[1]);
+
+ dramc_duty_calibration(CHANNEL_A, clkDelay, dqsDelay[CHANNEL_A]);
+ dramc_duty_calibration(CHANNEL_B, clkDelay, dqsDelay[CHANNEL_B]);
+
+ dramc_mode_reg_init();
+}
+
+void dramc_ac_timing_optimize(void)
+{
+ u8 chn;
+ dramc_dbg("[ACTiming Optimize] For MR8[5:2] = 4 sample only\n");
+ dramc_dbg("16Gb per die (8Gb per channel)\n");
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[3],
+ (0xff << 16), (0x64 << 16));
+ clrbits_le32(&ch[chn].ao.shu[0].ac_time_05t, (0x1 << 2));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[4],
+ (0x3ff << 0), (0x77 << 0));
+ }
+}
+
+static void ddr_update_ac_timing(void)
+{
+ u32 temp;
+
+ for (u8 chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[0],
+ (0xf << 24) | (0x7 << 16) | (0x1f << 8) | (0xf << 0),
+ (0x6 << 24) | (0x2 << 16) | (0xc << 8) | (0x7 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[1],
+ (0x1f << 24) | (0xf << 16) | (0xf << 8) | (0x7 << 0),
+ (0x10 << 24) | (0x8 << 16) | (0x5 << 8) | (0x1 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[2],
+ (0x1f << 24) | (0xf << 16) | (0x7 << 8) | (0x7 << 0),
+ (0x7 << 24) | (0x7 << 16) | (0x2 << 8) | (0x1 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[3],
+ (0xff << 16) | (0xff << 24) | (0xff << 0),
+ (0x64 << 16) | (0x61 << 24) | (0x2c << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[4],
+ (0xff << 24) | (0xff << 16) | (0x3ff << 0),
+ (0x22 << 24) | (0x65 << 16) | (0x77 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim[5],
+ (0xf << 24) | (0x1f << 8) | (0x1f << 0),
+ (0xa << 24) | (0xc << 8) | (0xb << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim_xrt,
+ (0xf << 24) | (0x7 << 16) | (0xf << 8) | (0x1f << 0),
+ (0x5 << 24) | (0x3 << 16) | (0x6 << 8) | (0x9 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].ac_time_05t,
+ (0x1 << 25) | (0x0 << 24) | (0x1 << 16) | (0x0 << 15)|
+ (0x1 << 13) | (0x1 << 12) | (0x1 << 10) | (0x1 << 9) |
+ (0x1 << 8) | (0x1 << 7) | (0x1 << 6) | (0x1 << 5) |
+ (0x1 << 4) | (0x1 << 2) | (0x1 << 1) | (0x1 << 0),
+ (0x0 << 25) | (0x0 << 24) | (0x1 << 16) | (0x0 << 15) |
+ (0x0 << 13) | (0x0 << 12) | (0x1 << 10) | (0x1 << 9) |
+ (0x0 << 8) | (0x1 << 7) | (0x1 << 6) | (0x1 << 5) |
+ (0x0 << 4) | (0x0 << 2) | (0x0 << 1) | (0x1 << 0));
+ clrsetbits_le32(&ch[chn].ao.catraining1,
+ (0xff << 24) | (0xf << 20), (0xb << 24) | (0x0 << 20));
+
+ /* DQSINCTL related */
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[0].dqsctl,
+ (0xf << 0), (0x4 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[1].dqsctl,
+ (0xf << 0), (0x4 << 0));
+ clrsetbits_le32(&ch[chn].ao.shu[0].odtctrl,
+ (0xf << 4), (0x4 << 4));
+
+ /* DATLAT related, tREFBW */
+ clrsetbits_le32(&ch[chn].ao.shu[0].conf[1],
+ (0x1f << 0) | (0x1f << 8) |
+ (0x1f << 26) | (0x3ff << 16),
+ (0xf << 0) | (0xd << 8) | (0xd << 26) | (0x0 << 16));
+ clrsetbits_le32(&ch[chn].ao.shu[0].conf[2],
+ (0xff << 8), (0x64 << 8));
+ clrsetbits_le32(&ch[chn].ao.shu[0].scintv,
+ (0x1f << 13) | (0x1f << 6), (0xf << 13) | (0xc << 6));
+
+ /* CKEPRD - CKE pulse width */
+ clrsetbits_le32(&ch[chn].ao.shu[0].ckectrl,
+ (0x7 << 20), (0x2 << 20));
+
+ /* CKELCKCNT: Valid clock requirement after CKE input low */
+ clrsetbits_le32(&ch[chn].ao.ckectrl, (0x7 << 24), (0x0 << 24));
+
+ /* Ininital setting values are the same,
+ * RANKINCTL_RXDLY = RANKINCTL = RANKINCTL_ROOT1
+ * XRTR2R setting will be updated in RxdqsGatingPostProcess */
+ temp = (read32(&ch[chn].ao.shu[0].rankctl) & 0x00f00000) >> 20;
+ clrsetbits_le32(&ch[chn].ao.shu[0].rankctl,
+ (0xf << 0), (temp << 0));
+
+ u8 u1ROOT = 0, u1TXRANKINCTL = 1, u1TXDLY = 2;
+ clrsetbits_le32(&ch[chn].ao.shu[0].rankctl,
+ (0xf << 16) | (0xf << 12) | (0xf << 8),
+ (u1ROOT << 16) | (u1TXRANKINCTL << 12) |
+ (u1TXDLY << 8));
+ }
+}
+
+void dramc_init(const struct sdram_params *params)
+{
+ u8 dram_t = 3;
+ u8 dram_cbt_mode, dram_cbt_mode_r0, dram_cbt_mode_r1;
+
+ dramc_setting(params);
+
+ ddr_update_ac_timing();
+
+ clrsetbits_le32(&ch[0].ao.arbctl, (0x3 << 10), (dram_t << 10));
+
+ dram_cbt_mode = get_cbt_mode(params);
+ dram_cbt_mode_r0 = dram_cbt_mode_r1 = dram_cbt_mode;
+
+ clrsetbits_le32(&ch[0].ao.rstmask, (0x3 << 13), dram_cbt_mode);
+
+ clrsetbits_le32(&ch[0].ao.arbctl, (0x1 << 13),
+ dram_cbt_mode_r0 | dram_cbt_mode_r1);
+}
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
new file mode 100644
index 0000000..f08a659
--- /dev/null
+++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
@@ -0,0 +1,2626 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <soc/dramc_register.h>
+#include <soc/dramc_pi_api.h>
+#include <soc/emi.h>
+#include <delay.h>
+#include <soc/infracfg.h>
+
+#define TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP 64
+#define IMP_LP4X_TERM_VREF_SEL 0x1b
+#define IMP_DRVP_LP4X_UNTERM_VREF_SEL 0x1a
+#define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x16
+#define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x1a
+
+enum {
+ DQ_DIV_SHIFT = 3,
+ DQ_DIV_MASK = BIT(DQ_DIV_SHIFT) - 1,
+ OEN_SHIFT = 16,
+};
+
+enum {
+ RX_VREF_BEGIN = 0,
+ RX_VREF_END = 12,
+ RX_VREF_STEP = 0x1,
+ TX_VREF_BEGIN = 8,
+ TX_VREF_END = 18,
+ TX_VREF_STEP = 1,
+};
+
+enum {
+ FIRST_DQ_DELAY = 0,
+ FIRST_DQS_DELAY = -27,
+ MAX_DQDLY_TAPS = 16,
+ MAX_RX_DQDLY_TAPS = 63,
+ MAX_TX_DQDLY_TAPS = 200,
+ MAX_TX_DQSDLY_TAPS = 63,
+ MAX_RX_DQSDLY_TAPS = 26
+};
+
+enum {
+ RX_WIN = 0,
+ STAGE_SETUP = 0,
+ STAGE_HOLD = 1,
+ STAGE_SETUP_RX_WIN = STAGE_SETUP | RX_WIN << 1,
+ STAGE_HOLD_RX_WIN = STAGE_HOLD | RX_WIN << 1,
+ STAGE_PRE_HOLD_RX_WIN,
+ TX_WIN_MOVE_DQ_ONLY,
+ TX_WIN_MOVE_DQ_DQM,
+};
+
+enum {
+ RX_DQ = 0,
+ RX_DQM,
+ RX_DQS,
+ TX_DQ,
+ TX_DQS,
+ TX_DQM
+};
+
+struct dqs_perbit_dly {
+ u8 vref;
+ s16 first_dqdly_pass;
+ s16 last_dqdly_pass;
+ s16 first_dqsdly_pass;
+ s16 last_dqsdly_pass;
+ s16 best_first_dqdly_pass;
+ s16 best_last_dqdly_pass;
+ s16 best_first_dqsdly_pass;
+ s16 best_last_dqsdly_pass;
+ s16 best_dqdly;
+ s16 best_dqsdly;
+};
+
+struct tx_dly_coarse_fine_tune {
+ u8 fine_tune;
+ u8 coarse_tune_large;
+ u8 coarse_tune_small;
+ u8 coarse_tune_large_oen;
+ u8 coarse_tune_small_oen;
+};
+
+struct per_byte_dly {
+ u16 max_center;
+ u16 min_center;
+ u16 final_dly;
+};
+
+static void auto_refresh_switch(u8 chn, u8 option)
+{
+ if (option == ENABLE) {
+ /* enable autorefresh */
+ clrbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_REFDIS_SHIFT);
+ } else {
+ /* disable autorefresh */
+ setbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_REFDIS_SHIFT);
+
+ /* because HW will actually disable autorefresh
+ * after refresh_queue empty, we need to wait quene empty */
+ udelay(((read32(&ch[chn].nao.misc_statusa) &
+ MISC_STATUSA_REFRESH_QUEUE_CNT_MASK) >>
+ MISC_STATUSA_REFRESH_QUEUE_CNT_SHIFT)*4);
+ }
+}
+
+static void dramc_rank_swap(u8 chn, u8 rank)
+{
+ u8 multi_rank = 1;
+
+ dramc_dbg("[RankSwap] (Multi %d), Rank %d\n", multi_rank, rank);
+
+ clrsetbits_le32(&ch[chn].ao.rkcfg,
+ RKCFG_RKMODE_MASK | 1 << RKCFG_RKSWAP_SHIFT | RKCFG_TXRANK_MASK,
+ (multi_rank << RKCFG_RKMODE_SHIFT) |
+ (rank << RKCFG_RKSWAP_SHIFT) | (rank << RKCFG_TXRANK_SHIFT));
+
+ /* TXRANK should be set before TXRANKFIX */
+ clrsetbits_le32(&ch[chn].ao.rkcfg,
+ 1 << RKCFG_TXRANKFIX_SHIFT, rank << RKCFG_TXRANKFIX_SHIFT);
+}
+
+static void move_dramc_dq_common(uint32_t *reg_0p5t, uint32_t *reg_2t,
+ u8 shift, s8 shift_coarse_tune)
+{
+ s32 tmp_0p5t, tmp_2t;
+ s32 sum = (((read32(reg_2t) >> shift) & DQ_DIV_MASK) << DQ_DIV_SHIFT) +
+ ((read32(reg_0p5t) >> shift) & DQ_DIV_MASK) +
+ shift_coarse_tune;
+
+ if (sum < 0)
+ sum = 0;
+
+ tmp_0p5t = sum & DQ_DIV_MASK;
+ tmp_2t = sum >> DQ_DIV_SHIFT;
+
+ clrsetbits_le32(reg_0p5t, DQ_DIV_MASK << shift, tmp_0p5t << shift);
+ clrsetbits_le32(reg_2t, DQ_DIV_MASK << shift, tmp_2t << shift);
+}
+
+static void move_dramc_tx_dqs(u8 chn, u8 byte_idx, s8 shift_coarse_tune)
+{
+ move_dramc_dq_common(&ch[chn].ao.shu[0].selph_dqs1,
+ &ch[chn].ao.shu[0].selph_dqs0,
+ byte_idx * 4, shift_coarse_tune);
+}
+
+static void move_dramc_tx_dqs_oen(u8 chn, u8 byte_idx,
+ s8 shift_coarse_tune)
+{
+ move_dramc_dq_common(&ch[chn].ao.shu[0].selph_dqs1,
+ &ch[chn].ao.shu[0].selph_dqs0,
+ (byte_idx * 4) + OEN_SHIFT, shift_coarse_tune);
+}
+
+static void move_dramc_tx_dq(u8 chn, u8 rank, u8 byte_idx, s8 shift_coarse_tune)
+{
+ move_dramc_dq_common(&ch[chn].ao.shu[0].rk[rank].selph_dq[3],
+ &ch[chn].ao.shu[0].rk[rank].selph_dq[1],
+ byte_idx * 4, shift_coarse_tune);
+
+ move_dramc_dq_common(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],
+ &ch[chn].ao.shu[0].rk[rank].selph_dq[0],
+ byte_idx * 4, shift_coarse_tune);
+}
+
+static void move_dramc_tx_dq_oen(u8 chn, u8 rank,
+ u8 byte_idx, s8 shift_coarse_tune)
+{
+ move_dramc_dq_common(&ch[chn].ao.shu[0].rk[rank].selph_dq[3],
+ &ch[chn].ao.shu[0].rk[rank].selph_dq[1],
+ (byte_idx * 4) + OEN_SHIFT, shift_coarse_tune);
+
+ move_dramc_dq_common(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],
+ &ch[chn].ao.shu[0].rk[rank].selph_dq[0],
+ (byte_idx * 4) + OEN_SHIFT, shift_coarse_tune);
+}
+
+static void write_leveling_move_dqs_instead_of_clk(u8 chn)
+{
+ for (u8 byte_idx = 0; byte_idx < DQS_NUMBER; byte_idx++) {
+ move_dramc_tx_dqs(chn, byte_idx, -1);
+ move_dramc_tx_dqs_oen(chn, byte_idx, -1);
+
+ for (u8 i = RANK_0; i < RANK_MAX; i++) {
+ move_dramc_tx_dq(chn, i, byte_idx, -1);
+ move_dramc_tx_dq_oen(chn, i, byte_idx, -1);
+ }
+ }
+}
+
+void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value)
+{
+ u32 rank = 0;
+ u32 u4reg_024;
+
+ u4reg_024 = read32(&ch[chn].ao.ckectrl);
+
+ cke_fix_onoff(CKE_FIXON, chn);
+
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSMA_MASK, mr_idx << MRS_MRSMA_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSOP_MASK, value << MRS_MRSOP_SHIFT);
+
+ setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_MRWEN_SHIFT);
+
+ while ((read32(&ch[chn].nao.spcmdresp) & 1) == 0) {
+ dramc_dbg("wait MRW command fired\n");
+ udelay(1);
+ }
+
+ clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_MRWEN_SHIFT);
+ setbits_le32(&ch[chn].ao.ckectrl, u4reg_024);
+
+ rank = (read32(&ch[chn].ao.mrs) & MRS_MRSRK_MASK) >>
+ MRS_MRSRK_SHIFT;
+
+ dramc_dbg("Write Rank%d MR%d =0x%x\n", rank, mr_idx, value);
+}
+
+void dramc_mode_reg_write_by_rank(u8 chn, u8 rank,
+ u8 mr_idx, u8 value)
+{
+ u32 u4RabnkBackup;
+
+ u4RabnkBackup = (read32(&ch[chn].ao.mrs) & MRS_MRSRK_MASK) >> 24;
+
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSRK_MASK, rank << MRS_MRSRK_SHIFT);
+ dramc_mode_reg_write(chn, mr_idx, value);
+
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSRK_MASK, u4RabnkBackup << MRS_MRSRK_SHIFT);
+}
+
+static void dramc_write_leveling(u8 chn, u8 rank,
+ const struct sdram_params *params)
+{
+ s32 wrlevel_dq_delay[DQS_NUMBER];
+ s32 wrlevel_dqs_final_delay[DQS_NUMBER];
+ s32 clock_delay_max = 0;
+
+ dramc_show("chn:%d, rank:%d params write level:0x%x, 0x%x\n",
+ chn, rank, params->wr_level[chn][rank][0],
+ params->wr_level[chn][rank][1]);
+
+ wrlevel_dqs_final_delay[0] = params->wr_level[chn][rank][0];
+ wrlevel_dqs_final_delay[1] = params->wr_level[chn][rank][1];
+
+ dramc_rank_swap(chn, rank);
+
+ if (rank == RANK_0)
+ write_leveling_move_dqs_instead_of_clk(chn);
+
+ dramc_dbg("No need to update CA/CS dly (CLK dly smaller than CA training)\n");
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9],
+ SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CLK_MASK,
+ clock_delay_max << SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CLK_SHIFT);
+
+ dramc_dbg("Final Clk output dly = %d\n", clock_delay_max);
+
+ for (size_t i = 0; i < DQS_NUMBER; i++) {
+ dramc_dbg("DQS%zd dly: %d\n", i, wrlevel_dqs_final_delay[i]);
+ }
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_PBYTE_B0_MASK,
+ wrlevel_dqs_final_delay[0] <<
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_PBYTE_B0_SHIFT);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_PBYTE_B1_MASK,
+ wrlevel_dqs_final_delay[1] <<
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_PBYTE_B1_SHIFT);
+
+ for (u8 i = 0; i < DQS_NUMBER; i++) {
+ wrlevel_dq_delay[i] = wrlevel_dqs_final_delay[i] + 0x10;
+ if (wrlevel_dq_delay[i] >= 0x40) {
+ wrlevel_dq_delay[i] -= 0x40;
+ move_dramc_tx_dq(chn, rank, i, 2);
+ move_dramc_tx_dq_oen(chn, rank, i, 2);
+ }
+ }
+ dramc_show("chn:%d, rank:%d, dq_delay: 0x%x, 0x%x\n",
+ chn, rank, wrlevel_dq_delay[0], wrlevel_dq_delay[1]);
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_MASK |
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_MASK,
+ (wrlevel_dq_delay[0] <<
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_SHIFT) |
+ (wrlevel_dq_delay[0] <<
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_SHIFT));
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_MASK |
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_MASK,
+ (wrlevel_dq_delay[1] <<
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_SHIFT) |
+ (wrlevel_dq_delay[1] <<
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_SHIFT));
+
+ dramc_rank_swap(chn, RANK_0);
+}
+
+static void cmd_bus_training(u8 chn, u8 rank,
+ const struct sdram_params *params)
+{
+ u32 cbt_cs, i_mr12_value;
+
+ cbt_cs = params->cbt_cs[chn][rank];
+ i_mr12_value = params->cbt_mr12[chn][rank];
+
+ dramc_dbg("start chn:%d, rank:%d, "
+ "cbt_cs:0x%x, mr12_value:0x%x\n",
+ chn, rank, cbt_cs, i_mr12_value);
+
+ /* cbt_adjust_cs */
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9],
+ SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CS_MASK,
+ cbt_cs << 0);
+
+ /* cbt_set_vref */
+ dramc_mode_reg_write_by_rank(chn, rank, 12, i_mr12_value);
+}
+
+void dramc_gating_mode(u8 chn, u8 mode)
+{
+ u8 VrefSel = 0, BurstE2 = 0;
+ if (mode == 0) {
+ VrefSel = 0;
+ BurstE2 = 0;
+ } else {
+ VrefSel = 2;
+ BurstE2 = 1;
+ }
+
+ clrsetbits_le32(&ch[chn].ao.stbcal1, (0x1 << 5), (BurstE2 << 5));
+ setbits_le32(&ch[chn].ao.stbcal, (0x1 << 30));
+
+ for (u8 b = 0; b < 2; b++) {
+ clrsetbits_le32(&ch[chn].phy.b[b].dq[6],
+ (0x3 << 14), (VrefSel << 14));
+ setbits_le32(&ch[chn].phy.b[b].dq[9], (0x1 << 5));
+
+ clrbits_le32(&ch[chn].phy.b[b].dq[9], (0x1 << 4) | (0x1 << 0));
+ udelay(1);
+ setbits_le32(&ch[chn].phy.b[b].dq[9], (0x1 << 4) | (0x1 << 0));
+ }
+}
+
+static void rx_dqs_isi_pulse_cg_en(u8 chn)
+{
+ dramc_dbg("CH %d RX DQS ISI pulse CG: enable\n", chn);
+
+ setbits_le32(&ch[chn].phy.b[0].dq[6],
+ 1 << B0_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B0_SHIFT);
+ setbits_le32(&ch[chn].phy.b[1].dq[6],
+ 1 << B1_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B1_SHIFT);
+}
+
+static void rx_dqs_isi_pulse_cg_dis(u8 chn)
+{
+ dramc_dbg("CH %d RX DQS ISI pulse CG: disable\n", chn);
+
+ clrbits_le32(&ch[chn].phy.b[0].dq[6],
+ 1 << B0_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B0_SHIFT);
+ clrbits_le32(&ch[chn].phy.b[1].dq[6],
+ 1 << B1_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B1_SHIFT);
+}
+
+static void dram_phy_reset(u8 chn)
+{
+ setbits_le32(&ch[chn].ao.ddrconf0, 1 << DDRCONF0_RDATRST_SHIFT);
+ setbits_le32(&ch[chn].phy.misc_ctrl1,
+ 1 << MISC_CTRL1_R_DMPHYRST_SHIFT);
+
+ clrbits_le32(&ch[chn].phy.b[0].dq[9],
+ (1 << 4) | (1 << 0));
+ clrbits_le32(&ch[chn].phy.b[1].dq[9],
+ (1 << 4) | (1 << 0));
+
+ udelay(1);
+
+ setbits_le32(&ch[chn].phy.b[1].dq[9],
+ (1 << 4) | (1 << 0));
+ setbits_le32(&ch[chn].phy.b[0].dq[9],
+ (1 << 4) | (1 << 0));
+
+ clrbits_le32(&ch[chn].phy.misc_ctrl1,
+ 1 << MISC_CTRL1_R_DMPHYRST_SHIFT);
+ clrbits_le32(&ch[chn].ao.ddrconf0,
+ 1 << DDRCONF0_RDATRST_SHIFT);
+}
+
+static void find_gating_window(u32 result_r, u32 result_f, u32 *debug_cnt,
+ u8 dly_coarse_large, u8 dly_coarse_0p5t, u8 *pass_begin,
+ u8 *pass_count, u8 *dly_fine_xt, u32 *coarse_tune, u8 *dqs_high)
+{
+ u8 dqs;
+ u32 pass_byte_count = 0, current_pass = 0;
+ u16 debug_cnt_perbyte;
+ u8 pass_count_1[DQS_NUMBER], min_coarse_tune2t_1[DQS_NUMBER],
+ min_coarse_tune0p5t_1[DQS_NUMBER], min_fine_tune_1[DQS_NUMBER];
+
+ u32 coarse_start = 18;
+ u32 coarse_end = coarse_start + 24;
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ if (pass_byte_count & (1 << dqs))
+ continue;
+
+ u8 dqs_result_r = (u8) ((result_r >> (8 * dqs)) & 0xff);
+ u8 dqs_result_f = (u8) ((result_f >> (8 * dqs)) & 0xff);
+ debug_cnt_perbyte = (u16) debug_cnt[dqs];
+
+ current_pass = 0;
+
+ if ((dqs_result_r == 0) && (dqs_result_f == 0) &&
+ (debug_cnt_perbyte == GATING_GOLDEND_DQSCNT))
+ current_pass = 1;
+
+ if (current_pass) {
+ if (pass_begin[dqs] == 0) {
+ pass_begin[dqs] = 1;
+ pass_count_1[dqs] = 0;
+ min_coarse_tune2t_1[dqs] = dly_coarse_large;
+ min_coarse_tune0p5t_1[dqs] = dly_coarse_0p5t;
+ min_fine_tune_1[dqs] = *dly_fine_xt;
+ dramc_dbg("[Byte %d]First pass (%d, %d, %d)\n",
+ dqs, dly_coarse_large,
+ dly_coarse_0p5t, *dly_fine_xt);
+ }
+
+ if (pass_begin[dqs] == 1)
+ pass_count_1[dqs]++;
+
+ if ((pass_begin[dqs] == 1) &&
+ (pass_count_1[dqs] * DQS_GW_FINE_STEP > 32))
+ dqs_high[dqs] = 0;
+
+ if ((pass_count_1[0] * DQS_GW_FINE_STEP > 32) &&
+ (pass_count_1[1] * DQS_GW_FINE_STEP > 32)) {
+ dramc_dbg("All bytes gating window > 1 "
+ "coarse_tune, Early break\n");
+ *dly_fine_xt = 32;
+ *coarse_tune = coarse_end;
+ }
+ }
+ }
+}
+
+static void find_dly_tune(u8 chn, u8 dly_coarse_large, u8 dly_coarse_0p5t,
+ u8 dly_fine_xt, u8 *dqs_cnt1, u8 *dqs_cnt2, u8 *dqs_high,
+ u8 *dly_coarse_large_cnt, u8 *dly_coarse_0p5t_cnt,
+ u8 *dly_fine_tune_cnt, u8 *dqs_transition)
+{
+ for (u8 dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ if (dqs == 0) {
+ dqs_cnt1[0] =
+ (read32(&ch[chn].phy_nao.misc_phy_stben_b0)
+ >> 16) & 1;
+ dqs_cnt2[0] =
+ (read32(&ch[chn].phy_nao.misc_phy_stben_b0)
+ >> 17) & 1;
+ } else {
+ dqs_cnt1[1] =
+ (read32(&ch[chn].phy_nao.misc_phy_stben_b1)
+ >> 16) & 1;
+ dqs_cnt2[1] =
+ (read32(&ch[chn].phy_nao.misc_phy_stben_b1)
+ >> 17) & 1;
+ }
+
+ if ((dqs_cnt1[dqs] == 1) && (dqs_cnt2[dqs] == 1))
+ dqs_high[dqs]++;
+
+ if (dqs_high[dqs] * DQS_GW_FINE_STEP <= 16)
+ continue;
+
+ if ((dqs_cnt1[dqs] == 1) && (dqs_cnt2[dqs] == 1)) {
+ dly_coarse_large_cnt[dqs] = dly_coarse_large;
+ dly_coarse_0p5t_cnt[dqs] = dly_coarse_0p5t;
+ dly_fine_tune_cnt[dqs] = dly_fine_xt;
+ dqs_transition[dqs] = 1;
+ } else if (((dqs_cnt1[dqs] == 1) && (dqs_cnt2[dqs] == 0)) ||
+ ((dqs_cnt1[dqs] == 0) && (dqs_cnt2[dqs] == 1))) {
+ if (dqs_transition[dqs] == 1)
+ dramc_dbg("[Byte %d] cnt1/cnt2 falling Transition"
+ " (%d, %d, %d)\n",
+ dqs, dly_coarse_large_cnt[dqs],
+ dly_coarse_0p5t_cnt[dqs],
+ dly_fine_tune_cnt[dqs]);
+
+ dqs_transition[dqs]++;
+ } else if ((dqs_cnt1[dqs] == 0) && (dqs_cnt2[dqs] == 0)) {
+ dramc_dbg("[Byte %d] cnt1/cnt2 Transition tap number (%d)\n",
+ dqs, dqs_transition[dqs]);
+ dqs_high[dqs] = 0;
+ }
+ }
+}
+
+static void dramc_rx_dqs_gating_cal(u8 chn, u8 rank)
+{
+ u8 pass_begin[DQS_NUMBER], pass_count[DQS_NUMBER];
+ u8 min_coarse_tune2t[DQS_NUMBER], min_coarse_tune0p5t[DQS_NUMBER],
+ min_fine_tune[DQS_NUMBER];
+ u8 best_fine_tune[DQS_NUMBER], best_coarse_tune0p5t[DQS_NUMBER],
+ best_coarse_tune2t[DQS_NUMBER];
+ u8 best_fine_tune_p1[DQS_NUMBER], best_coarse_tune0p5t_p1[DQS_NUMBER],
+ best_coarse_tune2t_p1[DQS_NUMBER];
+
+ u8 best_coarse_large_rodt[DQS_NUMBER],
+ best_coarse_0p5t_rodt[DQS_NUMBER];
+ u8 best_coarse_large_rodt_p1[DQS_NUMBER],
+ best_coarse_0p5t_rodt_p1[DQS_NUMBER];
+ u32 coarse_start = 8, coarse_end = 8;
+ u32 debug_cnt[DQS_NUMBER];
+
+ u8 dqs_cnt1[DQS_NUMBER], dqs_cnt2[DQS_NUMBER],
+ dqs_high[DQS_NUMBER], dqs_transition[DQS_NUMBER];
+ u8 dly_coarse_large_cnt[DQS_NUMBER],
+ dly_coarse_0p5t_cnt[DQS_NUMBER],
+ dly_fine_tune_cnt[DQS_NUMBER];
+ u8 dqs;
+ u8 mr1_value[FSP_MAX] = { 0x56, 0x56 };
+
+ u32 *u4RegBackup[] = {
+ &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],
+ };
+
+ save_restore_multi_reg(SAVE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ rx_dqs_isi_pulse_cg_dis(chn);
+ dramc_mode_reg_write_by_rank(chn, rank, 0x1, mr1_value[1] | 0x80);
+
+ clrbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_PBREFEN_SHIFT);
+
+ dramc_hw_gating_onoff(chn, GATING_OFF);
+
+ setbits_le32(&ch[chn].ao.stbcal1, 1 << STBCAL1_STBENCMPEN_SHIFT);
+ setbits_le32(&ch[chn].ao.stbcal1, 1 << STBCAL1_STBCNT_LATCH_EN_SHIFT);
+ clrbits_le32(&ch[chn].ao.ddrconf0, 1 << DDRCONF0_DM4TO1MODE_SHIFT);
+ setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_DQSGCNTEN_SHIFT);
+
+ udelay(4);
+
+ setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_DQSGCNTRST_SHIFT);
+ udelay(1);
+ clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_DQSGCNTRST_SHIFT);
+
+ clrsetbits_le32(&ch[chn].phy.misc_ctrl1,
+ 1 << MISC_CTRL1_R_DMSTBENCMP_RK_OPT_SHIFT,
+ rank << MISC_CTRL1_R_DMSTBENCMP_RK_OPT_SHIFT);
+ dramc_engine2_init(chn, rank,
+ DEFAULT_TEST2_1_CAL, 0xaa000000 | GATING_PATTERN_NUM,
+ TEST_AUDIO_PATTERN, 0);
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ pass_begin[dqs] = 0;
+ pass_count[dqs] = 0;
+ dqs_cnt1[dqs] = 0;
+ dqs_cnt2[dqs] = 0;
+ dqs_high[dqs] = 0;
+ dqs_transition[dqs] = 0;
+
+ dly_coarse_large_cnt[dqs] = 0;
+ dly_coarse_0p5t_cnt[dqs] = 0;
+ dly_fine_tune_cnt[dqs] = 0;
+ }
+
+ dramc_show("[Gating]\n");
+
+ coarse_start = 18;
+ coarse_end = coarse_start + 24;
+
+ for (u32 coarse_tune = coarse_start; coarse_tune < coarse_end;
+ coarse_tune += DQS_GW_COARSE_STEP) {
+ u32 dly_coarse_large_rodt = 0;
+ u32 dly_coarse_0p5t_rodt = 0;
+ u32 dly_coarse_large_rodt_p1 = 4;
+ u32 dly_coarse_0p5t_rodt_p1 = 4;
+
+ u8 dly_coarse_large = coarse_tune / RX_DQS_CTL_LOOP;
+ u8 dly_coarse_0p5t = coarse_tune % RX_DQS_CTL_LOOP;
+
+ u32 dly_coarse_large_p1 =
+ (coarse_tune + DQS_GW_FREQ_DIV) / RX_DQS_CTL_LOOP;
+ u32 dly_coarse_0p5t_p1 =
+ (coarse_tune + DQS_GW_FREQ_DIV) % RX_DQS_CTL_LOOP;
+
+ u32 value = (dly_coarse_large << 3) + dly_coarse_0p5t;
+
+ if (value >= 11) {
+ value -= 11;
+ dly_coarse_large_rodt = value >> 3;
+ dly_coarse_0p5t_rodt =
+ value - (dly_coarse_large_rodt << 3);
+
+ value = (dly_coarse_large << 3) + dly_coarse_0p5t - 11;
+ dly_coarse_large_rodt_p1 = value >> 3;
+ dly_coarse_0p5t_rodt_p1 =
+ value - (dly_coarse_large_rodt_p1 << 3);
+ }
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0,
+ ((u32) dly_coarse_large <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_SHIFT) |
+ ((u32) dly_coarse_large <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_SHIFT) |
+ (dly_coarse_large_p1 <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_SHIFT) |
+ (dly_coarse_large_p1 <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1_SHIFT));
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg1,
+ ((u32) dly_coarse_0p5t <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_SHIFT) |
+ ((u32) dly_coarse_0p5t <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_SHIFT) |
+ (dly_coarse_0p5t_p1 <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1_SHIFT) |
+ (dly_coarse_0p5t_p1 <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1_SHIFT));
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_odten0,
+ (dly_coarse_large_rodt <<
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_SHIFT) |
+ (dly_coarse_large_rodt <<
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_SHIFT) |
+ (dly_coarse_large_rodt_p1 <<
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1_SHIFT) |
+ (dly_coarse_large_rodt_p1 <<
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1_SHIFT));
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_odten1,
+ (dly_coarse_0p5t_rodt <<
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_SHIFT) |
+ (dly_coarse_0p5t_rodt <<
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_SHIFT) |
+ (dly_coarse_0p5t_rodt_p1 <<
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_P1_SHIFT) |
+ (dly_coarse_0p5t_rodt_p1 <<
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_P1_SHIFT));
+
+ for (u8 dly_fine_xt = DQS_GW_FINE_START;
+ dly_fine_xt < DQS_GW_FINE_END;
+ dly_fine_xt += DQS_GW_FINE_STEP) {
+
+ dramc_gating_mode(chn, 0);
+
+ write32(&ch[chn].ao.shu[0].rk[rank].dqsien,
+ dly_fine_xt | (dly_fine_xt << 8));
+
+ dram_phy_reset(chn);
+
+ setbits_le32(&ch[chn].ao.spcmd,
+ 1 << SPCMD_DQSGCNTRST_SHIFT);
+ udelay(1);
+ clrbits_le32(&ch[chn].ao.spcmd,
+ 1 << SPCMD_DQSGCNTRST_SHIFT);
+
+ dramc_engine2_run(chn,
+ TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);
+
+ u32 result_r =
+ read32(&ch[chn].phy.misc_stberr_rk0_r)
+ & MISC_STBERR_RK_R_STBERR_RK_R_MASK;
+ u32 result_f =
+ read32(&ch[chn].phy.misc_stberr_rk0_f)
+ & MISC_STBERR_RK_F_STBERR_RK_F_MASK;
+ debug_cnt[0] = read32(&ch[chn].nao.dqsgnwcnt[0]);
+ debug_cnt[1] = (debug_cnt[0] >> 16) & 0xffff;
+ debug_cnt[0] &= 0xffff;
+
+ dramc_gating_mode(chn, 1);
+ dramc_engine2_run(chn,
+ TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);
+
+ find_dly_tune(chn, dly_coarse_large, dly_coarse_0p5t,
+ dly_fine_xt, &dqs_cnt1[0], &dqs_cnt2[0],
+ &dqs_high[0], &dly_coarse_large_cnt[0],
+ &dly_coarse_0p5t_cnt[0],
+ &dly_fine_tune_cnt[0], &dqs_transition[0]);
+
+ dramc_show("%d %d %d |",
+ dly_coarse_large, dly_coarse_0p5t,
+ dly_fine_xt);
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++)
+ dramc_show("%X ", debug_cnt[dqs]);
+
+ dramc_show(" |");
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ dramc_show("(%X %X)",
+ (result_f >> (DQS_BIT_NUMBER * dqs)) & 0xff,
+ (result_r >> (DQS_BIT_NUMBER * dqs)) & 0xff);
+ }
+
+ dramc_show(" |");
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++)
+ dramc_show("(%d %d)",
+ dqs_cnt1[dqs], dqs_cnt2[dqs]);
+
+ dramc_show("\n");
+
+
+ find_gating_window(result_r, result_f, &debug_cnt[0],
+ dly_coarse_large, dly_coarse_0p5t,
+ &pass_begin[0], &pass_count[0],
+ &dly_fine_xt, &coarse_tune, &dqs_high[0]);
+ }
+ }
+
+ dramc_engine2_end(chn);
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ pass_count[dqs] = dqs_transition[dqs];
+ min_fine_tune[dqs] = dly_fine_tune_cnt[dqs];
+ min_coarse_tune0p5t[dqs] = dly_coarse_0p5t_cnt[dqs];
+ min_coarse_tune2t[dqs] = dly_coarse_large_cnt[dqs];
+
+ u8 tmp_offset = pass_count[dqs] * DQS_GW_FINE_STEP / 2;
+ u8 tmp_value = min_fine_tune[dqs] + tmp_offset;
+ best_fine_tune[dqs] = tmp_value % RX_DLY_DQSIENSTB_LOOP;
+ best_fine_tune_p1[dqs] = best_fine_tune[dqs];
+
+ tmp_offset = tmp_value / RX_DLY_DQSIENSTB_LOOP;
+ tmp_value = min_coarse_tune0p5t[dqs] + tmp_offset;
+ best_coarse_tune0p5t[dqs] = tmp_value % RX_DQS_CTL_LOOP;
+
+ tmp_offset = tmp_value / RX_DQS_CTL_LOOP;
+ best_coarse_tune2t[dqs] =
+ min_coarse_tune2t[dqs] + tmp_offset;
+
+ tmp_value = best_coarse_tune0p5t[dqs] + DQS_GW_FREQ_DIV;
+ best_coarse_tune0p5t_p1[dqs] = tmp_value % RX_DQS_CTL_LOOP;
+
+ tmp_offset = tmp_value / RX_DQS_CTL_LOOP;
+ best_coarse_tune2t_p1[dqs] =
+ best_coarse_tune2t[dqs] + tmp_offset;
+ }
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++)
+ dramc_show("\nbest DQS%d dly(2T, 0.5T, fine tune)"
+ " = (%d, %d, %d)\n",
+ dqs, best_coarse_tune2t[dqs],
+ best_coarse_tune0p5t[dqs], best_fine_tune[dqs]);
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++)
+ dramc_show("\nbest DQS%d best coarse dly"
+ "(2T, 0.5T, fine tune) = (%d, %d, %d)\n",
+ dqs, best_coarse_tune2t_p1[dqs],
+ best_coarse_tune0p5t_p1[dqs],
+ best_fine_tune[dqs]);
+
+ save_restore_multi_reg(RESTORE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ dramc_mode_reg_write_by_rank(chn, rank, 0x1, mr1_value[1] & 0x7f);
+
+ rx_dqs_isi_pulse_cg_en(chn);
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0,
+ ((u32) best_coarse_tune2t[0] <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_SHIFT) |
+ ((u32) best_coarse_tune2t[1] <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_SHIFT) |
+ ((u32) best_coarse_tune2t_p1[0] <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_SHIFT) |
+ ((u32) best_coarse_tune2t_p1[1] <<
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1_SHIFT));
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg1,
+ ((u32) best_coarse_tune0p5t[0] <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_SHIFT) |
+ ((u32) best_coarse_tune0p5t[1] <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_SHIFT) |
+ ((u32) best_coarse_tune0p5t_p1[0] <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1_SHIFT) |
+ ((u32) best_coarse_tune0p5t_p1[1] <<
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1_SHIFT));
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ u8 tmp_value = (best_coarse_tune2t[dqs] << 3)
+ + best_coarse_tune0p5t[dqs];
+
+ if (tmp_value >= 11) {
+ tmp_value -= 11;
+ best_coarse_large_rodt[dqs] = tmp_value >> 3;
+ best_coarse_0p5t_rodt[dqs] =
+ tmp_value - (best_coarse_large_rodt[dqs] << 3);
+
+ tmp_value = (best_coarse_tune2t_p1[dqs] << 3) +
+ best_coarse_tune0p5t_p1[dqs] - 11;
+ best_coarse_large_rodt_p1[dqs] = tmp_value >> 3;
+ best_coarse_0p5t_rodt_p1[dqs] =
+ tmp_value - (best_coarse_large_rodt_p1[dqs] << 3);
+
+ dramc_dbg("\nbest RODT dly(2T, 0.5T) = (%d, %d)\n",
+ best_coarse_large_rodt[dqs],
+ best_coarse_0p5t_rodt[dqs]);
+ } else {
+
+ best_coarse_large_rodt[dqs] = 0;
+ best_coarse_0p5t_rodt[dqs] = 0;
+
+ best_coarse_large_rodt_p1[dqs] = 4;
+ best_coarse_0p5t_rodt_p1[dqs] = 4;
+
+ dramc_dbg
+ ("[RxdqsGatingCal] Error: best_coarse_tune2t[%d]"
+ " is already 0. RODT cannot be -1 coarse tune\n",
+ dqs);
+ }
+ }
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_odten0,
+ ((u32) best_coarse_large_rodt[0] <<
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_SHIFT) |
+ ((u32) best_coarse_large_rodt[1] <<
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_SHIFT) |
+ ((u32) best_coarse_large_rodt_p1[0] <<
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1_SHIFT) |
+ ((u32) best_coarse_large_rodt_p1[1] <<
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1_SHIFT));
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_odten1,
+ ((u32) best_coarse_0p5t_rodt[0] <<
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_SHIFT) |
+ ((u32) best_coarse_0p5t_rodt[1] <<
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_SHIFT) |
+ ((u32) best_coarse_0p5t_rodt_p1[0] <<
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_P1_SHIFT) |
+ ((u32) best_coarse_0p5t_rodt_p1[1] <<
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_P1_SHIFT));
+
+ write32(&ch[chn].ao.shu[0].rk[rank].dqsien,
+ best_fine_tune[0] | (best_fine_tune[1] << 8));
+
+ dram_phy_reset(chn);
+ dramc_dbg("[dramc_rx_dqs_gating_cal] Done\n\n");
+}
+
+static void dramc_rx_dqs_gating_post_process(u8 chn)
+{
+ u8 dqs, rank_rx_dvs, dbi_r_on = 0;
+ u8 rank, rank_max, rank_cur = 0;
+ s8 change_dqsinctl;
+ u32 read_dqsinctl, read_rodt;
+ u32 rankinctl_root, xrtr2r, reg_tx_dly_dqsgated_min = 0;
+ u8 txdly_cal_min = 0xff, txdly_cal_max = 0, tx_dly_dqs_gated = 0;
+ u32 best_coarse_tune2t[RANK_MAX][DQS_NUMBER];
+ u32 best_coarse_tune2t_p1[RANK_MAX][DQS_NUMBER];
+
+ reg_tx_dly_dqsgated_min = 3;
+ rank_rx_dvs = reg_tx_dly_dqsgated_min - 1;
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[7],
+ SHU1_B0_DQ7_R_DMRANKRXDVS_B0_MASK,
+ rank_rx_dvs << SHU1_B0_DQ7_R_DMRANKRXDVS_B0_SHIFT);
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[7],
+ SHU1_B1_DQ7_R_DMRANKRXDVS_B1_MASK,
+ rank_rx_dvs << SHU1_B1_DQ7_R_DMRANKRXDVS_B1_SHIFT);
+
+ if (((read32(&ch[chn].ao.rstmask)>>
+ RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM_SHIFT) & 1) == 0)
+ rank_max = RANK_MAX;
+ else
+ rank_max = RANK_1;
+
+ for (rank = 0; rank < rank_max; rank++) {
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ best_coarse_tune2t[rank][dqs] =
+ (read32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0) >>
+ (dqs * 8)) &
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_MASK;
+ best_coarse_tune2t_p1[rank][dqs] =
+ ((read32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0)
+ >> (dqs * 8)) &
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_MASK) >>
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_SHIFT;
+ dramc_dbg("\nrank%d best DQS%d dly(2T, (P1)2T) = (%d, %d)\n",
+ (u32) rank, (u32) dqs,
+ (u32) best_coarse_tune2t[rank][dqs],
+ (u32) best_coarse_tune2t_p1[rank][dqs]);
+
+ tx_dly_dqs_gated = best_coarse_tune2t[rank][dqs];
+ if (tx_dly_dqs_gated < txdly_cal_min)
+ txdly_cal_min = tx_dly_dqs_gated;
+
+ tx_dly_dqs_gated = best_coarse_tune2t_p1[rank][dqs];
+ if (tx_dly_dqs_gated > txdly_cal_max)
+ txdly_cal_max = tx_dly_dqs_gated;
+ }
+ }
+
+ change_dqsinctl = reg_tx_dly_dqsgated_min - txdly_cal_min;
+
+ dramc_dbg
+ ("ChangeDQSINCTL %d, tx_dly_dqsgated_min %d, txdly_cal_min %d\n",
+ change_dqsinctl, reg_tx_dly_dqsgated_min, txdly_cal_min);
+
+ if (change_dqsinctl != 0) {
+ txdly_cal_min += change_dqsinctl;
+ txdly_cal_max += change_dqsinctl;
+
+ for (rank = 0; rank < rank_max; rank++) {
+ dramc_dbg("Rank: %d\n", rank);
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ best_coarse_tune2t[rank][dqs] += change_dqsinctl;
+ best_coarse_tune2t_p1[rank][dqs] += change_dqsinctl;
+
+ dramc_dbg("best DQS%d dly(2T) = (%d)\n", dqs,
+ best_coarse_tune2t[rank][dqs]);
+ }
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ dramc_dbg("best DQS%d P1 dly(2T) = (%d)\n",
+ dqs,
+ best_coarse_tune2t_p1[rank][dqs]);
+ }
+ }
+
+ for (rank = 0; rank < rank_max; rank++) {
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0,
+ (best_coarse_tune2t[rank][0] << 0) |
+ (best_coarse_tune2t[rank][1] << 8) |
+ (best_coarse_tune2t_p1[rank][0] << 4) |
+ (best_coarse_tune2t_p1[rank][1] << 12));
+ }
+ }
+
+ read_dqsinctl = read32(&ch[chn].ao.shu[0].rk[rank_cur].dqsctl) &
+ SHURK_DQSCTL_DQSINCTL_MASK;
+ read_dqsinctl -= change_dqsinctl;
+
+ if (dbi_r_on) {
+ read_dqsinctl++;
+ read_rodt =
+ (read32(&ch[chn].ao.shu[0].odtctrl) &
+ SHU_ODTCTRL_RODT_MASK) >> SHU_ODTCTRL_RODT_SHIFT;
+ clrsetbits_le32(&ch[chn].ao.shu[0].odtctrl,
+ SHU_ODTCTRL_RODT_MASK,
+ (read_rodt + 1) << SHU_ODTCTRL_RODT_SHIFT);
+ }
+
+ if (read_dqsinctl >= 3) {
+ rankinctl_root = read_dqsinctl - 3;
+ } else {
+ rankinctl_root = 0;
+ dramc_dbg("DQSINCTL < 3, Risk for supporting 1066/RL8\n");
+ }
+
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[0].dqsctl,
+ SHURK_DQSCTL_DQSINCTL_MASK,
+ read_dqsinctl << SHURK_DQSCTL_DQSINCTL_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.shu[0].rk[1].dqsctl,
+ SHURK_DQSCTL_DQSINCTL_MASK,
+ read_dqsinctl << SHURK_DQSCTL_DQSINCTL_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.shu[0].rankctl,
+ SHU_RANKCTL_RANKINCTL_PHY_MASK,
+ read_dqsinctl << SHU_RANKCTL_RANKINCTL_PHY_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.shu[0].rankctl,
+ SHU_RANKCTL_RANKINCTL_MASK,
+ rankinctl_root << SHU_RANKCTL_RANKINCTL_SHIFT);
+ clrsetbits_le32(&ch[chn].ao.shu[0].rankctl,
+ SHU_RANKCTL_RANKINCTL_ROOT1_MASK,
+ rankinctl_root << SHU_RANKCTL_RANKINCTL_ROOT1_SHIFT);
+
+ xrtr2r = 8 + txdly_cal_max + 1;
+ if (xrtr2r > 12) {
+ xrtr2r = 12;
+ dramc_dbg("XRTR2R > 12, Max value is 12\n");
+ }
+
+ clrsetbits_le32(&ch[chn].ao.shu[0].actim_xrt,
+ SHU_ACTIM_XRT_XRTR2R_MASK,
+ xrtr2r << SHU_ACTIM_XRT_XRTR2R_SHIFT);
+
+ dramc_dbg("TX_dly_DQSgated check: min %d max %d, ChangeDQSINCTL=%d\n",
+ txdly_cal_min, txdly_cal_max, change_dqsinctl);
+ dramc_dbg("DQSINCTL=%d, RANKINCTL=%d, XRTR2R=%d\n",
+ read_dqsinctl, rankinctl_root, xrtr2r);
+}
+
+static void dramc_rd_dqc_init(u8 chn, u8 rank)
+{
+ u8 *lpddr_phy_mapping;
+ u16 temp_value = 0;
+ u8 mr15_golden_value = 0;
+ u8 mr20_golden_value = 0;
+ int i;
+ const u8 LPDDR4_PHY_Mapping_POP[CHANNEL_NUM][16] = {
+ /* CHA */
+ {
+ 1, 0, 2, 4, 3, 7, 5, 6,
+ 9, 8, 12, 11, 10, 15, 13, 14
+ },
+ /* CHB */
+ {
+ 0, 1, 5, 6, 3, 7, 4, 2,
+ 9, 8, 12, 15, 11, 14, 13, 10
+ }
+ };
+
+ clrbits_le32(&ch[chn].phy.shu[0].b[0].dq[7],
+ 0x1 << SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT);
+ clrbits_le32(&ch[chn].phy.shu[0].b[1].dq[7],
+ 0x1 << SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1_SHIFT);
+
+ if(rank == RANK_0)
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSRK_MASK, 0 << MRS_MRSRK_SHIFT);
+ else
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MRSRK_MASK, 1 << MRS_MRSRK_SHIFT);
+ setbits_le32(&ch[chn].ao.mpc_option,
+ (0x1 << MPC_OPTION_MPCRKEN_SHIFT));
+
+ lpddr_phy_mapping = (u8 *)LPDDR4_PHY_Mapping_POP[chn];
+ for (i = 0; i < 16; i++)
+ temp_value |= ((0x5555 >> i) & 0x1) << lpddr_phy_mapping[i];
+
+ mr15_golden_value = (u8) temp_value & 0xff;
+ mr20_golden_value = (u8) (temp_value >> 8) & 0xff;
+
+ clrsetbits_le32(&ch[chn].ao.mr_golden,
+ MR_GOLDEN_MR15_GOLDEN_MASK | MR_GOLDEN_MR20_GOLDEN_MASK,
+ mr15_golden_value << 8 | mr20_golden_value);
+}
+
+static u32 dramc_rd_dqc_run(u8 chn)
+{
+ u16 timeout_cnt = 100;
+ u8 response;
+ u32 result;
+
+ setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_RDDQCEN_SHIFT);
+ setbits_le32(&ch[chn].ao.spcmdctrl, 1 << SPCMDCTRL_RDDQCDIS_SHIFT);
+
+ do {
+ response =
+ read32(&ch[chn].nao.spcmdresp)
+ & (0x1 << SPCMDRESP_RDDQC_RESPONSE_SHIFT);
+ timeout_cnt--;
+ udelay(1);
+ } while ((response == 0) && (timeout_cnt > 0));
+
+ if (timeout_cnt == 0)
+ dramc_dbg("[RxWinRDDQC] Resp fail (time out)\n");
+
+ result = read32(&ch[chn].nao.rdqc_cmp);
+ clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_RDDQCEN_SHIFT);
+ clrbits_le32(&ch[chn].ao.spcmdctrl, 1 << SPCMDCTRL_RDDQCDIS_SHIFT);
+
+ return result;
+}
+
+static void dramc_rd_dqc_end(u8 chn)
+{
+ clrsetbits_le32(&ch[chn].ao.mrs, MRS_MRSRK_MASK, 0 << MRS_MRSRK_SHIFT);
+}
+
+static void dramc_vref_enable(u8 chn)
+{
+ setbits_le32(&ch[chn].phy.b[0].dq[5],
+ 0x1 << B0_DQ5_RG_RX_ARDQ_VREF_EN_B0_SHIFT);
+ setbits_le32(&ch[chn].phy.b[1].dq[5],
+ 0x1 << B1_DQ5_RG_RX_ARDQ_VREF_EN_B1_SHIFT);
+}
+
+static void dramc_set_rx_vref(u8 chn, u8 value)
+{
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[5],
+ SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0_MASK,
+ value << SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0_SHIFT);
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[5],
+ SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1_MASK,
+ value << SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1_SHIFT);
+}
+
+static void dramc_set_tx_vref(u8 chn, u8 rank, u16 value)
+{
+ dramc_mode_reg_write_by_rank(chn, rank, 14, value | 0 << 6);
+}
+
+static void set_rx_dly_factor(u8 chn, u8 rank, u8 type, u32 val)
+{
+ u8 i;
+ u32 value;
+ u32 mask;
+
+ switch (type) {
+ case RX_DQ:
+ value = (val << 24 | val << 16 | val << 8 | val);
+ for (i = 2; i < 6; i++) {
+ write32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[i],
+ value);
+ write32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[i],
+ value);
+ }
+ break;
+
+ case RX_DQM:
+ value = (val << 8 | val);
+ mask = SHU1_B0_DQ6_RK_RX_ARDQM0_F_DLY_B0_MASK |
+ SHU1_B0_DQ6_RK_RX_ARDQM0_R_DLY_B0_MASK;
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[6],
+ mask, value);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[6],
+ mask, value);
+ break;
+
+ case RX_DQS:
+ value = (val << 24 | val << 16);
+ mask = SHU1_B0_DQ6_RK_RX_ARDQS0_F_DLY_B0_MASK |
+ SHU1_B0_DQ6_RK_RX_ARDQS0_R_DLY_B0_MASK;
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[6],
+ mask, value);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[6],
+ mask, value);
+
+ }
+}
+
+static void dramc_transfer_dly_tune(u8 chn, u32 dly,
+ struct tx_dly_coarse_fine_tune *dly_tune)
+{
+ u16 tmp_val;
+
+ dly_tune->fine_tune = dly & (TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP - 1);
+
+ tmp_val = (dly / TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP) << 1;
+ dly_tune->coarse_tune_small = tmp_val - ((tmp_val >> 3) << 3);
+ dly_tune->coarse_tune_large = tmp_val >> 3;
+
+ tmp_val -= 4;
+ dly_tune->coarse_tune_small_oen = tmp_val - ((tmp_val >> 3) << 3);
+ dly_tune->coarse_tune_large_oen = tmp_val >> 3;
+}
+
+static void set_tx_dly_factor(u32 chn, u8 rank, u8 type, u32 curr_val)
+{
+ u8 i;
+ struct tx_dly_coarse_fine_tune dly_tune = { };
+ u32 coarse_tune_large = 0;
+ u32 coarse_tune_large_oen = 0;
+ u32 coarse_tune_small = 0;
+ u32 coarse_tune_small_oen = 0;
+
+ dramc_transfer_dly_tune(chn, curr_val, &dly_tune);
+
+ for (i = 0; i < 4; i++) {
+ coarse_tune_large += dly_tune.coarse_tune_large << (i * 4);
+ coarse_tune_large_oen +=
+ dly_tune.coarse_tune_large_oen << (i * 4);
+ coarse_tune_small += dly_tune.coarse_tune_small << (i * 4);
+ coarse_tune_small_oen +=
+ dly_tune.coarse_tune_small_oen << (i * 4);
+ }
+ if (type == TX_DQM)
+ dramc_dbg("%3d |%d %d %2d | [0]", curr_val,
+ dly_tune.coarse_tune_large,
+ dly_tune.coarse_tune_small, dly_tune.fine_tune);
+
+ switch (type) {
+ case TX_DQM:
+ /* large coarse_tune setting */
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[0],
+ (coarse_tune_large_oen << 16) | coarse_tune_large);
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],
+ (coarse_tune_small_oen << 16) | coarse_tune_small);
+
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[1],
+ (coarse_tune_large_oen << 16) | coarse_tune_large);
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[3],
+ (coarse_tune_small_oen << 16) | coarse_tune_small);
+
+ /* fine_tune delay setting */
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_MASK,
+ dly_tune.fine_tune << 8);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_MASK,
+ dly_tune.fine_tune << 8);
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_MASK,
+ dly_tune.fine_tune << 16);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_MASK,
+ dly_tune.fine_tune << 16);
+ break;
+
+ case TX_DQ:
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[0],
+ (coarse_tune_large_oen << 16) | coarse_tune_large);
+ write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],
+ (coarse_tune_small_oen << 16) | coarse_tune_small);
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_MASK,
+ dly_tune.fine_tune << 8);
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_MASK,
+ dly_tune.fine_tune << 8);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void set_dly_factor(u8 chn, u8 rank, u8 type, u32 dly)
+{
+ switch (type) {
+ case TX_WIN_MOVE_DQ_ONLY:
+ set_tx_dly_factor(chn, rank, TX_DQ, dly);
+ break;
+
+ case TX_WIN_MOVE_DQ_DQM:
+ set_tx_dly_factor(chn, rank, TX_DQM, dly);
+ break;
+
+ default:
+ dramc_dbg("%s Invalid type\n", __func__);
+ break;
+ }
+}
+
+static void dramc_engine2_setpat(u8 chn, u8 testaudpat,
+ u8 log2loopcount, u8 Use_Len1_Flag)
+{
+ if (testaudpat == TEST_XTALK_PATTERN) {
+ if (Use_Len1_Flag != 0)
+ setbits_le32(&ch[chn].ao.test2_4,
+ 0x1 << TEST2_4_TEST_REQ_LEN1_SHIFT);
+ else
+ clrbits_le32(&ch[chn].ao.test2_4,
+ 0x1 << TEST2_4_TEST_REQ_LEN1_SHIFT);
+ setbits_le32(&ch[chn].ao.perfctl0, 1 << PERFCTL0_RWOFOEN_SHIFT);
+
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ 0x1 << TEST2_3_TESTAUDPAT_SHIFT | TEST2_3_TESTCNT_MASK,
+ log2loopcount << 0);
+
+ clrsetbits_le32(&ch[chn].ao.test2_4,
+ 0x1 << TEST2_4_TESTXTALKPAT_SHIFT |
+ 0x1 << TEST2_4_TESTAUDMODE_SHIFT |
+ 0x1 << TEST2_4_TESTAUDBITINV_SHIFT,
+ 0x1 << TEST2_4_TESTXTALKPAT_SHIFT);
+
+ clrbits_le32(&ch[chn].ao.test2_4,
+ 1 << TEST2_4_TESTSSOPAT_SHIFT |
+ 0x1 << TEST2_4_TESTSSOXTALKPAT_SHIFT);
+ } else if (testaudpat == TEST_AUDIO_PATTERN) {
+ clrsetbits_le32(&ch[chn].ao.test2_4,
+ TEST2_4_TESTAUDINIT_MASK |
+ TEST2_4_TESTAUDINC_MASK |
+ (0x1 << TEST2_4_TESTXTALKPAT_SHIFT) |
+ (0x1 << TEST2_4_TESTAUDMODE_SHIFT) |
+ (0x1 << TEST2_4_TESTAUDBITINV_SHIFT),
+ (0x11 << 8) | (0xd << 0) | (0x1 << 14));
+
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ 0x1 << TEST2_3_TESTAUDPAT_SHIFT | TEST2_3_TESTCNT_MASK,
+ 0x1 << TEST2_3_TESTAUDPAT_SHIFT | log2loopcount << 0);
+ } else {
+ clrsetbits_le32(&ch[chn].ao.test2_3,
+ 0x1 << TEST2_3_TESTAUDPAT_SHIFT | TEST2_3_TESTCNT_MASK,
+ log2loopcount << 0);
+ clrbits_le32(&ch[chn].ao.test2_4,
+ 0x1 << TEST2_4_TESTXTALKPAT_SHIFT);
+ }
+}
+
+static u32 dram_k_perbit(u8 chn, u8 engine_type)
+{
+ u32 err_value = 0x0;
+
+ if (engine_type) {
+ dramc_engine2_setpat(chn, TEST_AUDIO_PATTERN, 0, 0);
+ err_value = dramc_engine2_run(chn,
+ TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+ dramc_engine2_setpat(chn, TEST_XTALK_PATTERN, 0, 0);
+ err_value |= dramc_engine2_run(chn,
+ TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
+ } else
+ err_value = dramc_rd_dqc_run(chn);
+ return err_value;
+}
+
+static void dramc_check_dq_win(struct dqs_perbit_dly *p,
+ s16 dly_step, s16 last_step, u32 fail_bit)
+{
+ s16 dqdly_pass_win, best_pass_win;
+
+ if (fail_bit == 0) {
+ if (p->first_dqdly_pass == -1) {
+ /* first DQ pass delay tap */
+ p->first_dqdly_pass = dly_step;
+ }
+
+ if ((p->last_dqdly_pass == -2) && (dly_step == last_step)) {
+ /* pass to the last tap */
+ p->last_dqdly_pass = dly_step;
+ dqdly_pass_win =
+ p->last_dqdly_pass - p->first_dqdly_pass;
+ best_pass_win =
+ p->best_last_dqdly_pass
+ - p->best_first_dqdly_pass;
+ if (dqdly_pass_win > best_pass_win) {
+ p->best_last_dqdly_pass = p->last_dqdly_pass;
+ p->best_first_dqdly_pass = p->first_dqdly_pass;
+ }
+ /* clear to find the next pass range if it has */
+ p->first_dqdly_pass = -1;
+ p->last_dqdly_pass = -2;
+ }
+ } else {
+ if ((p->first_dqdly_pass != -1)
+ && (p->last_dqdly_pass == -2)) {
+ p->last_dqdly_pass = dly_step - 1;
+ dqdly_pass_win =
+ p->last_dqdly_pass - p->first_dqdly_pass;
+ best_pass_win =
+ p->best_last_dqdly_pass
+ - p->best_first_dqdly_pass;
+ if (dqdly_pass_win > best_pass_win) {
+ p->best_last_dqdly_pass = p->last_dqdly_pass;
+ p->best_first_dqdly_pass = p->first_dqdly_pass;
+ }
+ /* clear to find the next pass range if it has */
+ p->first_dqdly_pass = -1;
+ p->last_dqdly_pass = -2;
+ }
+ }
+}
+
+static int dramk_calcu_best_vref(u8 cal_type,
+ struct dqs_perbit_dly vref_dly[], struct dqs_perbit_dly delay[],
+ u32 min_win_size, u32 max_win_sum)
+{
+ u8 bit;
+ u32 win_size;
+ u32 win_size_sum = 0;
+ static u32 min_win_size_vref;
+
+ if (cal_type == (RX_WIN | (1 << 1))) {
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ win_size_sum +=
+ (delay[bit].best_last_dqdly_pass -
+ delay[bit].best_first_dqdly_pass + 1);
+ win_size_sum +=
+ (delay[bit].best_last_dqsdly_pass -
+ delay[bit].best_first_dqsdly_pass + 1);
+ }
+ if (win_size_sum > max_win_sum) {
+ max_win_sum = win_size_sum;
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ vref_dly[bit].vref = delay[bit].vref;
+ vref_dly[bit].best_dqdly =
+ delay[bit].best_dqdly;
+ vref_dly[bit].best_first_dqdly_pass =
+ delay[bit].best_first_dqdly_pass;
+ vref_dly[bit].best_last_dqdly_pass =
+ delay[bit].best_last_dqdly_pass;
+ vref_dly[bit].best_first_dqsdly_pass =
+ delay[bit].best_first_dqsdly_pass;
+ vref_dly[bit].best_last_dqsdly_pass =
+ delay[bit].best_last_dqsdly_pass;
+ }
+ }
+ if (win_size_sum < (max_win_sum * 95 / 100))
+ return 1;
+ } else if (cal_type == TX_DQ_DQS_MOVE_DQ_ONLY) {
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ win_size =
+ (delay[bit].best_last_dqdly_pass -
+ delay[bit].best_first_dqdly_pass + 1);
+ if (win_size < min_win_size)
+ min_win_size = win_size;
+ win_size_sum += win_size;
+ }
+
+ if ((win_size_sum > max_win_sum)
+ && (min_win_size >= min_win_size_vref)) {
+ max_win_sum = win_size_sum;
+ min_win_size_vref = min_win_size;
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ vref_dly[bit].vref = delay[bit].vref;
+ vref_dly[bit].best_dqdly =
+ delay[bit].best_dqdly;
+ vref_dly[bit].best_first_dqdly_pass =
+ delay[bit].best_first_dqdly_pass;
+ vref_dly[bit].best_last_dqdly_pass =
+ delay[bit].best_last_dqdly_pass;
+ }
+ }
+
+ } else {
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ vref_dly[bit].vref = delay[bit].vref;
+ vref_dly[bit].best_dqdly = delay[bit].best_dqdly;
+ vref_dly[bit].best_first_dqdly_pass =
+ delay[bit].best_first_dqdly_pass;
+ vref_dly[bit].best_last_dqdly_pass =
+ delay[bit].best_last_dqdly_pass;
+ vref_dly[bit].best_first_dqsdly_pass =
+ delay[bit].best_first_dqsdly_pass;
+ vref_dly[bit].best_last_dqsdly_pass =
+ delay[bit].best_last_dqsdly_pass;
+ }
+ }
+ return 0;
+}
+
+static u8 dramc_calcu_best_dly(u8 bit,
+ struct dqs_perbit_dly *p, u32 *p_max_byte)
+{
+ u8 fail = 0;
+ u8 hold, setup;
+
+ hold = p->best_last_dqsdly_pass - p->best_first_dqsdly_pass + 1;
+ setup = p->best_last_dqdly_pass - p->best_first_dqdly_pass + 1;
+
+ if (hold > setup) {
+ p->best_dqdly = 0;
+ p->best_dqsdly = (setup != 0) ? (hold - setup) / 2 :
+ (hold - setup) / 2 + p->best_first_dqsdly_pass;
+
+ if (p->best_dqsdly > *p_max_byte)
+ *p_max_byte = p->best_dqsdly;
+
+ } else if (hold < setup) {
+ p->best_dqsdly = 0;
+ p->best_dqdly = (hold != 0) ? (setup - hold) / 2 :
+ (setup - hold) / 2 + p->best_first_dqdly_pass;
+
+ } else { /* hold time == setup time */
+ p->best_dqsdly = 0;
+ p->best_dqdly = 0;
+
+ if (hold == 0) {
+ dramc_dbg("ERROR, error bit %d, "
+ "setup_time = hold_time = 0\n", bit);
+ fail = 1;
+ }
+ }
+
+ dramc_dbg("bit#%d : dq =%d dqs=%d win=%d (%d, %d)\n",
+ bit, setup, hold, setup + hold,
+ p->best_dqdly, p->best_dqsdly);
+
+ return fail;
+}
+
+static void dramc_calcu_tx_perbyte_dly(u8 bit,
+ struct dqs_perbit_dly *p, struct per_byte_dly *byte_delay_prop)
+{
+ s16 win_center;
+ win_center = (p->best_first_dqdly_pass + p->best_last_dqdly_pass) >> 1;
+
+ if (win_center < byte_delay_prop->min_center)
+ byte_delay_prop->min_center = win_center;
+ if (win_center > byte_delay_prop->max_center)
+ byte_delay_prop->max_center = win_center;
+}
+
+static void set_tx_best_dly_factor(u8 chn, u8 rank,
+ struct per_byte_dly *tx_perbyte_dly,
+ u16 dq_precal_result[])
+{
+ u8 i, rank_idx;
+ u32 coarse_tune_large = 0;
+ u32 coarse_tune_large_oen = 0;
+ u32 coarse_tune_small = 0;
+ u32 coarse_tune_small_oen = 0;
+ u16 dq_oen[DQS_NUMBER] = { }, dqm_oen[DQS_NUMBER] = { };
+ struct tx_dly_coarse_fine_tune perbyte_dqdly_tune[DQS_NUMBER] = { };
+ struct tx_dly_coarse_fine_tune perbyte_dqmdly_tune[DQS_NUMBER] = { };
+
+ for (i = 0; i < DQS_NUMBER; i++) {
+ dramc_transfer_dly_tune(chn, tx_perbyte_dly[i].final_dly,
+ &perbyte_dqdly_tune[i]);
+ dramc_transfer_dly_tune(chn, dq_precal_result[i],
+ &perbyte_dqmdly_tune[i]);
+
+ coarse_tune_large +=
+ perbyte_dqdly_tune[i].coarse_tune_large << (i * 4);
+ coarse_tune_large_oen +=
+ perbyte_dqdly_tune[i].coarse_tune_large_oen << (i * 4);
+ coarse_tune_small +=
+ perbyte_dqdly_tune[i].coarse_tune_small << (i * 4);
+ coarse_tune_small_oen +=
+ perbyte_dqdly_tune[i].coarse_tune_small_oen << (i * 4);
+ dq_oen[i] =
+ (perbyte_dqdly_tune[i].coarse_tune_large_oen << 3) +
+ (perbyte_dqdly_tune[i].coarse_tune_small_oen << 5) +
+ perbyte_dqdly_tune[i].fine_tune;
+ dqm_oen[i] =
+ (perbyte_dqmdly_tune[i].coarse_tune_large_oen << 3) +
+ (perbyte_dqmdly_tune[i].coarse_tune_small_oen << 5) +
+ perbyte_dqmdly_tune[i].fine_tune;
+ }
+
+ for (rank_idx = rank; rank_idx < RANK_MAX; rank_idx++) {
+ write32(&ch[chn].ao.shu[0].rk[rank_idx].selph_dq[0],
+ (coarse_tune_large_oen << 16) |
+ coarse_tune_large);
+ write32(&ch[chn].ao.shu[0].rk[rank_idx].selph_dq[2],
+ (coarse_tune_small_oen << 16) |
+ coarse_tune_small);
+
+ write32(&ch[chn].ao.shu[0].rk[rank_idx].selph_dq[1],
+ (coarse_tune_large_oen << 16) |
+ coarse_tune_large);
+ write32(&ch[chn].ao.shu[0].rk[rank_idx].selph_dq[3],
+ (coarse_tune_small_oen << 16) |
+ coarse_tune_small);
+ }
+
+ for (rank_idx = rank; rank_idx < RANK_MAX; rank_idx++) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank_idx].b[0].dq[7],
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_MASK |
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_MASK,
+ perbyte_dqdly_tune[0].fine_tune <<
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_SHIFT |
+ perbyte_dqmdly_tune[0].fine_tune <<
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_SHIFT);
+
+ clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank_idx].b[1].dq[7],
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_MASK |
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_MASK,
+ perbyte_dqdly_tune[1].fine_tune <<
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_SHIFT |
+ perbyte_dqmdly_tune[1].fine_tune <<
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_SHIFT);
+ }
+}
+
+static void set_rx_best_dly_factor(u8 chn, u8 rank,
+ struct dqs_perbit_dly *dqdqs_perbit_dly,
+ u32 *max_dqsdly_byte, u32 *ave_dqm_dly)
+{
+ u32 i, value = 0;
+ u8 index, byte;
+
+ for (i = 0; i < DQS_NUMBER; i++) {
+ value = (max_dqsdly_byte[i] << 24) |
+ (max_dqsdly_byte[i] << 16) |
+ (ave_dqm_dly[i] << 8) | (ave_dqm_dly[i] << 0);
+
+ /* Delay dqs/dqm */
+ write32(&ch[chn].phy.shu[0].rk[rank].b[i].dq[6], value);
+ }
+ dram_phy_reset(chn);
+
+ value = 0;
+ for (i = 0; i < DQ_DATA_WIDTH; i += 2) {
+ byte = i / DQS_BIT_NUMBER;
+ index = 2 + ((i % 8) * 2) / 4;
+ value =
+ dqdqs_perbit_dly[i + 1].best_dqdly << 24 |
+ dqdqs_perbit_dly[i + 1].best_dqdly << 16 |
+ dqdqs_perbit_dly[i].best_dqdly << 8 |
+ dqdqs_perbit_dly[i].best_dqdly;
+ write32(&ch[chn].phy.shu[0].rk[rank].b[byte].dq[index],
+ value);
+ }
+
+}
+
+static void dramc_get_vref_range(u8 cal_type, u8 enable,
+ u8 *begin, u8 *end, u8 *step)
+{
+ if (enable) {
+ if (cal_type == RX_WIN) {
+ *begin = RX_VREF_BEGIN;
+ *end = RX_VREF_END;
+ *step = RX_VREF_STEP;
+ } else if (cal_type == TX_WIN_MOVE_DQ_ONLY) {
+ *begin = TX_VREF_BEGIN;
+ *end = TX_VREF_END;
+ *step = TX_VREF_STEP;
+ }
+ } else {
+ *begin = 0;
+ *end = 1;
+ *step = 1;
+ }
+}
+
+static u32 dramc_get_smallest_dqs_dly(u8 chn, u8 rank)
+{
+ u32 dq_coarse_dly = 0;
+ u32 dq_fine_dly = 0;
+ u32 tmp_dly = 0;
+ u32 smallest_dqs_dly = 0xffff;
+ int i = 0;
+ const struct sdram_params *params = get_sdram_config();
+
+ for (i = 0; i < DQS_NUMBER; i++) {
+ dq_coarse_dly =
+ (read32(&ch[chn].ao.shu[0].selph_dqs0) >> (i << 2)) & 0x7;
+ dq_fine_dly =
+ (read32(&ch[chn].ao.shu[0].selph_dqs1) >> (i << 2)) & 0x7;
+
+ tmp_dly =
+ (((dq_coarse_dly << 3) + dq_fine_dly) << 5) + params->wr_level[chn][rank][i];
+ if (tmp_dly < smallest_dqs_dly)
+ smallest_dqs_dly = tmp_dly;
+ }
+
+ return smallest_dqs_dly;
+}
+static void dramc_get_dly_range(u8 chn, u8 rank, u8 cal_type, u16 *pre_cal,
+ s16 *begin, s16 *end)
+{
+ u16 pre_dq_dly;
+
+ if (cal_type == TX_WIN_MOVE_DQ_DQM) {
+ *begin = dramc_get_smallest_dqs_dly(chn, rank);
+ *end = *begin + 256;
+ } else if (cal_type == TX_WIN_MOVE_DQ_ONLY) {
+ pre_dq_dly =
+ (pre_cal[0] > pre_cal[1]) ? pre_cal[1] : pre_cal[0];
+ if (pre_dq_dly > 24)
+ pre_dq_dly -= 24;
+ else
+ pre_dq_dly = 0;
+
+ *begin = pre_dq_dly;
+ *end = *begin + 64;
+ }
+}
+
+static void dramc_check_dqs_win(struct dqs_perbit_dly *p,
+ u8 dly_step, u8 last_step, u32 fail_bit)
+{
+ s8 dqsdly_pass_win, best_pass_win;
+
+ if (fail_bit == 0) {
+ if (p->first_dqsdly_pass == -1) {
+ /* first DQS pass delay tap */
+ p->first_dqsdly_pass = dly_step;
+ }
+ if ((p->last_dqsdly_pass == -2) && (dly_step == last_step)) {
+ /* pass to the last tap */
+ p->last_dqsdly_pass = dly_step;
+ dqsdly_pass_win = p->last_dqsdly_pass
+ - p->first_dqsdly_pass;
+ best_pass_win = p->best_last_dqsdly_pass
+ - p->best_first_dqsdly_pass;
+ if (dqsdly_pass_win > best_pass_win) {
+ p->best_last_dqsdly_pass =
+ p->last_dqsdly_pass;
+ p->best_first_dqsdly_pass =
+ p->first_dqsdly_pass;
+ }
+ /* clear to find the next pass range if it has */
+ p->first_dqsdly_pass = -1;
+ p->last_dqsdly_pass = -2;
+ }
+ } else {
+ if ((p->first_dqsdly_pass != -1)
+ && (p->last_dqsdly_pass == -2)) {
+ p->last_dqsdly_pass = dly_step - 1;
+ dqsdly_pass_win = p->last_dqsdly_pass
+ - p->first_dqsdly_pass;
+ best_pass_win = p->best_last_dqsdly_pass
+ - p->best_first_dqsdly_pass;
+ if (dqsdly_pass_win > best_pass_win) {
+ p->best_last_dqsdly_pass
+ = p->last_dqsdly_pass;
+ p->best_first_dqsdly_pass
+ = p->first_dqsdly_pass;
+ }
+ /* clear to find the next pass range if it has */
+ p->first_dqsdly_pass = -1;
+ p->last_dqsdly_pass = -2;
+ }
+ }
+}
+
+static void dramc_set_dqdqs_dly(u8 chn, u8 rank, s32 dly)
+{
+ if (dly <= 0) {
+ /* Hold time calibration */
+ set_rx_dly_factor(chn, rank, RX_DQS, -dly);
+ dram_phy_reset(chn);
+ } else {
+ /* Setup time calibration */
+ set_rx_dly_factor(chn, rank, RX_DQS, 0);
+ set_rx_dly_factor(chn, rank, RX_DQM, dly);
+ dram_phy_reset(chn);
+ set_rx_dly_factor(chn, rank, RX_DQ, dly);
+ }
+}
+
+static u8 dramc_rx_window_perbit_cal(u8 chn, u8 cal_type,
+ u8 rank, u8 engine_type)
+{
+ u8 vref;
+ u8 vref_begin = 0, vref_end = 1, vref_step = 1;
+ u8 vref_scan_enable;
+ s8 fail = 0;
+ u8 i, bit, max_dq_taps;
+ u8 index, max_limit;
+ s16 dly;
+ u8 dly_step = 1;
+ u8 type = cal_type;
+ u32 err_value, fail_bit;
+ u32 min_win_size = 0xffff;
+ u32 max_win_size_sum = 0;
+ static u32 max_dqsdly_byte[DQS_NUMBER], ave_dqmdly_byte[DQS_NUMBER];
+ static struct dqs_perbit_dly vref_dq_perbit_dly[DQ_DATA_WIDTH];
+ struct dqs_perbit_dly dqdqs_perbit_dly[DQ_DATA_WIDTH];
+
+ if (engine_type && (rank == RANK_0)) {
+ vref_scan_enable = 1;
+ dramc_vref_enable(chn);
+ } else {
+ vref_scan_enable = 0;
+ }
+
+ dramc_dbg("%s [Rank %d] [Channel %d] Calibration Type:%d, engine:%d,vref_enable:%d\n",
+ __func__, rank, chn, type, engine_type, vref_scan_enable);
+
+ if (engine_type)
+ dramc_engine2_init(chn, rank, DEFAULT_TEST2_1_CAL,
+ DEFAULT_TEST2_2_CAL, TEST_XTALK_PATTERN, 0);
+ else
+ dramc_rd_dqc_init(chn, rank);
+
+ dramc_get_vref_range(type, vref_scan_enable,
+ &vref_begin, &vref_end, &vref_step);
+
+ /* if calibration data is allready stored in emmc,
+ * Vref end need change */
+ for (vref = vref_begin; vref < vref_end; vref += vref_step) {
+ if (vref_scan_enable)
+ dramc_set_rx_vref(chn, vref);
+
+ for (i = 0; i < DQ_DATA_WIDTH; i++) {
+ dqdqs_perbit_dly[i].vref = vref;
+ dqdqs_perbit_dly[i].first_dqdly_pass = -1;
+ dqdqs_perbit_dly[i].last_dqdly_pass = -2;
+ dqdqs_perbit_dly[i].first_dqsdly_pass = -1;
+ dqdqs_perbit_dly[i].last_dqsdly_pass = -2;
+ dqdqs_perbit_dly[i].best_first_dqdly_pass = -1;
+ dqdqs_perbit_dly[i].best_last_dqdly_pass = -2;
+ dqdqs_perbit_dly[i].best_first_dqsdly_pass = -1;
+ dqdqs_perbit_dly[i].best_last_dqsdly_pass = -2;
+ }
+
+ set_rx_dly_factor(chn, rank, RX_DQM, FIRST_DQ_DELAY);
+ set_rx_dly_factor(chn, rank, RX_DQ, FIRST_DQ_DELAY);
+
+ max_dq_taps = MAX_RX_DQDLY_TAPS;
+ for (dly = FIRST_DQS_DELAY; dly < max_dq_taps;
+ dly += dly_step) {
+ dramc_set_dqdqs_dly(chn, rank, dly);
+ err_value = dram_k_perbit(chn, engine_type);
+ if (!vref_scan_enable)
+ dramc_dbg("delay %d ", dly);
+
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ fail_bit = err_value & ((u32) 1 << bit);
+ if (dly < 0) {
+ dramc_check_dqs_win(
+ &(dqdqs_perbit_dly[bit]),
+ -dly, -FIRST_DQS_DELAY,
+ fail_bit);
+ } else
+ dramc_check_dq_win(
+ &(dqdqs_perbit_dly[bit]),
+ dly, max_dq_taps, fail_bit);
+ if (!vref_scan_enable) {
+ if (fail_bit == 0)
+ dramc_dbg("o");
+ else
+ dramc_dbg("x");
+ }
+ }
+
+ if (!vref_scan_enable)
+ dramc_dbg(" [MSB]\n");
+ }
+ if (dramk_calcu_best_vref
+ (type | (1 << engine_type), vref_dq_perbit_dly,
+ dqdqs_perbit_dly, min_win_size, max_win_size_sum))
+ break;
+ }
+
+ if (engine_type)
+ dramc_engine2_end(chn);
+ else
+ dramc_rd_dqc_end(chn);
+
+ if (vref_scan_enable)
+ dramc_set_rx_vref(chn, vref_dq_perbit_dly[0].vref);
+ for (i = 0; i < DQS_NUMBER; i++) {
+ max_dqsdly_byte[i] = 0;
+ ave_dqmdly_byte[i] = 0;
+ }
+
+ for (i = 0; i < DQ_DATA_WIDTH; i++) {
+ index = i / DQS_BIT_NUMBER;
+ fail |= dramc_calcu_best_dly(i,
+ &vref_dq_perbit_dly[i], &max_dqsdly_byte[index]);
+ }
+
+ for (i = 0; i < DQ_DATA_WIDTH; i++) {
+ index = i / DQS_BIT_NUMBER;
+ /* set DQS to max for 8-bit */
+ if (dqdqs_perbit_dly[i].best_dqsdly < max_dqsdly_byte[index]) {
+ /* Delay DQ to compensate extra DQS delay */
+ dly = max_dqsdly_byte[index] -
+ vref_dq_perbit_dly[i].best_dqsdly;
+ vref_dq_perbit_dly[i].best_dqdly += dly;
+ max_limit = MAX_DQDLY_TAPS - 1;
+ if (vref_dq_perbit_dly[i].best_dqdly > max_limit)
+ vref_dq_perbit_dly[i].best_dqdly = max_limit;
+ }
+
+ ave_dqmdly_byte[index] += vref_dq_perbit_dly[i].best_dqdly;
+ if ((i + 1) % DQS_BIT_NUMBER == 0)
+ ave_dqmdly_byte[index] /= DQS_BIT_NUMBER;
+ }
+
+ if (fail == 1) {
+ dramc_dbg("FAIL on perbit_window_cal()\n");
+ return -1;
+ }
+
+ set_rx_best_dly_factor(chn, rank, vref_dq_perbit_dly, max_dqsdly_byte,
+ ave_dqmdly_byte);
+ return 0;
+}
+
+static void dramc_tx_window_perbit_cal(u8 chn, u8 rank, u8 cal_type)
+{
+ u8 vref, vref_begin, vref_end, vref_step;
+ u8 vref_scan_enable;
+ s16 dly_begin = 0, dly_end = 0;
+ u8 i, bit, index;
+ s16 dly;
+ u8 dly_step = 1;
+ u32 win_sum;
+ u32 err_value, fail_bit;
+ struct per_byte_dly tx_perbyte_dly[DQS_NUMBER];
+ static u16 dq_precal_result[DQS_NUMBER];
+ struct dqs_perbit_dly dqdqs_perbit_dly[DQ_DATA_WIDTH];
+ struct dqs_perbit_dly vref_dqdqs_perbit_dly[DQ_DATA_WIDTH];
+ u32 min_win_size = 0xffff;
+ u32 max_win_size_sum = 0;
+
+ if (cal_type == TX_WIN_MOVE_DQ_ONLY)
+ vref_scan_enable = 1;
+ else
+ vref_scan_enable = 0;
+
+ dramc_dbg("%s [Rank %d][Channel %d] Calibration Type:%d\n",
+ __func__, rank, chn, cal_type);
+
+ write32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[0], 0);
+ write32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[0], 0);
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[1], 0xf);
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[1], 0xf);
+
+ setbits_le32(&ch[chn].phy.misc_ctrl1,
+ 0x1 << MISC_CTRL1_R_DMAR_FINE_TUNE_DQ_SW_SHIFT);
+ setbits_le32(&ch[chn].ao.dqsoscr,
+ 0x1 << DQSOSCR_AR_COARSE_TUNE_DQ_SW_SHIFT);
+
+ dramc_engine2_init(chn, rank, DEFAULT_TEST2_1_CAL, DEFAULT_TEST2_2_CAL,
+ TEST_XTALK_PATTERN, 0);
+
+ dramc_get_vref_range(cal_type, vref_scan_enable,
+ &vref_begin, &vref_end, &vref_step);
+ for (vref = vref_begin; vref < vref_end; vref += vref_step) {
+
+ win_sum = 0;
+ for (i = 0; i < DQ_DATA_WIDTH; i++) {
+ dqdqs_perbit_dly[i].vref = vref;
+ dqdqs_perbit_dly[i].first_dqdly_pass = -1;
+ dqdqs_perbit_dly[i].last_dqdly_pass = -2;
+ dqdqs_perbit_dly[i].best_first_dqdly_pass = -1;
+ dqdqs_perbit_dly[i].best_last_dqdly_pass = -2;
+ }
+
+ if (vref_scan_enable)
+ dramc_set_tx_vref(chn, rank, vref);
+
+ dramc_get_dly_range(chn, rank, cal_type, dq_precal_result,
+ &dly_begin, &dly_end);
+
+ dramc_dbg("delay range: (%d - %d)\n", dly_begin, dly_end);
+ for (dly = dly_begin; dly < dly_end; dly += dly_step) {
+ set_dly_factor(chn, rank, cal_type, dly);
+ dramc_dbg("delay = %d ", dly);
+ err_value = dram_k_perbit(chn, 1);
+
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ fail_bit = err_value & ((u32) 1 << bit);
+ dramc_check_dq_win(&(dqdqs_perbit_dly[bit]),
+ dly, dly_end, fail_bit);
+ if (fail_bit == 0)
+ dramc_dbg("o");
+ else
+ dramc_dbg("x");
+ }
+
+ dramc_dbg(" [MSB]\n");
+ }
+
+ for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {
+ dramc_dbg("dq[%d] win(%d ~ %d)\n",
+ bit, dqdqs_perbit_dly[bit].best_first_dqdly_pass,
+ dqdqs_perbit_dly[bit].best_last_dqdly_pass);
+ }
+
+ dramk_calcu_best_vref(cal_type, vref_dqdqs_perbit_dly,
+ dqdqs_perbit_dly, min_win_size, max_win_size_sum);
+ }
+ dramc_engine2_end(chn);
+
+ dramc_dbg("Final Vref is %d\n", vref_dqdqs_perbit_dly[0].vref);
+ if (vref_scan_enable)
+ dramc_set_tx_vref(chn, rank, vref_dqdqs_perbit_dly[0].vref);
+
+ for (i = 0; i < DQS_NUMBER; i++) {
+ tx_perbyte_dly[i].min_center = 0xffff;
+ tx_perbyte_dly[i].max_center = 0;
+ }
+
+ for (i = 0; i < DQ_DATA_WIDTH; i++) {
+ index = i / DQS_BIT_NUMBER;
+ dramc_calcu_tx_perbyte_dly(i, &vref_dqdqs_perbit_dly[i],
+ &tx_perbyte_dly[index]);
+ }
+
+ for (i = 0; i < DQS_NUMBER; i++) {
+ tx_perbyte_dly[i].final_dly =
+ (tx_perbyte_dly[i].max_center +
+ tx_perbyte_dly[i].min_center) >> 1;
+ dq_precal_result[i] = tx_perbyte_dly[i].final_dly;
+ dramc_dbg("dq_perbyte_dly[%d] = %d\n",
+ i, dq_precal_result[i]);
+ }
+
+ set_tx_best_dly_factor(chn, rank, tx_perbyte_dly, dq_precal_result);
+}
+
+static void dramc_read_dbi_onoff(u8 onoff)
+{
+ u8 chn;
+
+ /* DRAMC Read-DBI On/Off */
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[7],
+ 0x1 << SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT,
+ (onoff << SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT));
+ clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[7],
+ 0x1 << SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT,
+ (onoff << SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT));
+ }
+}
+
+static void dramc_write_dbi_onoff(u8 onoff)
+{
+ u8 u1value, chn;
+
+ /* DRAMC Write-DBI On/Off */
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ clrsetbits_le32(&ch[chn].ao.shu[0].wodt,
+ 0x1 << SHU1_WODT_DBIWR_SHIFT,
+ (onoff << SHU1_WODT_DBIWR_SHIFT));
+ }
+
+ u1value = read32(&ch[0].ao.shu[0].wodt);
+ dramc_dbg("DRAMC Write-DBI On/Off = %d\n", u1value);
+}
+
+u8 dramc_zq_calibration(u8 chn, u8 rank)
+{
+ u32 u4Response;
+ u32 u4TimeCnt;
+ u32 *u4RegBackup[] = {
+ &ch[chn].ao.mrs,
+ &ch[chn].ao.dramc_pd_ctrl,
+ &ch[chn].ao.ckectrl,
+ };
+
+ dramc_dbg("[%s] rank:%d\n", __func__, rank);
+ u4TimeCnt = TIME_OUT_CNT;
+
+ save_restore_multi_reg(SAVE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ setbits_le32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26);
+
+ cke_fix_onoff(CKE_FIXON, chn);
+
+ clrsetbits_le32(&ch[chn].ao.mrs,
+ MRS_MPCRK_MASK, (rank << MRS_MPCRK_SHIFT));
+ setbits_le32(&ch[chn].ao.mpc_option,
+ (0x1 << MPC_OPTION_MPCRKEN_SHIFT));
+
+ setbits_le32(&ch[chn].ao.spcmd, (0x1 << SPCMD_ZQCEN_SHIFT));
+ do {
+ u4Response =
+ (read32(&ch[chn].nao.spcmdresp) &
+ (0x1 << SPCMDRESP_ZQC_RESPONSE_SHIFT)) >>
+ SPCMDRESP_ZQC_RESPONSE_SHIFT;
+ u4TimeCnt--;
+ udelay(1);
+ dramc_dbg("try:%d\n", u4TimeCnt);
+ } while ((u4Response == 0) && (u4TimeCnt > 0));
+
+ if (u4TimeCnt == 0) {
+ dramc_dbg("ZQCAL Start fail (time out)\n");
+ return 1;
+ }
+
+ clrbits_le32(&ch[chn].ao.spcmd, (0x1 << SPCMD_ZQCEN_SHIFT));
+
+ udelay(1);
+ u4TimeCnt = TIME_OUT_CNT;
+
+ setbits_le32(&ch[chn].ao.spcmd, (0x1 << SPCMD_ZQLATEN_SHIFT));
+ do {
+ u4Response = (read32(&ch[chn].nao.spcmdresp) &
+ (0x1 << SPCMDRESP_ZQLAT_RESPONSE_SHIFT)) >>
+ SPCMDRESP_ZQLAT_RESPONSE_SHIFT;
+ u4TimeCnt--;
+ udelay(1);
+ dramc_dbg("%d\n", u4TimeCnt);
+ } while ((u4Response == 0) && (u4TimeCnt > 0));
+
+ if (u4TimeCnt == 0) {
+ dramc_dbg("ZQCAL Latch fail (time out)\n");
+ return 1;
+ }
+
+ clrbits_le32(&ch[chn].ao.spcmd, (0x1 << SPCMD_ZQLATEN_SHIFT));
+
+ udelay(1);
+
+ save_restore_multi_reg(RESTORE_VALUE,
+ u4RegBackup, ARRAY_SIZE(u4RegBackup));
+
+ return 0;
+}
+
+static void dle_factor_handler(u8 chn, u8 curr_val)
+{
+ if (curr_val < 2)
+ curr_val = 2;
+ clrsetbits_le32(&ch[chn].ao.shu[0].conf[1],
+ (SHU_CONF1_DATLAT_MASK) | (SHU_CONF1_DATLAT_DSEL_MASK) |
+ (SHU_CONF1_DATLAT_DSEL_PHY_MASK),
+ (curr_val << SHU_CONF1_DATLAT_SHIFT) |
+ ((curr_val - 2) << SHU_CONF1_DATLAT_DSEL_SHIFT) |
+ ((curr_val - 2) << SHU_CONF1_DATLAT_DSEL_PHY_SHIFT));
+ dram_phy_reset(chn);
+}
+
+static u32 rx_datlat_result(u8 chn, u8 rank, u8 type, u8 best_step)
+{
+ static u8 aru1RxDatlatResult[CHANNEL_NUM][RANK_MAX] = {0x0};
+
+ if (type == SAVE_VALUE) {
+ aru1RxDatlatResult[chn][rank] = best_step;
+ return 0;
+ }
+
+ return aru1RxDatlatResult[chn][rank];
+}
+
+static u8 dramc_rxdatlat_scan(u8 chn, u8 rank,
+ enum dram_datlat_type use_rxtx_scan)
+{
+ u8 ii;
+ u32 u4prv_register_080;
+ u32 u4err_value = 0xffffffff;
+ u8 ucfirst, ucbegin, ucsum, ucbest_step;
+ u16 u2DatlatBegin;
+
+ dramc_show("[DATLAT]\nCH%d RK%d, use_rxtx_scan=%d\n\n",
+ chn, rank, use_rxtx_scan);
+
+ u4prv_register_080 = read32(&ch[chn].ao.shu[0].conf[1]);
+ ucbest_step = (u8) (read32(&ch[chn].ao.shu[0].conf[1])
+ & (SHU_CONF1_DATLAT_MASK));
+ dramc_dbg("DATLAT Default: 0x%x\n", ucbest_step);
+
+ ucfirst = 0xff;
+ ucbegin = 0;
+ ucsum = 0;
+
+ dramc_engine2_init(chn, rank, DEFAULT_TEST2_1_CAL, DEFAULT_TEST2_2_CAL,
+ TEST_XTALK_PATTERN, 0);
+
+ u2DatlatBegin = 7;
+ for (ii = u2DatlatBegin; ii < DATLAT_TAP_NUMBER; ii++) {
+ dle_factor_handler(chn, ii);
+
+ if (use_rxtx_scan == DATLAT_USE_DEFAULT) {
+ u4err_value =
+ dramc_engine2_run(chn,
+ TE_OP_WRITE_READ_CHECK,
+ TEST_XTALK_PATTERN);
+ }
+ if (u4err_value == 0) {
+ if (ucbegin == 0) {
+ ucfirst = ii;
+ ucbegin = 1;
+ }
+ if (ucbegin == 1) {
+ ucsum++;
+ if (ucsum > 4)
+ break;
+ }
+ } else {
+ if (ucbegin == 1)
+ ucbegin = 0xff;
+ }
+
+ dramc_show("TAP=%2d, err_value=0x%8x, sum=%d\n",
+ ii, u4err_value, ucsum);
+ }
+
+ dramc_engine2_end(chn);
+
+ if (ucsum == 0)
+ dramc_show("no DATLAT taps pass, DATLAT calibration fail!\n");
+ else if (ucsum <= 3)
+ ucbest_step = ucfirst + (ucsum >> 1);
+ else
+ ucbest_step = ucfirst + 2;
+
+ rx_datlat_result(chn, rank, SAVE_VALUE, ucbest_step);
+ dramc_dbg("pattern=%d first_step=%d total pass=%d best_step=%d\n",
+ TEST_XTALK_PATTERN, ucfirst, ucsum, ucbest_step);
+
+ if (ucsum < 4)
+ dramc_dbg("[NOTICE] CH%d, DatlatSum %d\n", chn, ucsum);
+
+ if (ucsum == 0) {
+ dramc_show("DATLAT calibration fail,"
+ "write back to default values!\n");
+ write32(&ch[chn].ao.shu[0].conf[1], u4prv_register_080);
+ } else {
+ dle_factor_handler(chn, ucbest_step);
+ }
+
+ clrsetbits_le32(&ch[chn].ao.padctrl, (PADCTRL_DQIENQKEND_MASK),
+ (0x1 << PADCTRL_DQIENQKEND_SHIFT) |
+ (0x1 << PADCTRL_DQIENLATEBEGIN_SHIFT));
+ return ucsum;
+}
+
+static void dramc_rx_datlat_cal(u8 chn, u8 rank)
+{
+ u8 u1DatlatWindowSum;
+
+ u1DatlatWindowSum = dramc_rxdatlat_scan(chn, rank, DATLAT_USE_DEFAULT);
+}
+
+static void dramc_dual_rank_rx_datlat_cal(u8 chn)
+{
+ u8 u1FinalDatlat, u1Datlat0, u1Datlat1;
+
+ u1Datlat0 = rx_datlat_result(chn, RANK_0, RESTORE_VALUE, 0);
+ u1Datlat1 = rx_datlat_result(chn, RANK_1, RESTORE_VALUE, 0);
+
+ if (u1Datlat0 > u1Datlat1)
+ u1FinalDatlat = u1Datlat0;
+ else
+ u1FinalDatlat = u1Datlat1;
+
+ dle_factor_handler(chn, u1FinalDatlat);
+ dramc_dbg("[%s] RK0: %d, RK1: %d, Final_Datlat %d\n",
+ __func__, u1Datlat0, u1Datlat1, u1FinalDatlat);
+}
+
+static void imp_cal_vref_sel(u8 term_option, u8 u1ImpCalStage)
+{
+ u8 u1RegTmpValue = 0;
+
+ if (term_option == 1) {
+ u1RegTmpValue = IMP_LP4X_TERM_VREF_SEL;
+ } else {
+ if (u1ImpCalStage == IMPCAL_STAGE_DRVP)
+ u1RegTmpValue = IMP_DRVP_LP4X_UNTERM_VREF_SEL;
+ else if (u1ImpCalStage == IMPCAL_STAGE_DRVN)
+ u1RegTmpValue = IMP_DRVN_LP4X_UNTERM_VREF_SEL;
+ else
+ u1RegTmpValue = IMP_TRACK_LP4X_UNTERM_VREF_SEL;
+ }
+
+ dramc_dbg("[%s] IMP_VREF_SEL 0x%x\n", __func__, u1RegTmpValue);
+
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11],
+ 0x3f << 8, u1RegTmpValue << 8);
+}
+
+void dramc_sw_impedance_save_register(const struct sdram_params *params)
+{
+ int tmp;
+ u32 broadcast_bak;
+ u8 term_opt, ca_term_option = 0, dq_term_option = 1;
+ u32 uSwImpedanceResult[2][4] = { {0}, {0} };
+
+ uSwImpedanceResult[0][0] = params->impedance[ca_term_option][0];
+ uSwImpedanceResult[0][1] = params->impedance[ca_term_option][1];
+ uSwImpedanceResult[0][2] = params->impedance[ca_term_option][2];
+ uSwImpedanceResult[0][3] = params->impedance[ca_term_option][3];
+
+ uSwImpedanceResult[1][0] = params->impedance[dq_term_option][0];
+ uSwImpedanceResult[1][1] = params->impedance[dq_term_option][1];
+ uSwImpedanceResult[1][2] = params->impedance[dq_term_option][2];
+ uSwImpedanceResult[1][3] = params->impedance[dq_term_option][3];
+
+ broadcast_bak = get_dramc_broadcast();
+
+ uSwImpedanceResult[ODT_OFF][2] = uSwImpedanceResult[ODT_ON][2];
+ uSwImpedanceResult[ODT_OFF][3] = uSwImpedanceResult[ODT_ON][3];
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ tmp = 3;
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11],
+ 0xFF, tmp);
+
+ /* Set IMP_VREF_SEL value for DRVP */
+ imp_cal_vref_sel(dq_term_option, IMPCAL_STAGE_DRVP);
+
+ /* DQ */
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[0], (0x1F << 5)|(0x1F << 0),
+ (uSwImpedanceResult[dq_term_option][0] << 5) |
+ (uSwImpedanceResult[dq_term_option][1] << 0));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[1],
+ (0x1F << 25)|(0x1F << 20) | (1 << 31),
+ (uSwImpedanceResult[dq_term_option][0] << 25) |
+ (uSwImpedanceResult[dq_term_option][1] << 20) |
+ (!dq_term_option << 31));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[2], (0x1F << 5)|(0x1F << 0),
+ (uSwImpedanceResult[dq_term_option][2] << 5) |
+ (uSwImpedanceResult[dq_term_option][3] << 0));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[3], (0x1F << 25)|(0x1F << 20),
+ (uSwImpedanceResult[dq_term_option][2] << 25) |
+ (uSwImpedanceResult[dq_term_option][3] << 20));
+ /* DQS */
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[0], (0x1F << 25)|(0x1F << 20),
+ (uSwImpedanceResult[dq_term_option][0] << 25) |
+ (uSwImpedanceResult[dq_term_option][1] << 20));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[0], (0x1F << 15)|(0x1F << 10),
+ (uSwImpedanceResult[dq_term_option][0] << 15) |
+ (uSwImpedanceResult[dq_term_option][1] << 10));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[2], (0x1F << 25)|(0x1F << 20),
+ (uSwImpedanceResult[dq_term_option][2] << 25) |
+ (uSwImpedanceResult[dq_term_option][3] << 20));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[2], (0x1F << 15)|(0x1F << 10),
+ (uSwImpedanceResult[dq_term_option][2] << 15) |
+ (uSwImpedanceResult[dq_term_option][3] << 10));
+
+ /* CMD & CLK */
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[1], (0x1F << 15)|(0x1F << 10),
+ (uSwImpedanceResult[ca_term_option][0] << 15) |
+ (uSwImpedanceResult[ca_term_option][1] << 10));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[1], (0x1F << 5)|(0x1F << 0),
+ (uSwImpedanceResult[ca_term_option][0] << 5) |
+ (uSwImpedanceResult[ca_term_option][1] << 0));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[3], (0x1F << 15)|(0x1F << 10),
+ (uSwImpedanceResult[ca_term_option][2] << 15) |
+ (uSwImpedanceResult[ca_term_option][3] << 10));
+ clrsetbits_le32(&ch[0].ao.shu[0].drving[3], (0x1F << 5)|(0x1F << 0),
+ (uSwImpedanceResult[ca_term_option][2] << 5) |
+ (uSwImpedanceResult[ca_term_option][3] << 0));
+
+ /* RG_TX_*RCKE_DRVP/RG_TX_*RCKE_DRVN doesn't set, so set 0xA first */
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], (0x1f << 17),
+ (uSwImpedanceResult[ca_term_option][0] << 17));
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], (0x1f << 22),
+ (uSwImpedanceResult[ca_term_option][1] << 22));
+ /* DRVP[4:0] = RG_TX_ARCMD_PU_PRE<1:0>, RG_TX_ARCLK_DRVN_PRE<2:0> */
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[3],
+ SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_MASK,
+ (((8 >> 3) & 0x3) <<
+ SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_SHIFT));
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[0],
+ SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE_MASK,
+ ((8 & 0x7) << SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE_SHIFT));
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+ clrsetbits_le32(&ch[0].phy.shu[0].ca_dll[1],
+ (0x1F << 16), (0x9 << 16));
+ clrsetbits_le32(&ch[1].phy.shu[0].ca_dll[1],
+ (0x1F << 16), (0x9 << 16));
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ for (term_opt = 0; term_opt < 2; term_opt++) {
+ dramc_show("term_opt=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n",
+ term_opt, uSwImpedanceResult[term_opt][0],
+ uSwImpedanceResult[term_opt][1],
+ uSwImpedanceResult[term_opt][3]);
+ }
+ dramc_broadcast_onoff(broadcast_bak);
+}
+
+static void enable_dramc_phy_dcm_2_channel(u8 chn, u8 bEn)
+{
+ u8 shu, shu_cnt = DRAM_DFS_SHUFFLE_MAX;
+
+ if (!bEn) {
+ clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl0,
+ (0x1 << 20) | (0x1 << 19) | 0x3FF << 8,
+ (0x0 << 20) | (0x1 << 19) | 0x3FF << 8);
+
+ for (shu = DRAM_DFS_SHUFFLE_1; shu < shu_cnt; shu++) {
+ setbits_le32(&ch[chn].phy.shu[shu].b[0].dq[8],
+ 0x1FFF << 19);
+ setbits_le32(&ch[chn].phy.shu[shu].b[1].dq[8],
+ 0x1FFF << 19);
+ clrbits_le32(&ch[chn].phy.shu[shu].ca_cmd[8],
+ 0x1FFF << 19);
+ }
+ clrbits_le32(&ch[chn].phy.misc_cg_ctrl5,
+ (0x7 << 16) | (0x7 << 20));
+ }
+}
+
+void enable_dramc_phy_dcm(u8 bEn)
+{
+ u32 broadcast_bak = get_dramc_broadcast();
+ u8 shu, shu_cnt = DRAM_DFS_SHUFFLE_MAX;
+ u8 chn = 0;
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+
+ for (chn = 0; chn < CHANNEL_NUM ; chn++) {
+ clrbits_le32(&ch[chn].phy.b[0].dll_fine_tune[1], (0x1 << 20));
+ clrbits_le32(&ch[chn].phy.b[1].dll_fine_tune[1], (0x1 << 20));
+ clrbits_le32(&ch[chn].phy.ca_dll_fine_tune[1], (0x1 << 20));
+
+ for (shu = 0; shu < shu_cnt; shu++) {
+ setbits_le32(&ch[chn].phy.shu[shu].b[0].dll[0],
+ (0x1 << 0));
+ setbits_le32(&ch[chn].phy.shu[shu].b[1].dll[0],
+ (0x1 << 0));
+ setbits_le32(&ch[chn].phy.shu[shu].ca_dll[0],
+ (0x1 << 0));
+ }
+
+ if (bEn) { /* DCM on */
+ clrsetbits_le32(&ch[chn].ao.dramc_pd_ctrl,
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2) |
+ (0x1 << 5) |
+ (0x1 << 26) | (0x1 << 30) | (0x1 << 31),
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2) |
+ (0x0 << 5) |
+ (0x0 << 26) | (0x1 << 30) | (0x1 << 31));
+
+ /* CHANNEL_EMI free run */
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x806003BE);
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x806003BF);
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x806003BF);
+ clrbits_le32(&ch[chn].phy.misc_ctrl3, (0x3 << 26));
+
+ for (shu = 0; shu < shu_cnt; shu++) {
+ setbits_le32(&ch[chn].phy.shu[shu].b[0].dq[7],
+ (0x7 << 17));
+ setbits_le32(&ch[chn].phy.shu[shu].b[1].dq[7],
+ (0x7 << 17));
+ setbits_le32(&ch[chn].phy.shu[shu].ca_cmd[7],
+ (0x7 << 17));
+ }
+ } else {
+ clrsetbits_le32(&ch[chn].ao.dramc_pd_ctrl,
+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2) |
+ (0x1 << 5) | (0x1 << 26) |
+ (0x1 << 30) | (0x1 << 31),
+ (0x0 << 0) | (0x0 << 1) | (0x0 << 2) |
+ (0x1 << 5) | (0x1 << 26) |
+ (0x0 << 30) | (0x0 << 31));
+
+ /* mem_dcm */
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060037E);
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060037F);
+ write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060037E);
+
+ setbits_le32(&ch[chn].phy.misc_ctrl3, (0x3 << 26));
+
+ for (shu = 0; shu < shu_cnt; shu++) {
+ clrbits_le32(&ch[chn].phy.shu[shu].b[0].dq[7],
+ (0x7 << 17));
+ clrbits_le32(&ch[chn].phy.shu[shu].b[1].dq[7],
+ (0x7 << 17));
+ clrbits_le32(&ch[chn].phy.shu[shu].ca_cmd[7],
+ (0x7 << 17));
+ }
+ }
+ }
+ enable_dramc_phy_dcm_2_channel(chn, bEn);
+
+ dramc_broadcast_onoff(broadcast_bak);
+}
+
+static void reset_delay_chain_before_calibration(void)
+{
+ u8 chn = 0, rank = 0;
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ for (rank = 0; rank < RANK_MAX; rank++) {
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[0],
+ (0xffffff << 0));
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[0],
+ (0xfffffff << 0));
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[0],
+ (0xfffffff << 0));
+
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[1],
+ (0xf << 0));
+
+ clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[1],
+ (0xf << 0));
+ }
+ }
+}
+
+void dramc_hw_gating_onoff(u8 chn, u8 u1OnOff)
+{
+ clrsetbits_le32(&ch[chn].ao.shuctrl2, (0x3 << 14),
+ (u1OnOff << 14) | (u1OnOff << 15));
+ clrsetbits_le32(&ch[chn].ao.stbcal2, (0x1 << 28), (u1OnOff << 28));
+ clrsetbits_le32(&ch[chn].ao.stbcal, (0x1 << 24), (u1OnOff << 24));
+ clrsetbits_le32(&ch[chn].ao.stbcal, (0x1 << 22), (u1OnOff << 22));
+}
+
+static void dramc_rx_input_delay_tracking_init_by_freq(void)
+{
+ u8 u1DVS_Delay;
+
+ u1DVS_Delay = 3;
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dq[5],
+ (0x7 << 20), (u1DVS_Delay << 20));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[1].dq[5],
+ (0x7 << 20), (u1DVS_Delay << 20));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[0].dq[7],
+ (0x1 << 12) | (0x1 << 13), (0x0 << 12) | (0x0 << 13));
+ clrsetbits_le32(&ch[0].phy.shu[0].b[1].dq[7],
+ (0x1 << 12) | (0x1 << 13), (0x0 << 12) | (0x0 << 13));
+}
+
+void apply_config_before_calibration(void)
+{
+ u8 shuf = 0;
+
+ /* Clk free run */
+ enable_dramc_phy_dcm(0);
+
+ /* Set LP4 Rank0/1 CA/TX delay chain to 0
+ * CA0~9 per bit delay line -> CHA_CA0 CHA_CA3 CHA_B0_DQ6 CHA_B0_DQ7
+ * CHA_B0_DQ2 CHA_B0_DQ5 CHA_B0_DQ4 CHA_B0_DQ1 CHA_B0_DQ0 CHA_B0_DQ3 */
+ reset_delay_chain_before_calibration();
+
+ /* MR4 refresh cnt set to 0x1ff (2ms update) */
+ clrsetbits_le32(&ch[0].ao.shu[0].conf[3],
+ (0x1ff << 16), (0x1ff << 16));
+
+ /* The counter for Read MR4 cannot be reset
+ * after SREF if DRAMC no power down. */
+ setbits_le32(&ch[0].ao.spcmdctrl, (0x1 << 24));
+
+ /* ---- ZQ CS init -------- */
+ /* ZQ Calibration Time, unit: 38.46ns, tZQCAL min is 1 us.
+ * need to set larger than 0x1b
+ */
+ clrsetbits_le32(&ch[0].ao.shu[0].scintv,
+ (0x1f << 1), (0x1b << 1));
+ /* Every refresh number to issue ZQCS commands,
+ * only for DDR3/LPDDR2/LPDDR3/LPDDR4
+ */
+ for (shuf = DRAM_DFS_SHUFFLE_1; shuf < DRAM_DFS_SHUFFLE_MAX; shuf++)
+ setbits_le32(&ch[0].ao.shu[shuf].conf[3], (0x1ff << 0));
+
+ /* HW send ZQ command for both rank, disable it due to
+ * some dram only have 1 ZQ pin for two rank.
+ */
+ clrbits_le32(&ch[0].ao.dramctrl, (0x1 << 18));
+
+ /* Disable LP4 HW ZQ */
+ /* ZQCSDISB=0 */
+ clrbits_le32(&ch[0].ao.spcmdctrl, (0x1 << 31));
+ /* LP4 ZQCALDISB=0 */
+ clrbits_le32(&ch[0].ao.spcmdctrl, (0x1 << 30));
+ /* End of ZQ CS init */
+
+ /* CBT_MODE = NORMAL_MODE */
+ clrbits_le32(&ch[0].ao.dqsoscr, (0x1 << 26));
+ clrbits_le32(&ch[0].ao.dqsoscr, (0x1 << 25));
+
+ /* Recover write-DBI of DRAMC */
+ dramc_write_dbi_onoff(DBI_OFF);
+ dramc_read_dbi_onoff(DBI_OFF);
+
+ for (int chn = 0; chn < CHANNEL_NUM; chn++) {
+ /* disable MR4 read, REFRDIS=1 */
+ setbits_le32(&ch[chn].ao.spcmdctrl, (0x1 << 29));
+ setbits_le32(&ch[chn].ao.dqsoscr, (0x1 << 24));
+ for (shuf = 0; shuf < DRAM_DFS_SHUFFLE_MAX; shuf++)
+ setbits_le32(&ch[chn].ao.shu[shuf].scintv,
+ (0x1 << 30));
+
+ clrbits_le32(&ch[chn].ao.dummy_rd, (0x1 << 7) | (0x7 << 20));
+
+ /* Disable HW gating tracking first, 0x1c0[31],
+ * need to disable both coarse tune and fine tune tracking
+ * or the gating delay reg won't be valid.
+ */
+ dramc_hw_gating_onoff(chn, GATING_OFF);
+
+ /* Disable gating debug */
+ clrbits_le32(&ch[chn].ao.stbcal2, (0x1 << 28));
+ }
+
+ for (size_t r = 0; r < 2; r++) {
+ for (size_t b = 0; b < 2; b++) {
+ /* Disable RX delay tracking */
+ clrbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x1 << 28));
+ clrbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x1 << 23));
+
+ /* RX delay mux, delay vlaue from reg. */
+ clrbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2],
+ (0x3 << 30));
+ }
+ clrbits_le32(&ch[0].phy.r0_ca_rxdvs[2],
+ (0x3 << 30));
+ }
+
+ for (int chn = 0; chn < CHANNEL_NUM; chn++) {
+ setbits_le32(&ch[chn].phy.misc_ctrl1,
+ (0x1 << 7) | (0x1 << 11));
+
+ /* Set to all-bank refresh */
+ clrbits_le32(&ch[chn].ao.refctrl0, (0x1 << 18));
+
+ /* set MPCRK to 0, MPCRKEN alwasys set 1 */
+ clrbits_le32(&ch[chn].ao.mrs, (0x3 << 24));
+ setbits_le32(&ch[chn].ao.mpc_option, (0x1 << 17));
+
+ /* RG mode */
+ 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();
+ for (int chn = 0; chn < CHANNEL_NUM; chn++) {
+ setbits_le32(&ch[chn].ao.dummy_rd, (0x1 << 25));
+ setbits_le32(&ch[chn].ao.drsctrl, (0x1 << 0));
+
+ clrbits_le32(&ch[chn].ao.shu[1].drving[1], 0x1 << 31);
+ }
+}
+
+void dram_calibration_all_channel(const struct sdram_params *params)
+{
+ for (u8 chn = 0; chn < CHANNEL_NUM; chn++) {
+ for (u8 rank = RANK_0; rank < RANK_MAX; rank++) {
+ dramc_show("start K ch:%d, rank:%d\n", chn, rank);
+ dramc_zq_calibration(chn, rank);
+ auto_refresh_switch(chn, 0);
+
+ cmd_bus_training(chn, rank, params);
+
+ /* Dram will be reset when finish write leveling */
+ dramc_write_leveling(chn, rank, params);
+
+ auto_refresh_switch(chn, 1);
+ dramc_rx_dqs_gating_cal(chn, rank);
+ dramc_rx_window_perbit_cal(chn, RX_WIN, rank, 0);
+
+ dramc_tx_window_perbit_cal(chn, rank,
+ TX_WIN_MOVE_DQ_DQM);
+ dramc_tx_window_perbit_cal(chn, rank,
+ TX_WIN_MOVE_DQ_ONLY);
+
+ dramc_rx_datlat_cal(chn, rank);
+ dramc_rx_window_perbit_cal(chn, RX_WIN, rank, 1);
+ }
+
+ /* ENABLE_TX_TRACKING */
+ dramc_rx_dqs_gating_post_process(chn);
+ dramc_dual_rank_rx_datlat_cal(chn);
+ }
+}
diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c
index e37fd56..8ef1613 100644
--- a/src/soc/mediatek/mt8183/emi.c
+++ b/src/soc/mediatek/mt8183/emi.c
@@ -13,9 +13,312 @@
* GNU General Public License for more details.
*/

+#include <arch/io.h>
+#include <soc/addressmap.h>
+#include <soc/dramc_pi_api.h>
+#include <soc/dramc_register.h>
#include <soc/emi.h>
+#include <soc/infracfg.h>
+#include <soc/spm.h>
+#include <delay.h>
+
+struct emi_regs *emi_regs = (void *)EMI_BASE;
+
+void get_dram_rank_size(u64 *dram_rank_size)
+{
+ u32 col_bit, row_bit;
+ u32 shift_for_16bit = 1; /* data width = 2 bytes */
+ u64 ch0_rank0_size, ch0_rank1_size, ch1_rank0_size, ch1_rank1_size;
+ u64 ch_rank0_size = 0, ch_rank1_size = 0;
+
+ u32 emi_cona = read32(&emi_regs->cona);
+ u32 emi_conh = read32(&emi_regs->conh);
+
+ if (emi_cona & 0x2)
+ shift_for_16bit = 0; /* data width = 4 bytes */
+
+ dram_rank_size[0] = 0;
+ dram_rank_size[1] = 0;
+
+ ch0_rank0_size = (emi_conh >> 16) & 0xf;
+ ch0_rank1_size = (emi_conh >> 20) & 0xf;
+ ch1_rank0_size = (emi_conh >> 24) & 0xf;
+ ch1_rank1_size = (emi_conh >> 28) & 0xf;
+
+ /* CH0 EMI */
+ if (ch0_rank0_size == 0) {
+ /* rank 0 setting */
+ col_bit = ((emi_cona >> 4) & 0x03) + 9;
+ row_bit = ((((emi_cona >> 24) & 0x01) << 2) +
+ ((emi_cona >> 12) & 0x03)) + 13;
+ /* data width (bytes) * 8 banks */
+ ch_rank0_size = ((u64)(1 << (row_bit + col_bit))) *
+ ((u64)(4 >> shift_for_16bit) * 8);
+ } else {
+ ch_rank0_size = (ch0_rank0_size * 256 << 20);
+ }
+
+ /* dual rank enable */
+ if (0 != (emi_cona & (1 << 17))) {
+ if (ch0_rank1_size == 0) {
+ col_bit = ((emi_cona >> 6) & 0x03) + 9;
+ row_bit = ((((emi_cona >> 25) & 0x01) << 2) +
+ ((emi_cona >> 14) & 0x03)) + 13;
+ /* data width (bytes) * 8 banks */
+ ch_rank1_size = ((u64)(1 << (row_bit + col_bit))) *
+ ((u64)(4 >> shift_for_16bit) * 8);
+ } else {
+ ch_rank1_size = (ch0_rank1_size * 256 << 20);
+ }
+ }
+
+ dram_rank_size[0] = ch_rank0_size;
+ dram_rank_size[1] = ch_rank1_size;
+
+ if (ch1_rank0_size == 0) {
+ /* rank0 setting */
+ col_bit = ((emi_cona >> 20) & 0x03) + 9;
+ row_bit = ((((emi_conh >> 4) & 0x01) << 2) +
+ ((emi_cona >> 28) & 0x03)) + 13;
+
+ /* data width (bytes) * 8 banks */
+ ch_rank0_size = ((u64)(1 << (row_bit + col_bit))) *
+ ((u64)(4 >> shift_for_16bit) * 8);
+ } else {
+ ch_rank0_size = (ch1_rank0_size * 256 << 20);
+ }
+
+ if (0 != (emi_cona & (1 << 16))) {
+ if (ch1_rank1_size == 0) {
+ col_bit = ((emi_cona >> 22) & 0x03) + 9;
+ row_bit = ((((emi_conh >> 5) & 0x01) << 2) +
+ ((emi_cona >> 30) & 0x03)) + 13;
+ /* data width (bytes) * 8 banks */
+ ch_rank1_size = ((u64)(1 << (row_bit + col_bit))) *
+ ((u64)(4 >> shift_for_16bit) * 8);
+ } else {
+ ch_rank1_size = (ch1_rank1_size * 256 << 20);
+ }
+ }
+
+ dram_rank_size[0] += ch_rank0_size;
+ dram_rank_size[1] += ch_rank1_size;
+}

size_t sdram_size(void)
{
- return (size_t)4 * GiB;
+ size_t dram_size = 0;
+ u64 rank_size[RANK_MAX];
+
+ get_dram_rank_size(&rank_size[0]);
+
+ for (int i = 0; i < RANK_MAX; i++) {
+ dram_size += rank_size[i];
+ dramc_show("rank%d size:0x%llx\n", i, rank_size[i]);
+ }
+
+ return dram_size;
+}
+
+static void set_rank_info_to_conf(const struct sdram_params *params)
+{
+ u8 u4value = 0;
+
+ /* CONA 17th bit 0: Disable dual rank mode
+ * 1: Enable dual rank mode */
+ u4value = ((params->EMI_CONA_VAL & (0x1 << 17)) >> 17) ? 0 : 1;
+ clrsetbits_le32(&ch[0].ao.arbctl, 0x1 << 12, u4value << 12);
+}
+
+static void set_MRR_pinmux_mapping(void)
+{
+ u8 chn;
+ u8 phy_mapping[CHANNEL_NUM][16] = {
+ [CHANNEL_A] = {
+ 1, 0, 2, 4, 3, 7, 5, 6,
+ 9, 8, 12, 11, 10, 15, 13, 14
+ },
+
+ [CHANNEL_B] = {
+ 0, 1, 5, 6, 3, 7, 4, 2,
+ 9, 8, 12, 15, 11, 14, 13, 10
+ }
+ };
+
+ for (chn = 0; chn < CHANNEL_NUM; chn++) {
+ u8 *map = phy_mapping[chn];
+ write32(&ch[chn].ao.mrr_bit_mux1,
+ (map[0] << 0) | (map[1] << 8) |
+ (map[2] << 16) | (map[3] << 24));
+
+ write32(&ch[chn].ao.mrr_bit_mux2,
+ (map[4] << 0) | (map[5]<<8) |
+ (map[6] << 16) | (map[7] << 24));
+
+ write32(&ch[chn].ao.mrr_bit_mux3,
+ (map[8] << 0) | (map[9] << 8) |
+ (map[10] << 16) | (map[11]<<24));
+
+ write32(&ch[chn].ao.mrr_bit_mux4,
+ (map[12] << 0) | (map[13] << 8) |
+ (map[14] << 16) | (map[15] << 24));
+ }
+}
+
+static void global_option_init(const struct sdram_params *params)
+{
+ set_rank_info_to_conf(params);
+ set_MRR_pinmux_mapping();
+}
+
+static void emi_esl_setting1(void)
+{
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ write32(&emi_regs->cona, 0xa053a154);
+
+ write32(&emi_regs->conb, 0x17283544);
+ write32(&emi_regs->conc, 0x0a1a0b1a);
+ write32(&emi_regs->cond, 0x3657587a);
+ write32(&emi_regs->cone, 0x80400148);
+ write32(&emi_regs->conf, 0x00000000);
+ write32(&emi_regs->cong, 0x2b2b2a38);
+ write32(&emi_regs->conh, 0x00000000);
+
+ write32(&emi_regs->coni, 0x00008803);
+ write32(&emi_regs->conm, 0x000001ff);
+ write32(&emi_regs->conn, 0x00000000);
+ write32(&emi_regs->mdct, 0x11338c17);
+ write32(&emi_regs->mdct_2nd, 0x00001112);
+ write32(&emi_regs->iocl, 0xa8a8a8a8);
+ write32(&emi_regs->iocl_2nd, 0x25252525);
+ write32(&emi_regs->iocm, 0xa8a8a8a8);
+ write32(&emi_regs->iocm_2nd, 0x25252525);
+ write32(&emi_regs->testb, 0x00060037);
+ write32(&emi_regs->testc, 0x38460000);
+ write32(&emi_regs->testd, 0x00000000);
+
+ write32(&emi_regs->arba, 0x4020524f);
+ write32(&emi_regs->arbb, 0x4020504f);
+ write32(&emi_regs->arbc, 0xa0a050c6);
+ write32(&emi_regs->arbd, 0x000070cc);
+ write32(&emi_regs->arbe, 0x40406045);
+ write32(&emi_regs->arbf, 0xa0a070d5);
+ write32(&emi_regs->arbg, 0xa0a0504f);
+ write32(&emi_regs->arbh, 0xa0a0504f);
+
+ write32(&emi_regs->arbi, 0x00007108);
+ write32(&emi_regs->arbi_2nd, 0x00007108);
+ write32(&emi_regs->slct, 0x0001ff00);
+
+ write32(&ch[0].emi.chn_cona, 0x0400a051);
+ write32(&ch[0].emi.chn_conb, 0x00ff2048);
+ write32(&ch[0].emi.chn_conc, 0x00000000);
+ write32(&ch[0].emi.chn_mdct, 0x88008817);
+
+ write32(&ch[0].emi.chn_testb, 0x00030027);
+ write32(&ch[0].emi.chn_testc, 0x38460002);
+ write32(&ch[0].emi.chn_testd, 0x00000000);
+
+ write32(&ch[0].emi.chn_md_pre_mask, 0x00000f00);
+ write32(&ch[0].emi.chn_md_pre_mask_shf, 0x00000b00);
+
+ write32(&ch[0].emi.chn_arbi, 0x20406188);
+ write32(&ch[0].emi.chn_arbi_2nd, 0x20406188);
+
+ write32(&ch[0].emi.chn_arbj, 0x3719595e);
+ write32(&ch[0].emi.chn_arbj_2nd, 0x3719595e);
+ write32(&ch[0].emi.chn_arbk, 0x64f3fc79);
+ write32(&ch[0].emi.chn_arbk_2nd, 0x64f3fc79);
+ write32(&ch[0].emi.chn_slct, 0x00080888);
+ write32(&ch[0].emi.chn_arb_ref, 0x82410222);
+
+ write32(&ch[0].emi.chn_emi_shf0, 0x8a228c17);
+ write32(&ch[0].emi.chn_rkarb0, 0x0006002f);
+ write32(&ch[0].emi.chn_rkarb1, 0x01010101);
+ write32(&ch[0].emi.chn_rkarb2, 0x10100820);
+ write32(&ch[0].emi.chn_eco3, 0x00000000);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+}
+
+static void emi_esl_setting2(void)
+{
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+
+ write32(&ch[0].emi.chn_conc, 0x01);
+ write32(&emi_regs->conm, 0x05ff);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_OFF);
+}
+
+static void emi_init(const struct sdram_params *params)
+{
+ emi_esl_setting1();
+
+ write32(&emi_regs->cona, params->EMI_CONA_VAL);
+ write32(&emi_regs->conf, params->EMI_CONF_VAL);
+ write32(&emi_regs->conh, params->EMI_CONH_VAL);
+
+ for (size_t chn = CHANNEL_A; chn < CHANNEL_NUM; chn++) {
+ write32(&ch[chn].emi.chn_cona, params->CHN_EMI_CONA_VAL[chn]);
+ write32(&ch[chn].emi.chn_conc, 0);
+ }
+}
+
+static void emi_init2(const struct sdram_params *params)
+{
+ emi_esl_setting2();
+
+ setbits_le32(&emi_mpu->mpu_ctrl_d0 + 0x4 * 1, 0x1 << 4);
+ setbits_le32(&emi_mpu->mpu_ctrl_d0 + 0x4 * 7, 0x1 << 4);
+
+ write32(&emi_regs->bwct0, 0x0A000705);
+ write32(&emi_regs->bwct0_3rd, 0x0);
+
+ /* EMI QoS 0.5 */
+ write32(&emi_regs->bwct0_2nd, 0x00030023);
+ write32(&emi_regs->bwct0_4th, 0x00c00023);
+ write32(&emi_regs->bwct0_5th, 0x00240023);
+}
+
+static void dramc_init_pre_settings(void)
+{
+ clrsetbits_le32(&ch[0].phy.ca_cmd[8],
+ (0x1 << 21) | (0x1 << 20) | (0x1 << 19) | (0x1 << 18) |
+ (0x1F << 8) | (0x1f << 0),
+ (0x1 << 19) | (0xa << 8) | (0xa << 0));
+
+ setbits_le32(&ch[0].phy.misc_ctrl1, (0x1 << 12));
+ clrbits_le32(&ch[0].phy.misc_ctrl1, (0x1 << 13));
+ setbits_le32(&ch[0].phy.misc_ctrl1, (0x1 << 31));
+}
+
+static void init_dram(const struct sdram_params *params)
+{
+ global_option_init(params);
+ emi_init(params);
+
+ dramc_broadcast_onoff(DRAMC_BROADCAST_ON);
+ dramc_init_pre_settings();
+
+ dramc_sw_impedance_save_register(params);
+
+ dramc_init(params);
+ emi_init2(params);
+}
+
+static void do_calib(const struct sdram_params *params)
+{
+ apply_config_before_calibration();
+ dram_calibration_all_channel(params);
+
+ dramc_ac_timing_optimize();
+ dramc_runtime_config();
+}
+
+void mt_set_emi(const struct sdram_params *params)
+{
+ init_dram(params);
+ do_calib(params);
}
diff --git a/src/soc/mediatek/mt8183/include/soc/addressmap.h b/src/soc/mediatek/mt8183/include/soc/addressmap.h
index de7eb1f..f8edf5b 100644
--- a/src/soc/mediatek/mt8183/include/soc/addressmap.h
+++ b/src/soc/mediatek/mt8183/include/soc/addressmap.h
@@ -19,7 +19,6 @@
enum {
MCUCFG_BASE = 0x0C530000,
IO_PHYS = 0x10000000,
- DDR_BASE = 0x40000000
};

enum {
@@ -30,6 +29,9 @@
RGU_BASE = IO_PHYS + 0x00007000,
GPT_BASE = IO_PHYS + 0x00008000,
APMIXED_BASE = IO_PHYS + 0x0000C000,
+ EMI_BASE = IO_PHYS + 0x00219000,
+ EMI_MPU_BASE = IO_PHYS + 0x00226000,
+ DRAMC_CH_BASE = IO_PHYS + 0x00228000,
UART0_BASE = IO_PHYS + 0x01002000,
SPI0_BASE = IO_PHYS + 0x0100A000,
SPI1_BASE = IO_PHYS + 0x01010000,
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
new file mode 100644
index 0000000..08b7b78
--- /dev/null
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DRAMC_COMMON_MT8183_H_
+#define _DRAMC_COMMON_MT8183_H_
+
+enum {
+ CHANNEL_A = 0,
+ CHANNEL_B,
+ CHANNEL_NUM
+};
+
+enum {
+ RANK_0 = 0,
+ RANK_1,
+ RANK_MAX
+};
+
+enum dram_odt_type {
+ ODT_OFF = 0,
+ ODT_ON
+};
+
+enum {
+ DQ_DATA_WIDTH = 16,
+ DQS_BIT_NUMBER = 8,
+ DQS_NUMBER = (DQ_DATA_WIDTH / DQS_BIT_NUMBER)
+};
+
+/*
+ * Internal CBT mode enum
+ * 1. Calibration flow uses vGet_Dram_CBT_Mode to
+ * differentiate between mixed vs non-mixed LP4
+ * 2. Declared as dram_cbt_mode[RANK_MAX] internally to
+ * store each rank's CBT mode type
+ */
+enum {
+ CBT_NORMAL_MODE = 0,
+ CBT_BYTE_MODE1
+};
+
+#endif /* _DRAMC_COMMON_MT8183_H_ */
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h
new file mode 100644
index 0000000..409086f
--- /dev/null
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h
@@ -0,0 +1,245 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DRAMC_PI_API_MT8183_H
+#define _DRAMC_PI_API_MT8183_H
+
+#include <console/console.h>
+#include <soc/emi.h>
+#include <types.h>
+
+#define dramc_show(_x_...) printk(BIOS_INFO, _x_)
+#if IS_ENABLED(CONFIG_DEBUG_DRAM)
+#define dramc_dbg(_x_...) printk(BIOS_DEBUG, _x_)
+#else
+#define dramc_dbg(_x_...)
+#endif
+
+#define ENABLE 1
+#define DISABLE 0
+
+#define DATLAT_TAP_NUMBER 32
+#define DEFAULT_TEST2_1_CAL 0x55000000
+#define DEFAULT_TEST2_2_CAL 0xaa000400
+
+#define MAX_CMP_CPT_WAIT_LOOP 10000
+#define TIME_OUT_CNT 100
+
+#define DRAMC_BROADCAST_ON 0x1f
+#define DRAMC_BROADCAST_OFF 0x0
+#define MR13_RRO 1
+#define POS_BANK_NUM 16
+#define MAX_BACKUP_REG_CNT 64
+
+enum {
+ TEST_ISI_PATTERN = 0,
+ TEST_AUDIO_PATTERN,
+ TEST_XTALK_PATTERN,
+ TEST_TA1_SIMPLE,
+ TEST_TESTPAT4,
+ TEST_TESTPAT4_3,
+ TEST_MIX_PATTERN,
+ TEST_DMA,
+};
+
+enum dram_datlat_type {
+ DATLAT_USE_DEFAULT = 0,
+ DATLAT_USE_RX_SCAN,
+};
+
+enum dram_te_op {
+ TE_OP_WRITE_READ_CHECK = 0,
+ TE_OP_READ_CHECK
+};
+
+enum {
+ DBI_OFF = 0,
+ DBI_ON
+};
+
+enum {
+ FSP_0 = 0,
+ FSP_1,
+ FSP_MAX
+};
+
+enum {
+ DLL_MASTER_CH = CHANNEL_A,
+ DLL_SLAVE_CH = CHANNEL_B,
+};
+
+enum {
+ TX_DQ_DQS_MOVE_DQ_ONLY = 0,
+ TX_DQ_DQS_MOVE_DQM_ONLY,
+ TX_DQ_DQS_MOVE_DQ_DQM
+};
+
+enum {
+ MAX_CA_FINE_TUNE_DELAY = 63,
+ MAX_CS_FINE_TUNE_DELAY = 63,
+ MAX_CLK_FINE_TUNE_DELAY = 31,
+ CATRAINING_NUM = 6,
+ PASS_RANGE_NA = 0x7fff
+};
+
+enum {
+ CBT_LOW_FREQ = 0,
+ CBT_HIGH_FREQ = 1
+};
+
+enum {
+ CBT_OFF = 0,
+ CBT_ON = 1
+};
+
+enum {
+ GATING_OFF = 0,
+ GATING_ON = 1
+};
+
+enum {
+ CKE_FIXOFF = 0,
+ CKE_FIXON,
+ CKE_DYNAMIC
+};
+
+enum {
+ RANK_SINGLE = 1,
+ RANK_DUAL
+};
+
+enum {
+ GATING_PATTERN_NUM = 0x23,
+ GATING_GOLDEND_DQSCNT = 0x4646
+};
+
+enum {
+ IMPCAL_STAGE_DRVP = 0x1,
+ IMPCAL_STAGE_DRVN,
+ IMPCAL_STAGE_TRACKING,
+};
+
+enum {
+ DQS_GW_COARSE_STEP = 1,
+ DQS_GW_FINE_START = 0,
+ DQS_GW_FINE_END = 32,
+ DQS_GW_FINE_STEP = 4,
+ DQS_GW_FREQ_DIV = 4,
+ RX_DQS_CTL_LOOP = 8,
+ RX_DLY_DQSIENSTB_LOOP = 32
+};
+
+enum {
+ DRAM_DFS_SHUFFLE_1 = 0,
+ DRAM_DFS_SHUFFLE_2,
+ DRAM_DFS_SHUFFLE_3,
+ DRAM_DFS_SHUFFLE_MAX
+};
+
+enum {
+ TYPE_DDR1 = 1,
+ TYPE_LPDDR2,
+ TYPE_LPDDR3,
+ TYPE_PCDDR3,
+ TYPE_LPDDR4,
+ TYPE_LPDDR4X,
+ TYPE_LPDDR4P
+};
+
+enum {
+ AC_TIMING_DRAM_TYPE = 0,
+ AC_TIMING_FREQUENCY,
+ AC_TIMING_DBI_ONOFF,
+ AC_TIMING_BYTE_MODE,
+ AC_TIMING_TRAS,
+ AC_TIMING_TRP,
+ AC_TIMING_TRPAB,
+ AC_TIMING_TRC,
+ AC_TIMING_TRFC,
+ AC_TIMING_TRFCPB,
+ AC_TIMING_TXP,
+ AC_TIMING_TRTP,
+ AC_TIMING_TRCD,
+ AC_TIMING_TWR,
+ AC_TIMING_TWTR,
+ AC_TIMING_TRRD,
+ AC_TIMING_TFAW,
+ AC_TIMING_TRTW_ODT_OFF,
+ AC_TIMING_TRTW_ODT_ON,
+ AC_TIMING_REFCNT,
+ AC_TIMING_REFCNT_FR_CLK,
+ AC_TIMING_TXREFCNT,
+ AC_TIMING_TZQCS,
+ AC_TIMING_TRTPD,
+ AC_TIMING_TWTPD,
+ AC_TIMING_TMRR2W_ODT_OFF,
+ AC_TIMING_TMRR2W_ODT_ON,
+ AC_TIMING_TRAS_05T,
+ AC_TIMING_TRP_05T,
+ AC_TIMING_TRPAB_05T,
+ AC_TIMING_TRC_05T,
+ AC_TIMING_TRFC_05T,
+ AC_TIMING_TRFCPB_05T,
+ AC_TIMING_TXP_05T,
+ AC_TIMING_TRTP_05T,
+ AC_TIMING_TRCD_05T,
+ AC_TIMING_TWR_05T,
+ AC_TIMING_TWTR_05T,
+ AC_TIMING_TRRD_05T,
+ AC_TIMING_TFAW_05T,
+ AC_TIMING_TRTW_05T_ODT_OFF,
+ AC_TIMING_TRTW_05T_ODT_ON,
+ AC_TIMING_TRTPD_05T,
+ AC_TIMING_TWTPD_05T,
+ AC_TIMING_XRTW2W,
+ AC_TIMING_XRTW2R,
+ AC_TIMING_XRTR2W,
+ AC_TIMING_XRTR2R,
+ AC_TIMING_DMCATRAIN_INTV,
+ AC_TIMING_DQSINCTL_FOR_GATING,
+ AC_TIMING_DATLAT,
+ AC_TIMING_MODE_REG_WL,
+ AC_TIMING_MODE_REG_RL,
+ AC_TIMING_ITEM_NUM
+};
+
+enum {
+ SAVE_VALUE,
+ RESTORE_VALUE
+};
+
+void dramc_init(const struct sdram_params *params);
+void get_dram_rank_size(u64 *dram_rank_size);
+void dramc_runtime_config(void);
+void dram_calibration_all_channel(const struct sdram_params *params);
+void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value);
+void dramc_engine2_init(u8 chn, u8 u1RankSel, u32 test2_1, u32 test2_2,
+ u8 testaudpat, u8 log2loopcount);
+u32 dramc_engine2_run(u8 chn, enum dram_te_op wr, u8 testaudpat);
+void dramc_engine2_end(u8 chn);
+void dramc_sw_impedance_save_register(const struct sdram_params *params);
+void dramc_broadcast_onoff(u32 bOnOff);
+u32 get_dramc_broadcast(void);
+void apply_config_before_calibration(void);
+void dramc_gating_mode(u8 chn, u8 mode);
+void dramc_hw_gating_onoff(u8 chn, u8 u1OnOff);
+void dramc_ac_timing_optimize(void);
+void cke_fix_onoff(int option, u8 chn);
+void save_restore_multi_reg(u8 type, u32 **reg_addr, u32 reg_count);
+u8 dramc_zq_calibration(u8 chn, u8 rank);
+void dramc_mode_reg_write_by_rank(u8 chn, u8 rank, u8 mr_idx, u8 value);
+void enable_dramc_phy_dcm(u8 bEn);
+
+#endif /* _DRAMC_PI_API_MT8183_H */
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_register.h b/src/soc/mediatek/mt8183/include/soc/dramc_register.h
new file mode 100644
index 0000000..9ebb5e4
--- /dev/null
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_register.h
@@ -0,0 +1,1446 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DRAMC_REGISTER_H_
+#define _DRAMC_REGISTER_H_
+
+#include <types.h>
+#include <soc/addressmap.h>
+
+struct dramc_no_regs_rk_counter {
+ uint32_t pre_standby_counter;
+ uint32_t pre_powerdown_counter;
+ uint32_t act_standby_counter;
+ uint32_t act_powerdown_counter;
+};
+
+struct dramc_nao_regs_rk {
+ uint32_t dqsosc_status;
+ uint32_t dqsosc_delta;
+ uint32_t dqsosc_delta2;
+ uint32_t rsvd_1[1];
+ uint32_t current_tx_setting1;
+ uint32_t current_tx_setting2;
+ uint32_t current_tx_setting3;
+ uint32_t current_tx_setting4;
+ uint32_t dummy_rd_data[4];
+ uint32_t b0_stb_max_min_dly;
+ uint32_t b1_stb_max_min_dly;
+ uint32_t b2_stb_max_min_dly;
+ uint32_t b3_stb_max_min_dly;
+ uint32_t dqsiendly;
+ uint32_t dqsienuidly;
+ uint32_t dqsienuidly_p1;
+ uint32_t rsvd_2[1];
+ uint32_t dqs_stbcaldec_cnt1;
+ uint32_t dqs_stbcaldec_cnt2;
+ uint32_t dqs_stbcalinc_cnt1;
+ uint32_t dqs_stbcalinc_cnt2;
+ uint32_t fine_tune_dq_cal;
+ uint32_t dqsg_retry_flag;
+ uint32_t fine_tune_dqm_cal;
+ uint32_t rsvd_3[1];
+ uint32_t dqs0_stbcal_cnt;
+ uint32_t dqs1_stbcal_cnt;
+ uint32_t dqs2_stbcal_cnt;
+ uint32_t dqs3_stbcal_cnt;
+ uint32_t b01_stb_dbg_info[16];
+ uint32_t b23_stb_dbg_info[16];
+};
+
+struct dramc_nao_regs {
+ uint32_t testmode;
+ uint32_t lbwdat0;
+ uint32_t lbwdat1;
+ uint32_t lbwdat2;
+ uint32_t lbwdat3;
+ uint32_t reserved0[3];
+ uint32_t ckphchk;
+ uint32_t dmmonitor;
+ uint32_t reserved1[2];
+ uint32_t testchip_dma1;
+ uint32_t reserved2[19];
+ uint32_t misc_statusa;
+ uint32_t special_status;
+ uint32_t spcmdresp;
+ uint32_t mrr_status;
+ uint32_t mrr_status2;
+ uint32_t mrrdata0;
+ uint32_t mrrdata1;
+ uint32_t mrrdata2;
+ uint32_t mrrdata3;
+ uint32_t reserved3[1];
+ uint32_t drs_status;
+ uint32_t reserved4[4];
+ uint32_t jmeter_st;
+ uint32_t tcmdo1lat;
+ uint32_t rdqc_cmp;
+ uint32_t ckphchk_status;
+ uint32_t reserved5[16];
+ uint32_t hwmrr_push2pop_cnt;
+ uint32_t hwmrr_status;
+ uint32_t hw_refrate_mon;
+ uint32_t reserved6[2];
+ uint32_t testrpt;
+ uint32_t cmp_err;
+ uint32_t test_abit_status1;
+ uint32_t test_abit_status2;
+ uint32_t test_abit_status3;
+ uint32_t test_abit_status4;
+ uint32_t reserved7[6];
+ uint32_t dqsdly0;
+ uint32_t dq_cal_max[8];
+ uint32_t dqs_cal_min[8];
+ uint32_t dqs_cal_max[8];
+ uint32_t dqical0;
+ uint32_t dqical1;
+ uint32_t dqical2;
+ uint32_t dqical3;
+ uint32_t reserved8[15];
+ uint32_t testchip_dma_status[34];
+ uint32_t reserved9[30];
+ uint32_t refresh_pop_counter;
+ uint32_t freerun_26m_counter;
+ uint32_t dramc_idle_counter;
+ uint32_t r2r_page_hit_counter;
+ uint32_t r2r_page_miss_counter;
+ uint32_t r2r_interbank_counter;
+ uint32_t r2w_page_hit_counter;
+ uint32_t r2w_page_miss_counter;
+ uint32_t r2w_interbank_counter;
+ uint32_t w2r_page_hit_counter;
+ uint32_t w2r_page_miss_counter;
+ uint32_t w2r_interbank_counter;
+ uint32_t w2w_page_hit_counter;
+ uint32_t w2w_page_miss_counter;
+ uint32_t w2w_interbank_counter;
+ struct dramc_no_regs_rk_counter rk_counter[3];
+ uint32_t dq0_toggle_counter;
+ uint32_t dq1_toggle_counter;
+ uint32_t dq2_toggle_counter;
+ uint32_t dq3_toggle_counter;
+ uint32_t dq0_toggle_counter_r;
+ uint32_t dq1_toggle_counter_r;
+ uint32_t dq2_toggle_counter_r;
+ uint32_t dq3_toggle_counter_r;
+ uint32_t read_bytes_counter;
+ uint32_t write_bytes_counter;
+ uint32_t max_sref_req_to_ack_latency_counter;
+ uint32_t max_rk1_drs_long_req_to_ack_latency_counter;
+ uint32_t max_rk1_drs_req_to_ack_latency_counter;
+ uint32_t reserved10[8];
+ uint32_t lat_counter_cmd[8];
+ uint32_t lat_counter_aver;
+ uint32_t lat_counter_num;
+ uint32_t lat_counter_block_ale;
+ uint32_t reserved11[5];
+ uint32_t dqssamplev;
+ uint32_t reserved12[1];
+ uint32_t dqsgnwcnt[6];
+ uint32_t toggle_cnt;
+ uint32_t dqs0_err_cnt;
+ uint32_t dq_err_cnt0;
+ uint32_t dqs1_err_cnt;
+ uint32_t dq_err_cnt1;
+ uint32_t dqs2_err_cnt;
+ uint32_t dq_err_cnt2;
+ uint32_t dqs3_err_cnt;
+ uint32_t dq_err_cnt3;
+ uint32_t reserved13[3];
+ uint32_t iorgcnt;
+ uint32_t dqsg_retry_state;
+ uint32_t dqsg_retry_state1;
+ uint32_t reserved14[1];
+ uint32_t impcal_status1;
+ uint32_t impcal_status2;
+ uint32_t dqdrv_status;
+ uint32_t cmddrv_status;
+ uint32_t cmddrv1;
+ uint32_t cmddrv2;
+ uint32_t reserved15[98];
+ struct dramc_nao_regs_rk rk[3];
+ uint32_t reserved25[192];
+ uint32_t dvfs_dbg0;
+ uint32_t dvfs_dbg1;
+ uint32_t dramc_nao_regs_end;
+};
+
+check_member(dramc_nao_regs, testmode, 0x0000);
+check_member(dramc_nao_regs, lbwdat0, 0x0004);
+check_member(dramc_nao_regs, lbwdat1, 0x0008);
+check_member(dramc_nao_regs, lbwdat2, 0x000c);
+check_member(dramc_nao_regs, lbwdat3, 0x0010);
+check_member(dramc_nao_regs, ckphchk, 0x0020);
+check_member(dramc_nao_regs, dmmonitor, 0x0024);
+check_member(dramc_nao_regs, testchip_dma1, 0x0030);
+check_member(dramc_nao_regs, misc_statusa, 0x0080);
+check_member(dramc_nao_regs, special_status, 0x0084);
+check_member(dramc_nao_regs, spcmdresp, 0x0088);
+check_member(dramc_nao_regs, mrr_status, 0x008c);
+check_member(dramc_nao_regs, mrr_status2, 0x0090);
+check_member(dramc_nao_regs, mrrdata0, 0x0094);
+check_member(dramc_nao_regs, mrrdata1, 0x0098);
+check_member(dramc_nao_regs, mrrdata2, 0x009c);
+check_member(dramc_nao_regs, mrrdata3, 0x00a0);
+check_member(dramc_nao_regs, drs_status, 0x00a8);
+check_member(dramc_nao_regs, jmeter_st, 0x00bc);
+check_member(dramc_nao_regs, tcmdo1lat, 0x00c0);
+check_member(dramc_nao_regs, rdqc_cmp, 0x00c4);
+check_member(dramc_nao_regs, ckphchk_status, 0x00c8);
+check_member(dramc_nao_regs, hwmrr_push2pop_cnt, 0x010c);
+check_member(dramc_nao_regs, hwmrr_status, 0x0110);
+check_member(dramc_nao_regs, testrpt, 0x0120);
+check_member(dramc_nao_regs, cmp_err, 0x0124);
+check_member(dramc_nao_regs, test_abit_status1, 0x0128);
+check_member(dramc_nao_regs, test_abit_status2, 0x012c);
+check_member(dramc_nao_regs, test_abit_status3, 0x0130);
+check_member(dramc_nao_regs, test_abit_status4, 0x0134);
+check_member(dramc_nao_regs, dqsdly0, 0x0150);
+check_member(dramc_nao_regs, dq_cal_max[0], 0x0154);
+check_member(dramc_nao_regs, dqs_cal_min[0], 0x0174);
+check_member(dramc_nao_regs, dqs_cal_max[0], 0x0194);
+check_member(dramc_nao_regs, dqical0, 0x01b4);
+check_member(dramc_nao_regs, dqical1, 0x01b8);
+check_member(dramc_nao_regs, dqical2, 0x01bc);
+check_member(dramc_nao_regs, dqical3, 0x01c0);
+check_member(dramc_nao_regs, testchip_dma_status[0], 0x0200);
+check_member(dramc_nao_regs, refresh_pop_counter, 0x0300);
+check_member(dramc_nao_regs, freerun_26m_counter, 0x0304);
+check_member(dramc_nao_regs, dramc_idle_counter, 0x0308);
+check_member(dramc_nao_regs, r2r_page_hit_counter, 0x030c);
+check_member(dramc_nao_regs, r2r_page_miss_counter, 0x0310);
+check_member(dramc_nao_regs, r2r_interbank_counter, 0x0314);
+check_member(dramc_nao_regs, r2w_page_hit_counter, 0x0318);
+check_member(dramc_nao_regs, r2w_page_miss_counter, 0x031c);
+check_member(dramc_nao_regs, r2w_interbank_counter, 0x0320);
+check_member(dramc_nao_regs, w2r_page_hit_counter, 0x0324);
+check_member(dramc_nao_regs, w2r_page_miss_counter, 0x0328);
+check_member(dramc_nao_regs, w2r_interbank_counter, 0x032c);
+check_member(dramc_nao_regs, w2w_page_hit_counter, 0x0330);
+check_member(dramc_nao_regs, w2w_page_miss_counter, 0x0334);
+check_member(dramc_nao_regs, w2w_interbank_counter, 0x0338);
+check_member(dramc_nao_regs, dq0_toggle_counter, 0x036c);
+check_member(dramc_nao_regs, dq1_toggle_counter, 0x0370);
+check_member(dramc_nao_regs, dq2_toggle_counter, 0x0374);
+check_member(dramc_nao_regs, dq3_toggle_counter, 0x0378);
+check_member(dramc_nao_regs, dq0_toggle_counter_r, 0x037c);
+check_member(dramc_nao_regs, dq1_toggle_counter_r, 0x0380);
+check_member(dramc_nao_regs, dq2_toggle_counter_r, 0x0384);
+check_member(dramc_nao_regs, dq3_toggle_counter_r, 0x0388);
+check_member(dramc_nao_regs, read_bytes_counter, 0x038c);
+check_member(dramc_nao_regs, write_bytes_counter, 0x0390);
+check_member(dramc_nao_regs, dqssamplev, 0x0400);
+check_member(dramc_nao_regs, dqsgnwcnt[0], 0x0408);
+check_member(dramc_nao_regs, toggle_cnt, 0x0420);
+check_member(dramc_nao_regs, dqs0_err_cnt, 0x0424);
+check_member(dramc_nao_regs, dq_err_cnt0, 0x0428);
+check_member(dramc_nao_regs, dqs1_err_cnt, 0x042c);
+check_member(dramc_nao_regs, dq_err_cnt1, 0x0430);
+check_member(dramc_nao_regs, dqs2_err_cnt, 0x0434);
+check_member(dramc_nao_regs, dq_err_cnt2, 0x0438);
+check_member(dramc_nao_regs, dqs3_err_cnt, 0x043c);
+check_member(dramc_nao_regs, dq_err_cnt3, 0x0440);
+check_member(dramc_nao_regs, iorgcnt, 0x0450);
+check_member(dramc_nao_regs, dqsg_retry_state, 0x0454);
+check_member(dramc_nao_regs, dqsg_retry_state1, 0x0458);
+check_member(dramc_nao_regs, impcal_status1, 0x0460);
+check_member(dramc_nao_regs, impcal_status2, 0x0464);
+check_member(dramc_nao_regs, dqdrv_status, 0x0468);
+check_member(dramc_nao_regs, cmddrv_status, 0x046c);
+check_member(dramc_nao_regs, cmddrv1, 0x0470);
+check_member(dramc_nao_regs, cmddrv2, 0x0474);
+
+struct dramc_ao_regs_rk {
+ uint32_t dqsosc;
+ uint32_t rsvd_1[5];
+ uint32_t dummy_rd_wdata0;
+ uint32_t dummy_rd_wdata1;
+ uint32_t dummy_rd_wdata2;
+ uint32_t dummy_rd_wdata3;
+ uint32_t dummy_rd_adr;
+ uint32_t dummy_rd_bk;
+ uint32_t pre_tdqsck[12];
+ uint32_t rsvd_2[40];
+};
+
+struct dramc_ao_regs_shu_rk {
+ uint32_t dqsctl;
+ uint32_t dqsien;
+ uint32_t dqscal;
+ uint32_t fine_tune;
+ uint32_t dqsosc;
+ uint32_t rsvd_1[2];
+ uint32_t selph_odten0;
+ uint32_t selph_odten1;
+ uint32_t selph_dqsg0;
+ uint32_t selph_dqsg1;
+ uint32_t selph_dq[4];
+ uint32_t rsvd_2[1];
+ uint32_t dqs2dq_cal1;
+ uint32_t dqs2dq_cal2;
+ uint32_t dqs2dq_cal3;
+ uint32_t dqs2dq_cal4;
+ uint32_t dqs2dq_cal5;
+ uint32_t rsvd_3[43];
+};
+
+struct dramc_ao_regs {
+ uint32_t ddrconf0;
+ uint32_t dramctrl;
+ uint32_t misctl0;
+ uint32_t perfctl0;
+ uint32_t arbctl;
+ uint32_t reserved0[2];
+ uint32_t rstmask;
+ uint32_t padctrl;
+ uint32_t ckectrl;
+ uint32_t drsctrl;
+ uint32_t reserved1[2];
+ uint32_t rkcfg;
+ uint32_t dramc_pd_ctrl;
+ uint32_t clkar;
+ uint32_t clkctrl;
+ uint32_t selfref_hwsave_flag;
+ uint32_t srefctrl;
+ uint32_t refctrl0;
+ uint32_t refctrl1;
+ uint32_t refratre_filter;
+ uint32_t zqcs;
+ uint32_t mrs;
+ uint32_t spcmd;
+ uint32_t spcmdctrl;
+ uint32_t ppr_ctrl;
+ uint32_t mpc_option;
+ uint32_t refque_cnt;
+ uint32_t hw_mrr_fun;
+ uint32_t mrr_bit_mux1;
+ uint32_t mrr_bit_mux2;
+ uint32_t mrr_bit_mux3;
+ uint32_t mrr_bit_mux4;
+ uint32_t reserved2[1];
+ uint32_t test2_5;
+ uint32_t test2_0;
+ uint32_t test2_1;
+ uint32_t test2_2;
+ uint32_t test2_3;
+ uint32_t test2_4;
+ uint32_t wdt_dbg_signal;
+ uint32_t reserved3[1];
+ uint32_t lbtest;
+ uint32_t catraining1;
+ uint32_t catraining2;
+ uint32_t reserved4[1];
+ uint32_t write_lev;
+ uint32_t mr_golden;
+ uint32_t slp4_testmode;
+ uint32_t dqsoscr;
+ uint32_t reserved5[1];
+ uint32_t dummy_rd;
+ uint32_t shuctrl;
+ uint32_t shuctrl1;
+ uint32_t shuctrl2;
+ uint32_t shuctrl3;
+ uint32_t shustatus;
+ uint32_t reserved6[70];
+ uint32_t stbcal;
+ uint32_t stbcal1;
+ uint32_t stbcal2;
+ uint32_t eyescan;
+ uint32_t dvfsdll;
+ uint32_t reserved7[1];
+ uint32_t pre_tdqsck[4];
+ uint32_t reserved8[1];
+ uint32_t impcal;
+ uint32_t impedamce_ctrl1;
+ uint32_t impedamce_ctrl2;
+ uint32_t impedamce_ctrl3;
+ uint32_t impedamce_ctrl4;
+ uint32_t dramc_dbg_sel1;
+ uint32_t dramc_dbg_sel2;
+ uint32_t rsvd_10[46];
+ struct dramc_ao_regs_rk rk[3];
+ uint32_t rsvd_16[64];
+ struct {
+ uint32_t rsvd0[64];
+ uint32_t actim[7];
+ uint32_t actim_xrt;
+ uint32_t ac_time_05t;
+ uint32_t ac_derating0;
+ uint32_t ac_derating1;
+ uint32_t rsvd1[1];
+ uint32_t ac_derating_05t;
+ uint32_t rsvd2[3];
+ uint32_t conf[4];
+ uint32_t stbcal;
+ uint32_t dqsoscthrd;
+ uint32_t rankctl;
+ uint32_t ckectrl;
+ uint32_t odtctrl;
+ uint32_t impcal1;
+ uint32_t dqsosc_prd;
+ uint32_t dqsoscr;
+ uint32_t dqsoscr2;
+ uint32_t rodtenstb;
+ uint32_t pipe;
+ uint32_t test1;
+ uint32_t selph_ca1;
+ uint32_t selph_ca2;
+ uint32_t selph_ca3;
+ uint32_t selph_ca4;
+ uint32_t selph_ca5;
+ uint32_t selph_ca6;
+ uint32_t selph_ca7;
+ uint32_t selph_ca8;
+ uint32_t selph_dqs0;
+ uint32_t selph_dqs1;
+ uint32_t drving[6];
+ uint32_t wodt;
+ uint32_t dqsg;
+ uint32_t scintv;
+ uint32_t misc;
+ uint32_t dqs2dq_tx;
+ uint32_t hwset_mr2;
+ uint32_t hwset_mr13;
+ uint32_t hwset_vrcg;
+ uint32_t rsvd3[72];
+ union {
+ struct dramc_ao_regs_shu_rk rk[3];
+ struct {
+ uint32_t rsvd_63[149];
+ uint32_t dqsg_retry;
+ };
+ };
+ } shu[4];
+ uint32_t dramc_ao_regs_end;
+};
+
+check_member(dramc_ao_regs, ddrconf0, 0x0000);
+check_member(dramc_ao_regs, dramctrl, 0x0004);
+check_member(dramc_ao_regs, misctl0, 0x0008);
+check_member(dramc_ao_regs, perfctl0, 0x000c);
+check_member(dramc_ao_regs, arbctl, 0x0010);
+check_member(dramc_ao_regs, rstmask, 0x001c);
+check_member(dramc_ao_regs, padctrl, 0x0020);
+check_member(dramc_ao_regs, ckectrl, 0x0024);
+check_member(dramc_ao_regs, drsctrl, 0x0028);
+check_member(dramc_ao_regs, rkcfg, 0x0034);
+check_member(dramc_ao_regs, dramc_pd_ctrl, 0x0038);
+check_member(dramc_ao_regs, clkar, 0x003c);
+check_member(dramc_ao_regs, clkctrl, 0x0040);
+check_member(dramc_ao_regs, selfref_hwsave_flag, 0x0044);
+check_member(dramc_ao_regs, srefctrl, 0x0048);
+check_member(dramc_ao_regs, refctrl0, 0x004c);
+check_member(dramc_ao_regs, refctrl1, 0x0050);
+check_member(dramc_ao_regs, refratre_filter, 0x0054);
+check_member(dramc_ao_regs, zqcs, 0x0058);
+check_member(dramc_ao_regs, mrs, 0x005c);
+check_member(dramc_ao_regs, spcmd, 0x0060);
+check_member(dramc_ao_regs, spcmdctrl, 0x0064);
+check_member(dramc_ao_regs, ppr_ctrl, 0x0068);
+check_member(dramc_ao_regs, mpc_option, 0x006c);
+check_member(dramc_ao_regs, refque_cnt, 0x0070);
+check_member(dramc_ao_regs, hw_mrr_fun, 0x0074);
+check_member(dramc_ao_regs, mrr_bit_mux1, 0x0078);
+check_member(dramc_ao_regs, mrr_bit_mux2, 0x007c);
+check_member(dramc_ao_regs, mrr_bit_mux3, 0x0080);
+check_member(dramc_ao_regs, mrr_bit_mux4, 0x0084);
+check_member(dramc_ao_regs, test2_5, 0x008c);
+check_member(dramc_ao_regs, test2_0, 0x0090);
+check_member(dramc_ao_regs, test2_1, 0x0094);
+check_member(dramc_ao_regs, test2_2, 0x0098);
+check_member(dramc_ao_regs, test2_3, 0x009c);
+check_member(dramc_ao_regs, test2_4, 0x00a0);
+check_member(dramc_ao_regs, wdt_dbg_signal, 0x00a4);
+check_member(dramc_ao_regs, lbtest, 0x00ac);
+check_member(dramc_ao_regs, catraining1, 0x00b0);
+check_member(dramc_ao_regs, catraining2, 0x00b4);
+check_member(dramc_ao_regs, write_lev, 0x00bc);
+check_member(dramc_ao_regs, mr_golden, 0x00c0);
+check_member(dramc_ao_regs, slp4_testmode, 0x00c4);
+check_member(dramc_ao_regs, dqsoscr, 0x00c8);
+check_member(dramc_ao_regs, dummy_rd, 0x00d0);
+check_member(dramc_ao_regs, shuctrl, 0x00d4);
+check_member(dramc_ao_regs, shuctrl1, 0x00d8);
+check_member(dramc_ao_regs, shuctrl2, 0x00dc);
+check_member(dramc_ao_regs, shuctrl3, 0x00e0);
+check_member(dramc_ao_regs, shustatus, 0x00e4);
+check_member(dramc_ao_regs, stbcal, 0x0200);
+check_member(dramc_ao_regs, stbcal1, 0x0204);
+check_member(dramc_ao_regs, stbcal2, 0x0208);
+check_member(dramc_ao_regs, eyescan, 0x020c);
+check_member(dramc_ao_regs, dvfsdll, 0x0210);
+check_member(dramc_ao_regs, pre_tdqsck[0], 0x0218);
+check_member(dramc_ao_regs, pre_tdqsck[1], 0x021c);
+check_member(dramc_ao_regs, pre_tdqsck[2], 0x0220);
+check_member(dramc_ao_regs, pre_tdqsck[3], 0x0224);
+check_member(dramc_ao_regs, impcal, 0x022c);
+check_member(dramc_ao_regs, impedamce_ctrl1, 0x0230);
+check_member(dramc_ao_regs, impedamce_ctrl2, 0x0234);
+check_member(dramc_ao_regs, impedamce_ctrl3, 0x0238);
+check_member(dramc_ao_regs, impedamce_ctrl4, 0x023c);
+check_member(dramc_ao_regs, dramc_dbg_sel1, 0x0240);
+check_member(dramc_ao_regs, dramc_dbg_sel2, 0x0244);
+check_member(dramc_ao_regs, shu[0].actim[0], 0x0800);
+check_member(dramc_ao_regs, shu[0].actim_xrt, 0x081c);
+check_member(dramc_ao_regs, shu[0].ac_time_05t, 0x0820);
+check_member(dramc_ao_regs, shu[0].ac_derating0, 0x0824);
+check_member(dramc_ao_regs, shu[0].ac_derating1, 0x0828);
+check_member(dramc_ao_regs, shu[0].ac_derating_05t, 0x0830);
+check_member(dramc_ao_regs, shu[0].conf[0], 0x0840);
+check_member(dramc_ao_regs, shu[0].rankctl, 0x0858);
+check_member(dramc_ao_regs, shu[0].ckectrl, 0x085c);
+check_member(dramc_ao_regs, shu[0].odtctrl, 0x0860);
+check_member(dramc_ao_regs, shu[0].impcal1, 0x0864);
+check_member(dramc_ao_regs, shu[0].dqsosc_prd, 0x0868);
+check_member(dramc_ao_regs, shu[0].dqsoscr, 0x086c);
+check_member(dramc_ao_regs, shu[0].dqsoscr2, 0x0870);
+check_member(dramc_ao_regs, shu[0].rodtenstb, 0x0874);
+check_member(dramc_ao_regs, shu[0].pipe, 0x0878);
+check_member(dramc_ao_regs, shu[0].test1, 0x087c);
+check_member(dramc_ao_regs, shu[0].selph_ca1, 0x0880);
+check_member(dramc_ao_regs, shu[0].selph_dqs0, 0x08a0);
+check_member(dramc_ao_regs, shu[0].selph_dqs1, 0x08a4);
+check_member(dramc_ao_regs, shu[0].drving[0], 0x08a8);
+check_member(dramc_ao_regs, shu[0].wodt, 0x08c0);
+check_member(dramc_ao_regs, shu[0].dqsg, 0x08c4);
+check_member(dramc_ao_regs, shu[0].scintv, 0x08c8);
+check_member(dramc_ao_regs, shu[0].misc, 0x08cc);
+check_member(dramc_ao_regs, shu[0].dqs2dq_tx, 0x08d0);
+check_member(dramc_ao_regs, shu[0].hwset_mr2, 0x08d4);
+check_member(dramc_ao_regs, shu[0].hwset_mr13, 0x08d8);
+check_member(dramc_ao_regs, shu[0].hwset_vrcg, 0x08dc);
+check_member(dramc_ao_regs, shu[0].rk[0].dqsctl, 0x0A00);
+check_member(dramc_ao_regs, shu[0].dqsg_retry, 0x0c54);
+check_member(dramc_ao_regs, shu[1].dqsg_retry, 0x1254);
+check_member(dramc_ao_regs, shu[2].dqsg_retry, 0x1854);
+check_member(dramc_ao_regs, shu[3].dqsg_retry, 0x1e54);
+
+struct dramc_ddrphy_regs_misc_stberr_rk {
+ uint32_t r;
+ uint32_t f;
+};
+
+struct dramc_ddrphy_regs_shu_rk {
+ struct {
+ uint32_t dq[8];
+ uint32_t rsvd_20[12];
+ } b[2];
+ uint32_t ca_cmd[10];
+ uint32_t rsvd_22[14];
+};
+
+struct dramc_ddrphy_ao_regs {
+ uint32_t pll1;
+ uint32_t pll2;
+ uint32_t pll3;
+ uint32_t pll4;
+ uint32_t pll5;
+ uint32_t pll6;
+ uint32_t pll7;
+ uint32_t pll8;
+ uint32_t pll9;
+ uint32_t pll10;
+ uint32_t pll11;
+ uint32_t pll12;
+ uint32_t pll13;
+ uint32_t pll14;
+ uint32_t pll15;
+ uint32_t pll16;
+ uint32_t reserved0[16];
+ struct {
+ uint32_t dll_fine_tune[6];
+ uint32_t dq[10];
+ uint32_t _rsvd_0[4];
+ uint32_t tx_mck;
+ uint32_t _rsvd_1[11];
+ } b[2];
+ uint32_t ca_dll_fine_tune[6];
+ uint32_t ca_cmd[11];
+ uint32_t rfu_0x1c4;
+ uint32_t rfu_0x1c8;
+ uint32_t rfu_0x1cc;
+ uint32_t ca_tx_mck;
+ uint32_t reserved3[11];
+ uint32_t misc_extlb[24];
+ uint32_t dvfs_emi_clk;
+ uint32_t misc_vref_ctrl;
+ uint32_t misc_imp_ctrl0;
+ uint32_t misc_imp_ctrl1;
+ uint32_t misc_shu_opt;
+ uint32_t misc_spm_ctrl0;
+ uint32_t misc_spm_ctrl1;
+ uint32_t misc_spm_ctrl2;
+ uint32_t misc_spm_ctrl3;
+ uint32_t misc_cg_ctrl0;
+ uint32_t misc_cg_ctrl1;
+ uint32_t misc_cg_ctrl2;
+ uint32_t misc_cg_ctrl3;
+ uint32_t misc_cg_ctrl4;
+ uint32_t misc_cg_ctrl5;
+ uint32_t misc_ctrl0;
+ uint32_t misc_ctrl1;
+ uint32_t misc_ctrl2;
+ uint32_t misc_ctrl3;
+ uint32_t misc_ctrl4;
+ uint32_t misc_ctrl5;
+ uint32_t misc_extlb_rx[21];
+ uint32_t ckmux_sel;
+ uint32_t reserved4[129];
+ uint32_t misc_stberr_rk0_r;
+ uint32_t misc_stberr_rk0_f;
+ uint32_t misc_stberr_rk1_r;
+ uint32_t misc_stberr_rk1_f;
+ uint32_t misc_stberr_rk2_r;
+ uint32_t misc_stberr_rk2_f;
+ uint32_t reserved5[46];
+ uint32_t misc_rxdvs[3];
+ uint32_t rfu_0x5ec;
+ uint32_t b0_rxdvs[2];
+ uint32_t rfu_0x5f8;
+ uint32_t rfu_0x5fc;
+ union {
+ struct {
+ struct {
+ uint32_t rxdvs[8];
+ uint32_t _rsvd[24];
+ } b[2];
+ uint32_t rxdvs[10];
+ uint32_t _rsvd_b[54];
+ } r[3];
+ struct {
+ uint32_t rsvd_2[28];
+ uint32_t b1_rxdvs[2];
+ uint32_t rsvd_3[30];
+ uint32_t ca_rxdvs0;
+ uint32_t ca_rxdvs1;
+ uint32_t rsvd_4[2];
+ uint32_t r0_ca_rxdvs[10];
+ };
+ };
+
+ struct {
+ struct {
+ uint32_t dq[13];
+ uint32_t dll[2];
+ uint32_t rsvd_16[17];
+ } b[2];
+ uint32_t ca_cmd[13];
+ uint32_t ca_dll[2];
+ uint32_t rsvd_18[17];
+ uint32_t pll[16];
+ uint32_t rsvd_19[4];
+ uint32_t pll20;
+ uint32_t pll21;
+ uint32_t rsvd_20[6];
+ uint32_t misc0;
+ uint32_t rsvd_21[3];
+ struct dramc_ddrphy_regs_shu_rk rk[3];
+ } shu[4];
+};
+
+check_member(dramc_ddrphy_ao_regs, pll1, 0x0000);
+check_member(dramc_ddrphy_ao_regs, b[0].dll_fine_tune[0], 0x0080);
+check_member(dramc_ddrphy_ao_regs, b[0].dq[0], 0x0098);
+check_member(dramc_ddrphy_ao_regs, b[0].tx_mck, 0x00d0);
+check_member(dramc_ddrphy_ao_regs, ca_dll_fine_tune[0], 0x0180);
+check_member(dramc_ddrphy_ao_regs, ca_cmd[0], 0x0198);
+check_member(dramc_ddrphy_ao_regs, ca_tx_mck, 0x01d0);
+check_member(dramc_ddrphy_ao_regs, misc_extlb[0], 0x0200);
+check_member(dramc_ddrphy_ao_regs, dvfs_emi_clk, 0x0260);
+check_member(dramc_ddrphy_ao_regs, misc_vref_ctrl, 0x0264);
+check_member(dramc_ddrphy_ao_regs, misc_imp_ctrl0, 0x0268);
+check_member(dramc_ddrphy_ao_regs, misc_imp_ctrl1, 0x026c);
+check_member(dramc_ddrphy_ao_regs, misc_shu_opt, 0x0270);
+check_member(dramc_ddrphy_ao_regs, misc_spm_ctrl0, 0x0274);
+check_member(dramc_ddrphy_ao_regs, misc_spm_ctrl1, 0x0278);
+check_member(dramc_ddrphy_ao_regs, misc_spm_ctrl2, 0x027c);
+check_member(dramc_ddrphy_ao_regs, misc_spm_ctrl3, 0x0280);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl0, 0x0284);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl1, 0x0288);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl2, 0x028c);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl3, 0x0290);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl4, 0x0294);
+check_member(dramc_ddrphy_ao_regs, misc_cg_ctrl5, 0x0298);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl0, 0x029c);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl1, 0x02a0);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl2, 0x02a4);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl3, 0x02a8);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl4, 0x02ac);
+check_member(dramc_ddrphy_ao_regs, misc_ctrl5, 0x02b0);
+check_member(dramc_ddrphy_ao_regs, misc_extlb_rx[0], 0x02b4);
+check_member(dramc_ddrphy_ao_regs, ckmux_sel, 0x0308);
+check_member(dramc_ddrphy_ao_regs, misc_rxdvs[0], 0x05e0);
+check_member(dramc_ddrphy_ao_regs, misc_rxdvs[1], 0x05e4);
+check_member(dramc_ddrphy_ao_regs, misc_rxdvs[2], 0x05e8);
+check_member(dramc_ddrphy_ao_regs, rfu_0x5ec, 0x05ec);
+check_member(dramc_ddrphy_ao_regs, b0_rxdvs[0], 0x05f0);
+check_member(dramc_ddrphy_ao_regs, r[0].b[0].rxdvs[0], 0x0600);
+check_member(dramc_ddrphy_ao_regs, b1_rxdvs[0], 0x0670);
+check_member(dramc_ddrphy_ao_regs, r[0].b[1].rxdvs[0], 0x0680);
+check_member(dramc_ddrphy_ao_regs, ca_rxdvs0, 0x06F0);
+check_member(dramc_ddrphy_ao_regs, r0_ca_rxdvs[0], 0x0700);
+check_member(dramc_ddrphy_ao_regs, r[1].b[1].rxdvs[0], 0x0880);
+check_member(dramc_ddrphy_ao_regs, r[1].rxdvs[0], 0x0900);
+check_member(dramc_ddrphy_ao_regs, shu[0].b[0].dq[0], 0x0c00);
+check_member(dramc_ddrphy_ao_regs, shu[0].b[1].dq[6], 0x0C98);
+check_member(dramc_ddrphy_ao_regs, shu[0].ca_cmd[0], 0x0d00);
+check_member(dramc_ddrphy_ao_regs, shu[0].ca_dll[0], 0x0d34);
+check_member(dramc_ddrphy_ao_regs, shu[0].pll[0], 0x0d80);
+check_member(dramc_ddrphy_ao_regs, shu[0].misc0, 0x0DF0);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[0].b[0].dq[0], 0x0e00);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[0].ca_cmd[9], 0x0ec4);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[1].b[0].dq[0], 0x0f00);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[1].ca_cmd[9], 0x0fc4);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[2].b[0].dq[0], 0x1000);
+check_member(dramc_ddrphy_ao_regs, shu[0].rk[2].ca_cmd[9], 0x10c4);
+check_member(dramc_ddrphy_ao_regs, shu[2].b[0].dq[0], 0x1600);
+check_member(dramc_ddrphy_ao_regs, shu[2].b[1].dq[0], 0x1680);
+check_member(dramc_ddrphy_ao_regs, shu[2].ca_cmd[0], 0x1700);
+check_member(dramc_ddrphy_ao_regs, shu[2].ca_dll[0], 0x1734);
+check_member(dramc_ddrphy_ao_regs, shu[2].pll[0], 0x1780);
+check_member(dramc_ddrphy_ao_regs, shu[2].misc0, 0x17F0);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[0].b[0].dq[0], 0x1800);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[0].ca_cmd[0], 0x18A0);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[1].b[0].dq[0], 0x1900);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[1].ca_cmd[0], 0x19A0);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[2].b[0].dq[0], 0x1A00);
+check_member(dramc_ddrphy_ao_regs, shu[2].rk[2].ca_cmd[0], 0x1AA0);
+check_member(dramc_ddrphy_ao_regs, shu[3].ca_cmd[0], 0x1C00);
+check_member(dramc_ddrphy_ao_regs, shu[3].pll[0], 0x1C80);
+check_member(dramc_ddrphy_ao_regs, shu[3].pll20, 0x1CD0);
+check_member(dramc_ddrphy_ao_regs, shu[3].misc0, 0x1CF0);
+check_member(dramc_ddrphy_ao_regs, shu[3].rk[0].ca_cmd[9], 0x1DC4);
+check_member(dramc_ddrphy_ao_regs, shu[3].rk[1].ca_cmd[9], 0x1EC4);
+check_member(dramc_ddrphy_ao_regs, shu[3].rk[2].ca_cmd[9], 0x1FC4);
+
+struct dramc_ddrphy_nao_regs {
+ uint32_t misc_sta_extlb[3];
+ uint32_t reserved0[29];
+ uint32_t misc_dq_rxdly_trro[32];
+ uint32_t misc_ca_rxdly_trro[32];
+ uint32_t misc_dqo1;
+ uint32_t misc_cao1;
+ uint32_t misc_ad_rx_dq_o1;
+ uint32_t misc_ad_rx_cmd_o1;
+ uint32_t misc_phy_rgs_dq;
+ uint32_t misc_phy_rgs_cmd;
+ uint32_t misc_phy_stben_b0;
+ uint32_t misc_phy_stben_b1;
+ uint32_t misc_phy_rgs_stben_cmd;
+ uint32_t dramc_ddrphy_nao_regs_end;
+};
+
+check_member(dramc_ddrphy_nao_regs, misc_sta_extlb[0], 0x0);
+check_member(dramc_ddrphy_nao_regs, misc_dq_rxdly_trro[0], 0x080);
+check_member(dramc_ddrphy_nao_regs, misc_dqo1, 0x0180);
+check_member(dramc_ddrphy_nao_regs, misc_cao1, 0x0184);
+check_member(dramc_ddrphy_nao_regs, misc_phy_rgs_dq, 0x0190);
+check_member(dramc_ddrphy_nao_regs, misc_phy_rgs_cmd, 0x0194);
+check_member(dramc_ddrphy_nao_regs, misc_phy_stben_b0, 0x0198);
+check_member(dramc_ddrphy_nao_regs, misc_phy_rgs_stben_cmd, 0x01A0);
+
+struct emi_regs {
+ uint32_t cona;
+ uint32_t reserved0[1];
+ uint32_t conb;
+ uint32_t reserved1[1];
+ uint32_t conc;
+ uint32_t reserved2[1];
+ uint32_t cond;
+ uint32_t reserved3[1];
+ uint32_t cone;
+ uint32_t reserved4[1];
+ uint32_t conf;
+ uint32_t reserved5[1];
+ uint32_t cong;
+ uint32_t reserved6[1];
+ uint32_t conh;
+ uint32_t conh_2nd;
+ uint32_t coni;
+ uint32_t reserved7[1];
+ uint32_t conj;
+ uint32_t reserved8[5];
+ uint32_t conm;
+ uint32_t reserved9[1];
+ uint32_t conn;
+ uint32_t reserved10[1];
+ uint32_t cono;
+ uint32_t reserved11[1];
+ uint32_t mdct;
+ uint32_t mdct_2nd;
+ uint32_t reserved12[20];
+ uint32_t iocl;
+ uint32_t iocl_2nd;
+ uint32_t iocm;
+ uint32_t iocm_2nd;
+ uint32_t reserved13[2];
+ uint32_t testb;
+ uint32_t reserved14[1];
+ uint32_t testc;
+ uint32_t reserved15[1];
+ uint32_t testd;
+ uint32_t reserved16[1];
+ uint32_t arba;
+ uint32_t reserved17[1];
+ uint32_t arbb;
+ uint32_t reserved18[1];
+ uint32_t arbc;
+ uint32_t reserved19[1];
+ uint32_t arbd;
+ uint32_t reserved20[1];
+ uint32_t arbe;
+ uint32_t reserved21[1];
+ uint32_t arbf;
+ uint32_t reserved22[1];
+ uint32_t arbg;
+ uint32_t reserved23[1];
+ uint32_t arbh;
+ uint32_t reserved24[1];
+ uint32_t arbi;
+ uint32_t arbi_2nd;
+ uint32_t reserved25[2];
+ uint32_t arbk;
+ uint32_t arbk_2nd;
+ uint32_t slct;
+ uint32_t reserved26[1];
+ uint32_t mpud_st[32];
+ uint32_t reserved27[4];
+ uint32_t mpus;
+ uint32_t reserved28[1];
+ uint32_t mput;
+ uint32_t mput_2nd;
+ uint32_t d_st2[32];
+ uint32_t reserved29[96];
+ uint32_t bmen;
+ uint32_t bstp;
+ uint32_t bcnt;
+ uint32_t reserved30[1];
+ uint32_t tact;
+ uint32_t reserved31[1];
+ uint32_t tsct;
+ uint32_t reserved32[1];
+ uint32_t wact;
+ uint32_t reserved33[1];
+ uint32_t wsct;
+ uint32_t reserved34[1];
+ uint32_t bact;
+ uint32_t reserved35[1];
+ uint32_t bsct;
+ uint32_t reserved36[1];
+ uint32_t msel;
+ uint32_t reserved37[1];
+ uint32_t tsct2;
+ uint32_t reserved38[1];
+ uint32_t tsct3;
+ uint32_t reserved39[1];
+ uint32_t wsct2;
+ uint32_t reserved40[1];
+ uint32_t wsct3;
+ uint32_t wsct4;
+ uint32_t msel2;
+ uint32_t reserved41[1];
+ uint32_t msel3;
+ uint32_t reserved42[1];
+ uint32_t msel4;
+ uint32_t reserved43[1];
+ uint32_t msel5;
+ uint32_t reserved44[1];
+ uint32_t msel6;
+ uint32_t reserved45[1];
+ uint32_t msel7;
+ uint32_t reserved46[1];
+ uint32_t msel8;
+ uint32_t reserved47[1];
+ uint32_t msel9;
+ uint32_t reserved48[1];
+ uint32_t msel10;
+ uint32_t reserved49[1];
+ uint32_t bmid0;
+ uint32_t bmid1;
+ uint32_t bmid2;
+ uint32_t bmid3;
+ uint32_t bmid4;
+ uint32_t bmid5;
+ uint32_t bmid6;
+ uint32_t bmid7;
+ uint32_t bmid8;
+ uint32_t bmid9;
+ uint32_t bmid10;
+ uint32_t reserved50[1];
+ uint32_t bmen1;
+ uint32_t reserved51[1];
+ uint32_t bmen2;
+ uint32_t reserved52[3];
+ uint32_t bmrw0;
+ uint32_t bmrw1;
+ uint32_t ttype1;
+ uint32_t reserved53[1];
+ uint32_t ttype2;
+ uint32_t reserved54[1];
+ uint32_t ttype3;
+ uint32_t reserved55[1];
+ uint32_t ttype4;
+ uint32_t reserved56[1];
+ uint32_t ttype5;
+ uint32_t reserved57[1];
+ uint32_t ttype6;
+ uint32_t reserved58[1];
+ uint32_t ttype7;
+ uint32_t reserved59[1];
+ uint32_t ttype8;
+ uint32_t reserved60[1];
+ uint32_t ttype9;
+ uint32_t reserved61[1];
+ uint32_t ttype10;
+ uint32_t reserved62[1];
+ uint32_t ttype11;
+ uint32_t reserved63[1];
+ uint32_t ttype12;
+ uint32_t reserved64[1];
+ uint32_t ttype13;
+ uint32_t reserved65[1];
+ uint32_t ttype14;
+ uint32_t reserved66[1];
+ uint32_t ttype15;
+ uint32_t reserved67[1];
+ uint32_t ttype16;
+ uint32_t reserved68[1];
+ uint32_t ttype17;
+ uint32_t reserved69[1];
+ uint32_t ttype18;
+ uint32_t reserved70[1];
+ uint32_t ttype19;
+ uint32_t reserved71[1];
+ uint32_t ttype20;
+ uint32_t reserved72[1];
+ uint32_t ttype21;
+ uint32_t reserved73[3];
+ uint32_t bwct0;
+ uint32_t bwct1;
+ uint32_t bwct2;
+ uint32_t bwct3;
+ uint32_t bwct4;
+ uint32_t bwst0;
+ uint32_t bwst1;
+ uint32_t reserved74[1];
+ uint32_t ex_con;
+ uint32_t ex_st0;
+ uint32_t ex_st1;
+ uint32_t ex_st2;
+ uint32_t wp_adr;
+ uint32_t wp_adr_2nd;
+ uint32_t wp_ctrl;
+ uint32_t reserved75[1];
+ uint32_t chker;
+ uint32_t chker_type;
+ uint32_t chker_adr;
+ uint32_t chker_adr_2nd;
+ uint32_t reserved76[40];
+ uint32_t bwct0_2nd;
+ uint32_t reserved77[43];
+ uint32_t ltct0_2nd;
+ uint32_t ltct1_2nd;
+ uint32_t ltct2_2nd;
+ uint32_t ltct3_2nd;
+ uint32_t reserved78[4];
+ uint32_t bwct0_3rd;
+ uint32_t reserved79[3];
+ uint32_t bwct0_4th;
+ uint32_t reserved80[11];
+ uint32_t bwct0_5th;
+ uint32_t reserved81[19];
+ uint32_t slva;
+};
+
+check_member(emi_regs, cona, 0x0000);
+check_member(emi_regs, conb, 0x0008);
+check_member(emi_regs, conc, 0x0010);
+check_member(emi_regs, cond, 0x0018);
+check_member(emi_regs, cone, 0x0020);
+check_member(emi_regs, conf, 0x0028);
+check_member(emi_regs, cong, 0x0030);
+check_member(emi_regs, conh, 0x0038);
+check_member(emi_regs, conh_2nd, 0x003c);
+check_member(emi_regs, coni, 0x0040);
+check_member(emi_regs, conj, 0x0048);
+check_member(emi_regs, conm, 0x0060);
+check_member(emi_regs, conn, 0x0068);
+check_member(emi_regs, cono, 0x0070);
+check_member(emi_regs, mdct, 0x0078);
+check_member(emi_regs, mdct_2nd, 0x007c);
+check_member(emi_regs, iocl, 0x00d0);
+check_member(emi_regs, iocl_2nd, 0x00d4);
+check_member(emi_regs, iocm, 0x00d8);
+check_member(emi_regs, iocm_2nd, 0x00dc);
+check_member(emi_regs, testb, 0x00e8);
+check_member(emi_regs, testc, 0x00f0);
+check_member(emi_regs, testd, 0x00f8);
+check_member(emi_regs, arba, 0x0100);
+check_member(emi_regs, arbb, 0x0108);
+check_member(emi_regs, arbc, 0x0110);
+check_member(emi_regs, arbd, 0x0118);
+check_member(emi_regs, arbe, 0x0120);
+check_member(emi_regs, arbf, 0x0128);
+check_member(emi_regs, arbg, 0x0130);
+check_member(emi_regs, arbh, 0x0138);
+check_member(emi_regs, arbi, 0x0140);
+check_member(emi_regs, arbi_2nd, 0x0144);
+check_member(emi_regs, slct, 0x0158);
+
+struct chn_emi_regs {
+ uint32_t chn_cona;
+ uint32_t rsvd_1[1];
+ uint32_t chn_conb;
+ uint32_t rsvd_2[1];
+ uint32_t chn_conc;
+ uint32_t rsvd_3[1];
+ uint32_t chn_mdct;
+ uint32_t rsvd_4[11];
+ uint32_t chn_testb;
+ uint32_t rsvd_5[1];
+ uint32_t chn_testc;
+ uint32_t rsvd_6[1];
+ uint32_t chn_testd;
+ uint32_t rsvd_7[9];
+ uint32_t chn_md_pre_mask;
+ uint32_t rsvd_8[1];
+ uint32_t chn_md_pre_mask_shf;
+ uint32_t rsvd_9[45];
+ uint32_t chn_arbi;
+ uint32_t chn_arbi_2nd;
+ uint32_t chn_arbj;
+ uint32_t chn_arbj_2nd;
+ uint32_t chn_arbk;
+ uint32_t chn_arbk_2nd;
+ uint32_t chn_slct;
+ uint32_t chn_arb_ref;
+ uint32_t rsvd_10[20];
+ uint32_t chn_rkarb0;
+ uint32_t chn_rkarb1;
+ uint32_t chn_rkarb2;
+ uint32_t rsvd_11[144];
+ uint32_t chn_eco3;
+ uint32_t rsvd_12[196];
+ uint32_t chn_emi_shf0;
+ uint32_t chn_emi_regs_end;
+
+};
+
+check_member(chn_emi_regs, chn_cona, 0x0000);
+check_member(chn_emi_regs, chn_conb, 0x0008);
+check_member(chn_emi_regs, chn_conc, 0x0010);
+check_member(chn_emi_regs, chn_mdct, 0x0018);
+check_member(chn_emi_regs, chn_testb, 0x0048);
+check_member(chn_emi_regs, chn_testc, 0x0050);
+check_member(chn_emi_regs, chn_testd, 0x0058);
+check_member(chn_emi_regs, chn_md_pre_mask, 0x0080);
+check_member(chn_emi_regs, chn_md_pre_mask_shf, 0x0088);
+check_member(chn_emi_regs, chn_arbi, 0x0140);
+check_member(chn_emi_regs, chn_arbi_2nd, 0x0144);
+check_member(chn_emi_regs, chn_arbj, 0x0148);
+check_member(chn_emi_regs, chn_arbj_2nd, 0x014c);
+check_member(chn_emi_regs, chn_arbk, 0x0150);
+check_member(chn_emi_regs, chn_arbk_2nd, 0x0154);
+check_member(chn_emi_regs, chn_slct, 0x0158);
+check_member(chn_emi_regs, chn_arb_ref, 0x015c);
+check_member(chn_emi_regs, chn_rkarb0, 0x01b0);
+check_member(chn_emi_regs, chn_rkarb1, 0x01b4);
+check_member(chn_emi_regs, chn_rkarb2, 0x01b8);
+check_member(chn_emi_regs, chn_eco3, 0x03fc);
+check_member(chn_emi_regs, chn_emi_shf0, 0x0710);
+
+struct emi_mpu_regs {
+ uint32_t mpu_ctrl;
+ uint32_t mpu_dbg;
+ uint32_t rsvd_2[62];
+ uint32_t mpu_sa0;
+ uint32_t rsvd_3[63];
+ uint32_t mpu_ea0;
+ uint32_t rsvd_4[63];
+ uint32_t mpu_apc0;
+ uint32_t rsvd_5[319];
+ uint32_t mpu_ctrl_d0;
+ uint32_t rsvd_6[63];
+ uint32_t rg_mask_d0;
+};
+
+check_member(emi_mpu_regs, mpu_dbg, 0x0004);
+check_member(emi_mpu_regs, mpu_sa0, 0x0100);
+check_member(emi_mpu_regs, mpu_ea0, 0x0200);
+check_member(emi_mpu_regs, mpu_apc0, 0x0300);
+check_member(emi_mpu_regs, mpu_ctrl_d0, 0x0800);
+check_member(emi_mpu_regs, rg_mask_d0, 0x0900);
+
+enum {
+ TESTCHIP_DMA1_DMA_LP4MATAB_OPT_SHIFT = 12,
+};
+
+enum {
+ MISC_STATUSA_REFRESH_QUEUE_CNT_SHIFT = 24,
+ MISC_STATUSA_REFRESH_QUEUE_CNT_MASK = 0x0f000000,
+};
+
+enum {
+ SPCMDRESP_RDDQC_RESPONSE_SHIFT = 7,
+ SPCMDRESP_ZQLAT_RESPONSE_SHIFT = 6,
+ SPCMDRESP_ZQC_RESPONSE_SHIFT = 4,
+};
+
+enum {
+ TESTRPT_DM_CMP_CPT_RK0_SHIFT = 0,
+};
+
+enum {
+ DDRCONF0_DM4TO1MODE_SHIFT = 22,
+ DDRCONF0_RDATRST_SHIFT = 0,
+};
+
+enum {
+ DRAMCTRL_ADRDECEN_TARKMODE_SHIFT = 1,
+};
+
+enum {
+ PERFCTL0_RWOFOEN_SHIFT = 4,
+};
+
+enum {
+ RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM_SHIFT = 12,
+};
+
+enum {
+ PADCTRL_DQIENLATEBEGIN_SHIFT = 3,
+ PADCTRL_DQIENQKEND_SHIFT = 0,
+ PADCTRL_DQIENQKEND_MASK = 0x00000003,
+};
+
+enum {
+ RKCFG_RKSWAP_SHIFT = 7,
+ RKCFG_RKMODE_SHIFT = 4,
+ RKCFG_RKMODE_MASK = 0x00000070,
+ RKCFG_TXRANKFIX_SHIFT = 3,
+ RKCFG_TXRANK_SHIFT = 0,
+ RKCFG_TXRANK_MASK = 0x00000003,
+};
+enum {
+ REFCTRL0_REFDIS_SHIFT = 29,
+ REFCTRL0_PBREFEN_SHIFT = 18,
+};
+
+enum {
+ MRS_MPCRK_SHIFT = 28,
+ MRS_MPCRK_MASK = 0x30000000,
+ MRS_MRSRK_SHIFT = 24,
+ MRS_MRSRK_MASK = 0x03000000,
+ MRS_MRSMA_SHIFT = 8,
+ MRS_MRSMA_MASK = 0x001fff00,
+ MRS_MRSOP_SHIFT = 0,
+ MRS_MRSOP_MASK = 0x000000ff,
+};
+
+enum {
+ SPCMD_DQSGCNTRST_SHIFT = 9,
+ SPCMD_DQSGCNTEN_SHIFT = 8,
+ SPCMD_RDDQCEN_SHIFT = 7,
+ SPCMD_ZQLATEN_SHIFT = 6,
+ SPCMD_ZQCEN_SHIFT = 4,
+ SPCMD_MRWEN_SHIFT = 0,
+};
+
+enum {
+ SPCMDCTRL_RDDQCDIS_SHIFT = 11,
+};
+
+enum {
+ MPC_OPTION_MPCRKEN_SHIFT = 17,
+};
+
+enum {
+ TEST2_0_PAT0_SHIFT = 8,
+ TEST2_0_PAT0_MASK = 0x0000ff00,
+ TEST2_0_PAT1_SHIFT = 0,
+ TEST2_0_PAT1_MASK = 0x000000ff,
+};
+
+enum {
+ TEST2_3_TEST2W_SHIFT = 31,
+ TEST2_3_TEST2R_SHIFT = 30,
+ TEST2_3_TEST1_SHIFT = 29,
+ TEST2_3_TESTAUDPAT_SHIFT = 7,
+ TEST2_3_TESTCNT_SHIFT = 0,
+ TEST2_3_TESTCNT_MASK = 0x0000000f,
+};
+
+enum {
+ TEST2_4_TESTAGENTRKSEL_MASK = 0x70000000,
+ TEST2_4_TESTAGENTRK_SHIFT = 24,
+ TEST2_4_TESTAGENTRK_MASK = 0x03000000,
+ TEST2_4_TEST_REQ_LEN1_SHIFT = 17,
+ TEST2_4_TESTXTALKPAT_SHIFT = 16,
+ TEST2_4_TESTAUDMODE_SHIFT = 15,
+ TEST2_4_TESTAUDBITINV_SHIFT = 14,
+ TEST2_4_TESTAUDINIT_SHIFT = 8,
+ TEST2_4_TESTAUDINIT_MASK = 0x00001f00,
+ TEST2_4_TESTSSOXTALKPAT_SHIFT = 7,
+ TEST2_4_TESTSSOPAT_SHIFT = 6,
+ TEST2_4_TESTAUDINC_SHIFT = 0,
+ TEST2_4_TESTAUDINC_MASK = 0x0000001f,
+};
+
+enum {
+ MR_GOLDEN_MR15_GOLDEN_MASK = 0x0000ff00,
+ MR_GOLDEN_MR20_GOLDEN_MASK = 0x000000ff,
+};
+
+enum {
+ DQSOSCR_AR_COARSE_TUNE_DQ_SW_SHIFT = 7,
+};
+
+enum {
+ DUMMY_RD_DQSG_DMYWR_EN_SHIFT = 23,
+ DUMMY_RD_DQSG_DMYRD_EN_SHIFT = 22,
+ DUMMY_RD_SREF_DMYRD_EN_SHIFT = 21,
+ DUMMY_RD_DUMMY_RD_EN_SHIFT = 20,
+ DUMMY_RD_DMY_RD_DBG_SHIFT = 7,
+ DUMMY_RD_DMY_WR_DBG_SHIFT = 6,
+};
+
+enum {
+ SHUCTRL2_R_DVFS_OPTION_SHIFT = 15,
+ SHUCTRL2_R_DVFS_PARK_N_SHIFT = 14,
+};
+
+enum {
+ STBCAL_DQSIENMODE_SELPH_SHIFT = 30,
+ STBCAL_STBCALEN_SHIFT = 24,
+ STBCAL_STB_SELPHYCALEN_SHIFT = 22,
+};
+
+enum {
+ STBCAL1_STBCNT_LATCH_EN_SHIFT = 11,
+ STBCAL1_STBENCMPEN_SHIFT = 10,
+ STBCAL1_DQSIEN_7_COARSE_TUNE_EN_SHIFT = 5,
+};
+
+enum {
+ SHU_ACTIM_XRT_XRTR2R_SHIFT = 0,
+ SHU_ACTIM_XRT_XRTR2R_MASK = 0x0000000f,
+};
+
+enum {
+ SHU_CONF1_DATLAT_DSEL_PHY_SHIFT = 26,
+ SHU_CONF1_DATLAT_DSEL_PHY_MASK = 0x7c000000,
+ SHU_CONF1_DATLAT_DSEL_SHIFT = 8,
+ SHU_CONF1_DATLAT_DSEL_MASK = 0x00001f00,
+ SHU_CONF1_DATLAT_SHIFT = 0,
+ SHU_CONF1_DATLAT_MASK = 0x0000001f,
+};
+
+enum {
+ SHU_RANKCTL_RANKINCTL_PHY_SHIFT = 28,
+ SHU_RANKCTL_RANKINCTL_PHY_MASK = 0xf0000000,
+ SHU_RANKCTL_RANKINCTL_ROOT1_SHIFT = 24,
+ SHU_RANKCTL_RANKINCTL_ROOT1_MASK = 0x0f000000,
+ SHU_RANKCTL_RANKINCTL_SHIFT = 20,
+ SHU_RANKCTL_RANKINCTL_MASK = 0x00f00000,
+};
+
+enum {
+ SHU_ODTCTRL_RODT_SHIFT = 4,
+ SHU_ODTCTRL_RODT_MASK = 0x000000f0,
+};
+
+enum {
+ SHU1_WODT_DBIWR_SHIFT = 29,
+};
+
+enum {
+ SHURK_DQSCTL_DQSINCTL_SHIFT = 0,
+ SHURK_DQSCTL_DQSINCTL_MASK = 0x0000000f,
+};
+
+enum {
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1_SHIFT = 12,
+ SHURK_SELPH_ODTEN0_TXDLY_B1_RODTEN_SHIFT = 8,
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1_SHIFT = 4,
+ SHURK_SELPH_ODTEN0_TXDLY_B0_RODTEN_SHIFT = 0,
+};
+
+enum {
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_P1_SHIFT = 12,
+ SHURK_SELPH_ODTEN1_DLY_B1_RODTEN_SHIFT = 8,
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_P1_SHIFT = 4,
+ SHURK_SELPH_ODTEN1_DLY_B0_RODTEN_SHIFT = 0,
+};
+
+enum {
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1_SHIFT = 12,
+ SHURK_SELPH_DQSG0_TX_DLY_DQS1_GATED_SHIFT = 8,
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_SHIFT = 4,
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1_MASK = 0x00000070,
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_SHIFT = 0,
+ SHURK_SELPH_DQSG0_TX_DLY_DQS0_GATED_MASK = 0x00000007,
+};
+
+enum {
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1_SHIFT = 12,
+ SHURK_SELPH_DQSG1_REG_DLY_DQS1_GATED_SHIFT = 8,
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1_SHIFT = 4,
+ SHURK_SELPH_DQSG1_REG_DLY_DQS0_GATED_SHIFT = 0,
+};
+
+enum {
+ B0_DQ5_RG_RX_ARDQ_VREF_EN_B0_SHIFT = 16,
+};
+
+enum {
+ B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0_SHIFT = 14,
+ B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0_MASK = 0x0000c000,
+ B0_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B0_SHIFT = 5,
+};
+
+enum {
+ B1_DQ5_RG_RX_ARDQ_VREF_EN_B1_SHIFT = 16,
+};
+
+enum {
+ B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1_SHIFT = 14,
+ B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1_MASK = 0x0000c000,
+ B1_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B1_SHIFT = 5,
+};
+
+enum {
+ MISC_CTRL1_R_DMSTBENCMP_RK_OPT_SHIFT = 25,
+ MISC_CTRL1_R_DMAR_FINE_TUNE_DQ_SW_SHIFT = 7,
+ MISC_CTRL1_R_DMPHYRST_SHIFT = 1,
+};
+
+enum {
+ MISC_STBERR_RK_R_STBERR_RK_R_MASK = 0x0000ffff,
+};
+
+enum {
+ MISC_STBERR_RK_F_STBERR_RK_F_MASK = 0x0000ffff,
+};
+
+enum {
+ SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0_SHIFT = 0,
+ SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0_MASK = 0x0000003f,
+};
+
+enum {
+ SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0_SHIFT = 7,
+ SHU1_B0_DQ7_R_DMRANKRXDVS_B0_SHIFT = 0,
+ SHU1_B0_DQ7_R_DMRANKRXDVS_B0_MASK = 0x0000000f,
+};
+
+enum {
+ SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1_SHIFT = 0,
+ SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1_MASK = 0x0000003f,
+};
+
+enum {
+ SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1_SHIFT = 7,
+ SHU1_B1_DQ7_R_DMRANKRXDVS_B1_SHIFT = 0,
+ SHU1_B1_DQ7_R_DMRANKRXDVS_B1_MASK = 0x0000000f,
+};
+
+enum {
+ SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE_SHIFT = 12,
+ SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE_MASK = 0x00007000,
+};
+
+enum {
+ SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_SHIFT = 10,
+ SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_MASK = 0x00000c00,
+};
+
+enum {
+ SHU1_B0_DQ6_RK_RX_ARDQS0_F_DLY_B0_MASK = 0x7f000000,
+ SHU1_B0_DQ6_RK_RX_ARDQS0_R_DLY_B0_MASK = 0x007f0000,
+ SHU1_B0_DQ6_RK_RX_ARDQM0_F_DLY_B0_MASK = 0x00003f00,
+ SHU1_B0_DQ6_RK_RX_ARDQM0_R_DLY_B0_MASK = 0x0000003f,
+};
+
+enum {
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_PBYTE_B0_SHIFT = 24,
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_PBYTE_B0_MASK = 0x3f000000,
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_SHIFT = 16,
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQM_B0_MASK = 0x003f0000,
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_SHIFT = 8,
+ SHU1_B0_DQ7_RK_ARFINE_TUNE_DQ_B0_MASK = 0x00003f00,
+};
+
+enum {
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_PBYTE_B1_SHIFT = 24,
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_PBYTE_B1_MASK = 0x3f000000,
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_SHIFT = 16,
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQM_B1_MASK = 0x003f0000,
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_SHIFT = 8,
+ SHU1_B1_DQ7_RK_ARFINE_TUNE_DQ_B1_MASK = 0x00003f00,
+};
+
+enum {
+ SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CLK_SHIFT = 24,
+ SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CLK_MASK = 0x3f000000,
+ SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CS_MASK = 0x0000003f,
+};
+
+enum {
+ SHU1_R2_B1_DQ1_RK2_TX_ARDQS0_DLY_B1_SHIFT = 24,
+ SHU1_R2_B1_DQ1_RK2_TX_ARDQS0_DLY_B1_MASK = 0x0f000000,
+ SHU1_R2_B1_DQ1_RK2_TX_ARDQM0_DLY_B1_SHIFT = 0,
+ SHU1_R2_B1_DQ1_RK2_TX_ARDQM0_DLY_B1_MASK = 0x0000000f,
+};
+
+enum {
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_PBYTE_B1_SHIFT = 24,
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_PBYTE_B1_MASK = 0x3f000000,
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_DQM_B1_SHIFT = 16,
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_DQM_B1_MASK = 0x003f0000,
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_DQ_B1_SHIFT = 8,
+ SHU1_R2_B1_DQ7_RK2_ARFINE_TUNE_DQ_B1_MASK = 0x00003f00,
+};
+
+struct dramc_channel_regs {
+ union {
+ struct dramc_ddrphy_ao_regs phy;
+ uint8_t size_ddrphy_ao_regs[0x2000];
+ };
+
+ union {
+ struct dramc_ao_regs ao;
+ uint8_t size_ao_regs[0x2000];
+ };
+
+ union {
+ struct dramc_nao_regs nao;
+ uint8_t size_nao_regs[0x1000];
+ };
+
+ union {
+ struct chn_emi_regs emi;
+ uint8_t size_emi_regs[0x1000];
+ };
+
+ union {
+ struct dramc_ddrphy_nao_regs phy_nao;
+ uint8_t size_ddrphy_nao_regs[0x2000];
+ };
+};
+
+static struct dramc_channel_regs *const ch = (void *)DRAMC_CH_BASE;
+static struct emi_mpu_regs *const emi_mpu = (void *)EMI_MPU_BASE;
+
+#endif /* _DRAMC_REGISTER_H_ */
diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h
index edc27a8..5969450 100644
--- a/src/soc/mediatek/mt8183/include/soc/emi.h
+++ b/src/soc/mediatek/mt8183/include/soc/emi.h
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright 2018 MediaTek Inc.
+ * Copyright 2017 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,7 +18,26 @@

#include <stdint.h>
#include <types.h>
+#include <soc/dramc_common_mt8183.h>

+struct sdram_params {
+ u32 impedance[2][4];
+ u8 wr_level[CHANNEL_NUM][RANK_MAX][DQS_NUMBER];
+ u8 cbt_cs[CHANNEL_NUM][RANK_MAX];
+ u8 cbt_mr12[CHANNEL_NUM][RANK_MAX];
+ s8 clk_delay;
+ s8 dqs_delay[CHANNEL_NUM];
+ u32 EMI_CONA_VAL;
+ u32 EMI_CONH_VAL;
+ u32 EMI_CONF_VAL;
+ u32 CHN_EMI_CONA_VAL[CHANNEL_NUM];
+ u32 cbt_mode_extern;
+};
+
+int complex_mem_test(u8 *start, unsigned int len);
size_t sdram_size(void);
+const struct sdram_params *get_sdram_config(void);
+void mt_set_emi(const struct sdram_params *params);
+void mt_mem_init(const struct sdram_params *params);

-#endif
+#endif /* SOC_MEDIATEK_MT8183_EMI_H */
diff --git a/src/soc/mediatek/mt8183/include/soc/memlayout.ld b/src/soc/mediatek/mt8183/include/soc/memlayout.ld
index f148eed..2a6d42d 100644
--- a/src/soc/mediatek/mt8183/include/soc/memlayout.ld
+++ b/src/soc/mediatek/mt8183/include/soc/memlayout.ld
@@ -39,7 +39,7 @@
SRAM_END(0x00120000)

SRAM_L2C_START(0x00200000)
- OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 92K)
+ OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 110K)
BOOTBLOCK(0x00227000, 89K)
VERSTAGE(0x0023E000, 114K)
SRAM_L2C_END(0x00280000)
diff --git a/src/soc/mediatek/mt8183/memory.c b/src/soc/mediatek/mt8183/memory.c
new file mode 100644
index 0000000..7fee8b8
--- /dev/null
+++ b/src/soc/mediatek/mt8183/memory.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <assert.h>
+#include <console/console.h>
+#include <soc/dramc_pi_api.h>
+#include <soc/emi.h>
+#include <symbols.h>
+
+void mt_mem_init(const struct sdram_params *params)
+{
+ u64 rank_size[RANK_MAX];
+
+ /* memory calibration */
+ mt_set_emi(params);
+
+ if (IS_ENABLED(CONFIG_MEMORY_TEST)) {
+ size_t r;
+ u8 *addr = _dram;
+
+ get_dram_rank_size(&rank_size[0]);
+
+ for (r = RANK_0; r < RANK_MAX; r++) {
+ int i;
+
+ if (rank_size[r] == 0)
+ break;
+
+ i = complex_mem_test(addr, 0x2000);
+
+ printk(BIOS_DEBUG, "[MEM] complex R/W mem test %s : %d\n",
+ (i == 0) ? "pass" : "fail", i);
+
+ ASSERT(i == 0);
+
+ addr += rank_size[r];
+ }
+ }
+}
diff --git a/src/soc/mediatek/mt8183/pll.c b/src/soc/mediatek/mt8183/pll.c
index e0dd388..b099e99 100644
--- a/src/soc/mediatek/mt8183/pll.c
+++ b/src/soc/mediatek/mt8183/pll.c
@@ -280,6 +280,35 @@
setbits_le32(pll->div_reg, PLL_PCW_CHG);
}

+static void mem_pll_init(void)
+{
+ unsigned int tmp;
+
+ /* CLKSQ Enable */
+ setbits_le32(&mtk_apmixed->ap_pll_con0, 0x85);
+ udelay(100);
+
+ /* CLKSQ LPF Enable */
+ setbits_le32(&mtk_apmixed->ap_pll_con0, 0x87);
+ udelay(1);
+
+ /* power on MPLL */
+ setbits_le32(&mtk_apmixed->mpll_pwr_con0, 0x3);
+ udelay(1);
+
+ /* turn off ISO of MPLL */
+ setbits_le32(&mtk_apmixed->mpll_pwr_con0, 0x1);
+ udelay(1);
+ tmp = read32(&mtk_apmixed->mpll_con1);
+
+ /* Config MPLL freq */
+ setbits_le32(&mtk_apmixed->mpll_con1, tmp | 0x80000000);
+
+ /* enable MPLL */
+ setbits_le32(&mtk_apmixed->mpll_con0, 0x181);
+ udelay(20);
+}
+
void mt_pll_init(void)
{
int i;
@@ -348,4 +377,6 @@

/* enable [14] dramc_pll104m_ck */
setbits_le32(&mtk_topckgen->clk_misc_cfg_0, 1 << 14);
+
+ mem_pll_init();
}

To view, visit change 28437. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaaa1db170c168a58b020095ae45d98355d8dfcb0
Gerrit-Change-Number: 28437
Gerrit-PatchSet: 1
Gerrit-Owner: Tristan Hsieh <tristan.shieh@mediatek.com>