From 69177c92519a3b6d3c495e2feafb1134215c07d4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 8 Oct 2020 19:38:57 +0200 Subject: [PATCH] software/liblitesdram: add initial support for write leveling bitslip (configurable via bios commands). --- litex/soc/software/bios/cmds/cmd_litedram.c | 64 ++++++++++++++++++++- litex/soc/software/liblitedram/sdram.c | 45 ++++++++++++--- litex/soc/software/liblitedram/sdram.h | 2 + 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/litex/soc/software/bios/cmds/cmd_litedram.c b/litex/soc/software/bios/cmds/cmd_litedram.c index 1d9d51997..b4f804d57 100644 --- a/litex/soc/software/bios/cmds/cmd_litedram.c +++ b/litex/soc/software/bios/cmds/cmd_litedram.c @@ -165,7 +165,7 @@ static void sdram_rst_dat_delay_handler(int nb_params, char **params) sdram_write_leveling_rst_dat_delay(module, 1); sdram_software_control_off(); } -define_command(sdram_rst_dat_delay, sdram_rst_dat_delay_handler, "Force write leveling Dat delay", LITEDRAM_CMDS); +define_command(sdram_rst_dat_delay, sdram_rst_dat_delay_handler, "Reset write leveling Dat delay", LITEDRAM_CMDS); #endif /** @@ -198,7 +198,67 @@ static void sdram_force_dat_delay_handler(int nb_params, char **params) sdram_write_leveling_force_dat_delay(module, taps, 1); sdram_software_control_off(); } -define_command(sdram_force_dat_delay, sdram_force_dat_delay_handler, "Reset write leveling Dat delay", LITEDRAM_CMDS); +define_command(sdram_force_dat_delay, sdram_force_dat_delay_handler, "Force write leveling Dat delay", LITEDRAM_CMDS); +#endif + +/** + * Command "sdram_rst_bitslip" + * + * Reset write leveling Bitslip + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +static void sdram_rst_bitslip_handler(int nb_params, char **params) +{ + char *c; + int module; + if (nb_params < 1) { + printf("sdram_rst_bitslip "); + return; + } + module = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect module"); + return; + } + sdram_software_control_on(); + sdram_write_leveling_rst_bitslip(module, 1); + sdram_software_control_off(); +} +define_command(sdram_rst_bitslip, sdram_rst_bitslip_handler, "Reset write leveling Bitslip", LITEDRAM_CMDS); +#endif + +/** + * Command "sdram_force_bitslip" + * + * Force write leveling Bitslip + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +static void sdram_force_bitslip_handler(int nb_params, char **params) +{ + char *c; + int module; + int bitslip; + if (nb_params < 2) { + printf("sdram_force_bitslip "); + return; + } + module = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect module"); + return; + } + bitslip = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect bitslip"); + return; + } + sdram_software_control_on(); + sdram_write_leveling_force_bitslip(module, bitslip, 1); + sdram_software_control_off(); +} +define_command(sdram_force_bitslip, sdram_force_bitslip_handler, "Force write leveling Bitslip", LITEDRAM_CMDS); #endif #endif diff --git a/litex/soc/software/liblitedram/sdram.c b/litex/soc/software/liblitedram/sdram.c index 852c37104..5cf6cb387 100644 --- a/litex/soc/software/liblitedram/sdram.c +++ b/litex/soc/software/liblitedram/sdram.c @@ -243,6 +243,7 @@ void sdram_mode_register_write(char reg, int value) { int _sdram_write_leveling_cmd_scan = 1; int _sdram_write_leveling_cmd_delay = 0; int _sdram_write_leveling_dat_delays[16]; +int _sdram_write_leveling_bitslips[16]; static void sdram_write_leveling_on(void) { @@ -305,6 +306,18 @@ void sdram_write_leveling_force_dat_delay(int module, int taps, int show) { printf("Forcing Dat delay of module %d to %d taps\n", module, taps); } +void sdram_write_leveling_rst_bitslip(int module, int show) { + _sdram_write_leveling_bitslips[module] = -1; + if (show) + printf("Reseting Bitslip of module %d\n", module); +} + +void sdram_write_leveling_force_bitslip(int module, int bitslip, int show) { + _sdram_write_leveling_bitslips[module] = bitslip; + if (show) + printf("Forcing Bitslip of module %d to %d\n", module, bitslip); +} + static void sdram_write_leveling_rst_delay(int module) { #ifdef SDRAM_PHY_WRITE_LEVELING_REINIT int i; @@ -506,8 +519,25 @@ int sdram_write_leveling(void) int cdly_range_start; int cdly_range_end; int cdly_range_step; + int i, j; + /* Configure write bitslips */ + for (i=0; i<16; i++) { + /* sel module */ + ddrphy_dly_sel_write(1 << i); + /* rst bitslip */ + ddrphy_wdly_dq_bitslip_rst_write(1); + /* set bitslip */ + if (_sdram_write_leveling_bitslips[i] >= 0) { + for (j=0; j<_sdram_write_leveling_bitslips[i]; j++) { + ddrphy_wdly_dq_bitslip_write(1); + } + } + /* unsel module */ + ddrphy_dly_sel_write(0); + } + if (_sdram_write_leveling_cmd_scan) { printf(" Cmd/Clk scan:\n"); @@ -580,7 +610,7 @@ static void sdram_read_leveling_rst_delay(int module) { #ifdef SDRAM_PHY_ECP5DDRPHY /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ - ddrphy_dly_sel_write(0xFF); + ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); #endif } @@ -597,7 +627,7 @@ static void sdram_read_leveling_inc_delay(int module) { #ifdef SDRAM_PHY_ECP5DDRPHY /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ - ddrphy_dly_sel_write(0xFF); + ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); #endif } @@ -607,7 +637,7 @@ static void sdram_read_leveling_rst_bitslip(char m) /* sel module */ ddrphy_dly_sel_write(1 << m); - /* inc delay */ + /* rst delay */ ddrphy_rdly_dq_bitslip_rst_write(1); /* unsel module */ @@ -675,9 +705,9 @@ static int sdram_read_leveling_scan_module(int module, int bitslip) command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); for(p=0;p