diff options
-rw-r--r-- | src/soc/mediatek/mt8183/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/dramc_pi_basic_api.c | 111 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/emi.c | 1 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h | 6 |
4 files changed, 119 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc index 944c9b1d18..e2076839de 100644 --- a/src/soc/mediatek/mt8183/Makefile.inc +++ b/src/soc/mediatek/mt8183/Makefile.inc @@ -25,6 +25,7 @@ verstage-y += ../common/wdt.c romstage-y += auxadc.c romstage-y += ../common/cbmem.c emi.c romstage-y += dramc_init_setting.c +romstage-y += dramc_pi_basic_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_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c new file mode 100644 index 0000000000..2cb0db2f1b --- /dev/null +++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c @@ -0,0 +1,111 @@ +/* + * 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/emi.h> +#include <soc/dramc_register.h> +#include <soc/dramc_pi_api.h> + +static void sw_imp_cal_vref_sel(u8 term_option, u8 impcal_stage) +{ + u8 vref_sel = 0; + + if (term_option == 1) + vref_sel = IMP_LP4X_TERM_VREF_SEL; + else { + switch (impcal_stage) { + case IMPCAL_STAGE_DRVP: + vref_sel = IMP_DRVP_LP4X_UNTERM_VREF_SEL; + break; + case IMPCAL_STAGE_DRVN: + vref_sel = IMP_DRVN_LP4X_UNTERM_VREF_SEL; + break; + default: + vref_sel = IMP_TRACK_LP4X_UNTERM_VREF_SEL; + break; + } + } + + clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], 0x3f << 8, vref_sel << 8); +} + +void dramc_sw_impedance(const struct sdram_params *params) +{ + u8 term = 0, ca_term = ODT_OFF, dq_term = ODT_ON; + u32 sw_impedance[2][4] = {0}; + + for (term = 0; term < 2; term++) + for (u8 i = 0; i < 4; i++) + sw_impedance[term][i] = params->impedance[term][i]; + + sw_impedance[ODT_OFF][2] = sw_impedance[ODT_ON][2]; + sw_impedance[ODT_OFF][3] = sw_impedance[ODT_ON][3]; + + clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], 0xff, 0x3); + sw_imp_cal_vref_sel(dq_term, IMPCAL_STAGE_DRVP); + + /* DQ */ + clrsetbits_le32(&ch[0].ao.shu[0].drving[0], (0x1f << 5) | (0x1f << 0), + (sw_impedance[dq_term][0] << 5) | + (sw_impedance[dq_term][1] << 0)); + clrsetbits_le32(&ch[0].ao.shu[0].drving[1], + (0x1f << 25)|(0x1f << 20) | (1 << 31), + (sw_impedance[dq_term][0] << 25) | + (sw_impedance[dq_term][1] << 20) | (!dq_term << 31)); + clrsetbits_le32(&ch[0].ao.shu[0].drving[2], (0x1f << 5) | (0x1f << 0), + (sw_impedance[dq_term][2] << 5) | + (sw_impedance[dq_term][3] << 0)); + clrsetbits_le32(&ch[0].ao.shu[0].drving[3], (0x1f << 25) | (0x1f << 20), + (sw_impedance[dq_term][2] << 25) | + (sw_impedance[dq_term][3] << 20)); + + /* DQS */ + for (u8 i = 0; i <= 2; i += 2) { + clrsetbits_le32(&ch[0].ao.shu[0].drving[i], + (0x1f << 25) | (0x1f << 20), + (sw_impedance[dq_term][i] << 25) | + (sw_impedance[dq_term][i + 1] << 20)); + clrsetbits_le32(&ch[0].ao.shu[0].drving[i], + (0x1f << 15) | (0x1f << 10), + (sw_impedance[dq_term][i] << 15) | + (sw_impedance[dq_term][i + 1] << 10)); + } + + /* CMD & CLK */ + for (u8 i = 1; i <= 3; i += 2) { + clrsetbits_le32(&ch[0].ao.shu[0].drving[i], + (0x1f << 15) | (0x1f << 10), + (sw_impedance[ca_term][i - 1] << 15) | + (sw_impedance[ca_term][i] << 10)); + clrsetbits_le32(&ch[0].ao.shu[0].drving[i], + (0x1f << 5) | (0x1f << 0), + (sw_impedance[ca_term][i - 1] << 5) | + (sw_impedance[ca_term][i] << 0)); + } + + clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], 0x1f << 17, + sw_impedance[ca_term][0] << 17); + clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], 0x1f << 22, + sw_impedance[ca_term][1] << 22); + + clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[3], + SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_MASK, + 1 << SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE_SHIFT); + clrbits_le32(&ch[0].phy.shu[0].ca_cmd[0], + SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE_MASK); + + clrsetbits_le32(&ch[0].phy.shu[0].ca_dll[1], 0x1f << 16, 0x9 << 16); +} diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 286c87253a..811e1303ab 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -280,6 +280,7 @@ static void init_dram(const struct sdram_params *params) dramc_set_broadcast(DRAMC_BROADCAST_ON); dramc_init_pre_settings(); + dramc_sw_impedance(params); dramc_init(); emi_init2(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 ecdff82bc8..e4300891ec 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -39,6 +39,11 @@ #define DRAMC_BROADCAST_OFF 0x0 #define MAX_BACKUP_REG_CNT 32 +#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 dram_te_op { TE_OP_WRITE_READ_CHECK = 0, TE_OP_READ_CHECK @@ -133,4 +138,5 @@ void dramc_get_rank_size(u64 *dram_rank_size); void dramc_set_broadcast(u32 onoff); u32 dramc_get_broadcast(void); void dramc_init(void); +void dramc_sw_impedance(const struct sdram_params *params); #endif /* _DRAMC_PI_API_MT8183_H */ |