Tristan Hsieh has uploaded this change for review. ( https://review.coreboot.org/28838
Change subject: mediatek/mt8183: Add DDR driver of pre-calibration part ......................................................................
mediatek/mt8183: Add DDR driver of pre-calibration part
BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui, and inits DRAM successfully with related patches.
Change-Id: If462126df31468ef55ec52e2061b9f98d3015f61 Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/Makefile.inc A src/soc/mediatek/mt8183/dramc_pi_calibration_api.c M src/soc/mediatek/mt8183/emi.c M src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h 4 files changed, 213 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/38/28838/1
diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc index e9b5f42..ec2a9c0 100644 --- a/src/soc/mediatek/mt8183/Makefile.inc +++ b/src/soc/mediatek/mt8183/Makefile.inc @@ -22,6 +22,7 @@
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-y += ../common/gpio.c gpio.c romstage-y += ../common/mmu_operations.c mmu_operations.c 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..c5ec9c7 --- /dev/null +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -0,0 +1,205 @@ +/* + * 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 <delay.h> +#include <arch/io.h> +#include <soc/emi.h> +#include <soc/dramc_register.h> +#include <soc/dramc_pi_api.h> + +static void dramc_read_dbi_onoff(u8 onoff) +{ + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) + for (u8 b = 0; b < 2; b++) + clrsetbits_le32(&ch[chn].phy.shu[0].b[b].dq[7], + 0x1 << SHU1_BX_DQ7_R_DMDQMDBI_SHU_SHIFT, + onoff << SHU1_BX_DQ7_R_DMDQMDBI_SHU_SHIFT); +} + +static void dramc_write_dbi_onoff(u8 onoff) +{ + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) + clrsetbits_le32(&ch[chn].ao.shu[0].wodt, + 0x1 << SHU1_WODT_DBIWR_SHIFT, + onoff << SHU1_WODT_DBIWR_SHIFT); +} + +static void enable_dramc_phy_dcm_2_channel(u8 chn, u8 en) +{ + u8 shu, shu_cnt = DRAM_DFS_SHUFFLE_MAX; + + if (!en) { + clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl0, + (0x1 << 20) | (0x1 << 19) | 0x3FF << 8, + (0x0 << 20) | (0x1 << 19) | 0x3FF << 8); + + for (shu = 0; 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)); + } +} + +static void dramc_enable_phy_dcm(u8 en) +{ + u32 broadcast_bak = dramc_get_broadcast(); + u8 shu, shu_cnt = DRAM_DFS_SHUFFLE_MAX; + u8 chn = 0; + + dramc_set_broadcast(DRAMC_BROADCAST_OFF); + + for (chn = 0; chn < CHANNEL_MAX ; 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); + } + + clrsetbits_le32(&ch[chn].ao.dramc_pd_ctrl, + (0x1 << 0) | (0x1 << 1) | (0x1 << 2) | + (0x1 << 5) | (0x1 << 26) | (0x1 << 30) | (0x1 << 31), + ((en ? 0x1 : 0) << 0) | ((en ? 0x1 : 0) << 1) | + ((en ? 0x1 : 0) << 2) | ((en ? 0 : 0x1) << 5) | + ((en ? 0 : 0x1) << 26) | ((en ? 0x1 : 0) << 30) | + ((en ? 0x1 : 0) << 31)); + + /* DCM on :CHANNEL_EMI free run ; DCM off :mem_dcm */ + assert(en == 0 || en == 1); + write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060033E | (0x40 << en)); + write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060033F | (0x40 << en)); + write32(&ch[chn].phy.misc_cg_ctrl2, 0x8060033E | (0x40 << en)); + + clrsetbits_le32(&ch[chn].phy.misc_ctrl3, 0x3 << 26, + (en ? 0 : 0x3) << 26); + for (shu = 0; shu < shu_cnt; shu++) { + clrsetbits_le32(&ch[chn].phy.shu[shu].b[0].dq[7], + 0x7 << 17, (en ? 0x7 : 0) << 17); + clrsetbits_le32(&ch[chn].phy.shu[shu].b[1].dq[7], + 0x7 << 17, (en ? 0x7 : 0) << 17); + clrsetbits_le32(&ch[chn].phy.shu[shu].ca_cmd[7], + 0x7 << 17, (en ? 0x7 : 0) << 17); + } + } + enable_dramc_phy_dcm_2_channel(chn, en); + dramc_set_broadcast(broadcast_bak); +} + +static void reset_delay_chain_before_calibration(void) +{ + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) + for (u8 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); + } +} + +static void dramc_hw_gating_onoff(u8 chn, u8 onoff) +{ + clrsetbits_le32(&ch[chn].ao.shuctrl2, 0x3 << 14, + (onoff << 14) | (onoff << 15)); + clrsetbits_le32(&ch[chn].ao.stbcal2, 0x1 << 28, onoff << 28); + clrsetbits_le32(&ch[chn].ao.stbcal, 0x1 << 24, onoff << 24); + clrsetbits_le32(&ch[chn].ao.stbcal, 0x1 << 22, onoff << 22); +} + +static void dramc_rx_input_delay_tracking_init_by_freq(u8 chn) +{ + u8 delay = 3; + clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[5], 0x7 << 20, delay << 20); + clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[5], 0x7 << 20, delay << 20); + clrsetbits_le32(&ch[chn].phy.shu[0].b[0].dq[7], + (0x1 << 12) | (0x1 << 13), (0x0 << 12) | (0x0 << 13)); + clrsetbits_le32(&ch[chn].phy.shu[0].b[1].dq[7], + (0x1 << 12) | (0x1 << 13), (0x0 << 12) | (0x0 << 13)); +} + +void dramc_apply_pre_calibration_config(void) +{ + u8 shu = 0; + + dramc_enable_phy_dcm(0); + reset_delay_chain_before_calibration(); + + setbits_le32(&ch[0].ao.shu[0].conf[3], 0x1ff << 16); + setbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 24); + clrsetbits_le32(&ch[0].ao.shu[0].scintv, 0x1f << 1, 0x1b << 1); + + for (shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + setbits_le32(&ch[0].ao.shu[shu].conf[3], 0x1ff << 0); + + clrbits_le32(&ch[0].ao.dramctrl, 0x1 << 18); + clrbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 31); + clrbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 30); + clrbits_le32(&ch[0].ao.dqsoscr, 0x1 << 26); + clrbits_le32(&ch[0].ao.dqsoscr, 0x1 << 25); + + dramc_write_dbi_onoff(DBI_OFF); + dramc_read_dbi_onoff(DBI_OFF); + + for (int chn = 0; chn < CHANNEL_MAX; chn++) { + setbits_le32(&ch[chn].ao.spcmdctrl, 0x1 << 29); + setbits_le32(&ch[chn].ao.dqsoscr, 0x1 << 24); + for (shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + setbits_le32(&ch[chn].ao.shu[shu].scintv, 0x1 << 30); + + clrbits_le32(&ch[chn].ao.dummy_rd, (0x1 << 7) | (0x7 << 20)); + dramc_hw_gating_onoff(chn, GATING_OFF); + clrbits_le32(&ch[chn].ao.stbcal2, 0x1 << 28); + + setbits_le32(&ch[chn].phy.misc_ctrl1, + (0x1 << 7) | (0x1 << 11)); + clrbits_le32(&ch[chn].ao.refctrl0, 0x1 << 18); + clrbits_le32(&ch[chn].ao.mrs, 0x3 << 24); + setbits_le32(&ch[chn].ao.mpc_option, 0x1 << 17); + clrsetbits_le32(&ch[chn].phy.b[0].dq[6], 0x3 << 0, 0x1 << 0); + clrsetbits_le32(&ch[chn].phy.b[1].dq[6], 0x3 << 0, 0x1 << 0); + clrsetbits_le32(&ch[chn].phy.ca_cmd[6], 0x3 << 0, 0x1 << 0); + 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); + + dramc_rx_input_delay_tracking_init_by_freq(chn); + } + + for (size_t r = 0; r < 2; r++) { + for (size_t b = 0; b < 2; b++) + clrbits_le32(&ch[0].phy.r[r].b[b].rxdvs[2], + (0x1 << 28) | (0x1 << 23) | (0x3 << 30)); + clrbits_le32(&ch[0].phy.r0_ca_rxdvs[2], 0x3 << 30); + } +} + diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 37997aa..ba913a2 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -293,7 +293,13 @@ emi_init2(params); }
+static void do_calib(const struct sdram_params *params) +{ + dramc_apply_pre_calibration_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/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h index af96316..ed9eb81 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -138,4 +138,5 @@ void dramc_set_broadcast(u32 onoff); u32 dramc_get_broadcast(void); void dramc_sw_impedance(const struct sdram_params *params); +void dramc_apply_pre_calibration_config(void); #endif /* _DRAMC_PI_API_MT8183_H */