diff --git a/nubus-to-ztex-gateware/DeclROM/.gitignore b/nubus-to-ztex-gateware/DeclROM/.gitignore index cb2c4e8..6581f3f 100644 --- a/nubus-to-ztex-gateware/DeclROM/.gitignore +++ b/nubus-to-ztex-gateware/DeclROM/.gitignore @@ -8,3 +8,4 @@ vid_decl_rom.srec VidRom* NuBusFPGADrvr*.s NuBusFPGARAMDskDrvr*.s +*.o diff --git a/nubus-to-ztex-gateware/DeclROM/Makefile b/nubus-to-ztex-gateware/DeclROM/Makefile index 51cb0f2..edfcea3 100644 --- a/nubus-to-ztex-gateware/DeclROM/Makefile +++ b/nubus-to-ztex-gateware/DeclROM/Makefile @@ -18,7 +18,7 @@ APPLEINCS=${NS816DECLROMDIR}/atrap.inc ${NS816DECLROMDIR}/declrom.inc ${NS816DEC HRES=1920 VRES=1080 -CSRC_VIDEO=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c NuBusFPGAPrimaryInit_Primary.c NuBusFPGASecondaryInit_Secondary.c +CSRC_VIDEO=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c NuBusFPGAPrimaryInit_Primary.c NuBusFPGAPrimaryInit_RamInit.c NuBusFPGASecondaryInit_Secondary.c CSRC_RAMDSK=NuBusFPGARAMDskDrvr_OpenClose.c NuBusFPGARAMDskDrvr_Ctrl.c NuBusFPGARAMDskDrvr_Prime.c NuBusFPGARAMDskDrvr_Status.c myrle.c CSRC=${CSRC_VIDEO} ${CSRC_RAMDSK} CSRC_ASM=${CSRC:.c=.s} diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr.h b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr.h index 520a028..fa5969f 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr.h +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr.h @@ -139,6 +139,7 @@ OSErr cNuBusFPGAClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ /* primary init */ UInt32 Primary(SEBlock* block) __attribute__ ((section (".text.primary"))); +int sdram_init(uint32_t a32) __attribute__ ((section (".text.primary"))); /* secondary init */ UInt32 Secondary(SEBlock* seblock) __attribute__ ((section (".text.secondary"))); diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c index 2943f5e..6ad3db1 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c @@ -64,6 +64,9 @@ OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) dStore->irqen = 0; dStore->slot = dce->dCtlSlot; + /* initialize DRAM controller */ + //sdram_init(0xF0000000 | (((unsigned long)dStore->slot) << 24)); + /* Get the HW setting for native resolution */ dStore->hres[0] = __builtin_bswap32((unsigned int)read_reg(dce, GOBOFB_HRES)); // fixme: endianness dStore->vres[0] = __builtin_bswap32((unsigned int)read_reg(dce, GOBOFB_VRES)); // fixme: endianness diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_Primary.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_Primary.c index d28ec71..55b031d 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_Primary.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_Primary.c @@ -32,6 +32,9 @@ UInt32 Primary(SEBlock* seblock) { hres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_HRES)); // fixme: endianness vres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_VRES)); // fixme: endianness + + /* initialize DRAM controller */ + sdram_init(a32); /* grey the screen */ /* should switch to HW ? */ @@ -148,3 +151,5 @@ UInt32 Primary(SEBlock* seblock) { return 0; } +/* SDRAM INIT */ + diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_RamInit.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_RamInit.c new file mode 100644 index 0000000..1e337bf --- /dev/null +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_RamInit.c @@ -0,0 +1,650 @@ +#include "NuBusFPGADrvr.h" + +#define CONFIG_CSR_DATA_WIDTH 32 + +#include "../nubusfpga_csr_ddrphy.h" +#include "../nubusfpga_csr_sdram.h" + +/* auto-generated sdram_phy.h + sc */ +#define DFII_CONTROL_SEL 0x01 +#define DFII_CONTROL_CKE 0x02 +#define DFII_CONTROL_ODT 0x04 +#define DFII_CONTROL_RESET_N 0x08 + +#define DFII_COMMAND_CS 0x01 +#define DFII_COMMAND_WE 0x02 +#define DFII_COMMAND_CAS 0x04 +#define DFII_COMMAND_RAS 0x08 +#define DFII_COMMAND_WRDATA 0x10 +#define DFII_COMMAND_RDDATA 0x20 + +#define SDRAM_PHY_A7DDRPHY +#define SDRAM_PHY_XDR 2 +#define SDRAM_PHY_DATABITS 16 +#define SDRAM_PHY_PHASES 4 +#define SDRAM_PHY_CL 6 +#define SDRAM_PHY_CWL 5 +#define SDRAM_PHY_CMD_LATENCY 0 +#define SDRAM_PHY_RDPHASE 2 +#define SDRAM_PHY_WRPHASE 3 +#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE +#define SDRAM_PHY_READ_LEVELING_CAPABLE +#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8 +#define SDRAM_PHY_DELAYS 32 +#define SDRAM_PHY_BITSLIPS 8 + +__attribute__ ((section (".text.primary"))) static void cdelay(int i); + +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_rst_delay (uint32_t a32, int module); +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_inc_delay (uint32_t a32, int module); + +__attribute__ ((section (".text.primary"))) static inline void command_p0(uint32_t a32, int cmd) +{ + sdram_dfii_pi0_command_write(a32, cmd); + sdram_dfii_pi0_command_issue_write(a32, 1); +} +__attribute__ ((section (".text.primary"))) static inline void command_p1(uint32_t a32, int cmd) +{ + sdram_dfii_pi1_command_write(a32, cmd); + sdram_dfii_pi1_command_issue_write(a32, 1); +} +__attribute__ ((section (".text.primary"))) static inline void command_p2(uint32_t a32, int cmd) +{ + sdram_dfii_pi2_command_write(a32, cmd); + sdram_dfii_pi2_command_issue_write(a32, 1); +} +__attribute__ ((section (".text.primary"))) static inline void command_p3(uint32_t a32, int cmd) +{ + sdram_dfii_pi3_command_write(a32, cmd); + sdram_dfii_pi3_command_issue_write(a32, 1); +} + +#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE + +__attribute__ ((section (".text.primary"))) static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase) +{ + switch (phase) { + case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR; + case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR; + case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR; + case 3: return CSR_SDRAM_DFII_PI3_WRDATA_ADDR; + default: return 0; + } +} + +__attribute__ ((section (".text.primary"))) static inline unsigned long sdram_dfii_pix_rddata_addr(int phase) +{ + switch (phase) { + case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR; + case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR; + case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR; + case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR; + default: return 0; + } +} + +#define DDRX_MR_WRLVL_ADDRESS 1 +#define DDRX_MR_WRLVL_RESET 6 +#define DDRX_MR_WRLVL_BIT 7 + +__attribute__ ((section (".text.primary"))) static inline void init_sequence(uint32_t a32) +{ + /* Release reset */ + sdram_dfii_pi0_address_write(a32, 0x0); + sdram_dfii_pi0_baddress_write(a32, 0); + sdram_dfii_control_write(a32, DFII_CONTROL_ODT|DFII_CONTROL_RESET_N); + cdelay(50000); + + /* Bring CKE high */ + sdram_dfii_pi0_address_write(a32, 0x0); + sdram_dfii_pi0_baddress_write(a32, 0); + sdram_dfii_control_write(a32, DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N); + cdelay(10000); + + /* Load Mode Register 2, CWL=5 */ + sdram_dfii_pi0_address_write(a32, 0x200); + sdram_dfii_pi0_baddress_write(a32, 2); + command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + + /* Load Mode Register 3 */ + sdram_dfii_pi0_address_write(a32, 0x0); + sdram_dfii_pi0_baddress_write(a32, 3); + command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + + /* Load Mode Register 1 */ + sdram_dfii_pi0_address_write(a32, 0x6); + sdram_dfii_pi0_baddress_write(a32, 1); + command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + + /* Load Mode Register 0, CL=6, BL=8 */ + sdram_dfii_pi0_address_write(a32, 0x920); + sdram_dfii_pi0_baddress_write(a32, 0); + command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS); + cdelay(200); + + /* ZQ Calibration */ + sdram_dfii_pi0_address_write(a32, 0x400); + sdram_dfii_pi0_baddress_write(a32, 0); + command_p0(a32, DFII_COMMAND_WE|DFII_COMMAND_CS); + cdelay(200); +} + +#include "nubusfpga_csr_common.h" + +/* sdram.c from liblitedram, preprocessed for our case, + sc */ + +__attribute__ ((section (".text.primary"))) static inline unsigned long +lfsr (unsigned long bits, unsigned long prev) +{ + /*static*/ const unsigned long long lfsr_taps[] = { + 0x0L, + 0x0L, + 0x3L, + 0x6L, + 0xcL, + 0x14L, + 0x30L, + 0x60L, + 0xb8L, + 0x110L, + 0x240L, + 0x500L, + 0x829L, + 0x100dL, + 0x2015L, + 0x6000L, + 0xd008L, + 0x12000L, + 0x20400L, + 0x40023L, + 0x90000L, + 0x140000L, + 0x300000L, + 0x420000L, + 0xe10000L, + 0x1200000L, + 0x2000023L, + 0x4000013L, + 0x9000000L, + 0x14000000L, + 0x20000029L, + 0x48000000L, + 0x80200003L, + 0x100080000L, + 0x204000003L, + 0x500000000L, + 0x801000000L, + 0x100000001fL, + 0x2000000031L, + 0x4400000000L, + 0xa000140000L, + 0x12000000000L, + 0x300000c0000L, + 0x63000000000L, + 0xc0000030000L, + 0x1b0000000000L, + 0x300003000000L, + 0x420000000000L, + 0xc00000180000L, + 0x1008000000000L, + 0x3000000c00000L, + 0x6000c00000000L, + 0x9000000000000L, + 0x18003000000000L, + 0x30000000030000L, + 0x40000040000000L, + 0xc0000600000000L, + 0x102000000000000L, + 0x200004000000000L, + 0x600003000000000L, + 0xc00000000000000L, + 0x1800300000000000L, + 0x3000000000000030L, + 0x6000000000000000L, + 0x800000000000000dL + }; + unsigned long lsb = prev & 1; + prev >>= 1; + prev ^= (-lsb) & lfsr_taps[bits]; + return prev; +} + +__attribute__ ((section (".text.primary"))) +static void cdelay (int i) +{ + //i >>= 2; + while (i > 0) { + __asm__ volatile (""); + i--; + } +} + +__attribute__ ((section (".text.primary"))) static unsigned char +sdram_dfii_get_rdphase(uint32_t a32) +{ + return ddrphy_rdphase_read(a32); +} +__attribute__ ((section (".text.primary"))) static unsigned char +sdram_dfii_get_wrphase(uint32_t a32) +{ + return ddrphy_wrphase_read(a32); +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_pix_address_write(uint32_t a32, unsigned char phase, unsigned int value) +{ + switch (phase) { + case 3: + sdram_dfii_pi3_address_write(a32, value); + break; + case 2: + sdram_dfii_pi2_address_write(a32, value); + break; + case 1: + sdram_dfii_pi1_address_write(a32, value); + break; + default: + sdram_dfii_pi0_address_write(a32, value); + } +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_pird_address_write(uint32_t a32, unsigned int value) +{ + unsigned char rdphase = sdram_dfii_get_rdphase(a32); + sdram_dfii_pix_address_write(a32, rdphase, value); +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_piwr_address_write(uint32_t a32, unsigned int value) +{ + unsigned char wrphase = sdram_dfii_get_wrphase(a32); + sdram_dfii_pix_address_write(a32, wrphase, value); +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_pix_baddress_write(uint32_t a32, unsigned char phase, unsigned int value) +{ + switch (phase) { + case 3: + sdram_dfii_pi3_baddress_write(a32, value); + break; + case 2: + sdram_dfii_pi2_baddress_write(a32, value); + break; + case 1: + sdram_dfii_pi1_baddress_write(a32, value); + break; + default: + sdram_dfii_pi0_baddress_write(a32, value); + } +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_pird_baddress_write(uint32_t a32, unsigned int value) +{ + unsigned char rdphase = sdram_dfii_get_rdphase(a32); + sdram_dfii_pix_baddress_write(a32, rdphase, value); +} +__attribute__ ((section (".text.primary"))) static void +sdram_dfii_piwr_baddress_write(uint32_t a32, unsigned int value) +{ + unsigned char wrphase = sdram_dfii_get_wrphase(a32); + sdram_dfii_pix_baddress_write(a32, wrphase, value); +} +__attribute__ ((section (".text.primary"))) static void +command_px(uint32_t a32, unsigned char phase, unsigned int value) +{ + switch (phase) { + case 3: + command_p3(a32, value); + break; + case 2: + command_p2(a32, value); + break; + case 1: + command_p1(a32, value); + break; + default: + command_p0(a32, value); + } +} +__attribute__ ((section (".text.primary"))) static void +command_prd(uint32_t a32, unsigned int value) +{ + unsigned char rdphase = sdram_dfii_get_rdphase(a32); + command_px(a32, rdphase, value); +} +__attribute__ ((section (".text.primary"))) static void +command_pwr (uint32_t a32, unsigned int value) +{ + unsigned char wrphase = sdram_dfii_get_wrphase(a32); + command_px(a32, wrphase, value); +} +__attribute__ ((section (".text.primary"))) static void +sdram_software_control_on(uint32_t a32) +{ + unsigned int previous; + previous = sdram_dfii_control_read(a32); + if (previous != (0x02 | 0x04 | 0x08)) { + sdram_dfii_control_write(a32, (0x02 | 0x04 | 0x08)); + } +} +__attribute__ ((section (".text.primary"))) static void +sdram_software_control_off(uint32_t a32) +{ + unsigned int previous; + previous = sdram_dfii_control_read(a32); + if (previous != (0x01)) { + sdram_dfii_control_write(a32, (0x01)); + } +} +__attribute__ ((section (".text.primary"))) static void +sdram_mode_register_write(uint32_t a32, char reg, int value) +{ + sdram_dfii_pi0_address_write(a32, value); + sdram_dfii_pi0_baddress_write(a32, reg); + command_p0(a32, 0x08 | 0x04 | 0x02 | 0x01); +} + +//typedef void (*delay_callback) (uint32_t a32, int module); + +__attribute__ ((section (".text.primary"))) static void +sdram_activate_test_row(uint32_t a32) +{ + sdram_dfii_pi0_address_write(a32, 0); + sdram_dfii_pi0_baddress_write(a32, 0); + command_p0(a32, 0x08 | 0x01); + cdelay (15); +} +__attribute__ ((section (".text.primary"))) static void +sdram_precharge_test_row(uint32_t a32) +{ + sdram_dfii_pi0_address_write(a32, 0); + sdram_dfii_pi0_baddress_write(a32, 0); + command_p0(a32, 0x08 | 0x02 | 0x01); + cdelay (15); +} + +__attribute__ ((section (".text.primary"))) static unsigned int +popcount (unsigned int x) +{ + x -= ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += (x >> 8); + x += (x >> 16); + return x & 0x0000003F; +} + +__attribute__ ((section (".text.primary"))) static unsigned int +sdram_write_read_check_test_pattern (uint32_t a32, int module, unsigned int seed) +{ + int p, i; + unsigned int errors; + unsigned int prv; + unsigned char tst[1 * 32 / 8]; + unsigned char prs[4][1 * 32 / 8]; + prv = seed; + for (p = 0; p < 4; p++) { + for (i = 0; i < 1 * 32 / 8; i++) { + prv = lfsr (32, prv); + prs[p][i] = prv; + } + } + sdram_activate_test_row(a32); + for (p = 0; p < 4; p++) + csr_wr_buf_uint8(a32, (sdram_dfii_pix_wrdata_addr (p)/* - CSR_SDRAM_BASE*/), prs[p], 1 * 32 / 8); /* cleanme */ + sdram_dfii_piwr_address_write(a32, 0); + sdram_dfii_piwr_baddress_write(a32, 0); + command_pwr(a32, 0x04 | 0x02 | 0x01 | 0x10); + cdelay (15); + sdram_dfii_pird_address_write(a32, 0); + sdram_dfii_pird_baddress_write(a32, 0); + command_prd(a32, 0x04 | 0x01 | 0x20); + cdelay (15); + sdram_precharge_test_row(a32); + errors = 0; + for (p = 0; p < 4; p++) { + csr_rd_buf_uint8(a32, (sdram_dfii_pix_rddata_addr (p)/* - CSR_SDRAM_BASE*/), tst, 1 * 32 / 8); /* cleanme */ + errors += + popcount (prs[p][16 / 8 - 1 - module] ^ tst[16 / 8 - 1 - module]); + errors += + popcount (prs[p][2 * 16 / 8 - 1 - module] ^ + tst[2 * 16 / 8 - 1 - module]); + } + return errors; +} +__attribute__ ((section (".text.primary"))) static void +sdram_leveling_center_module (uint32_t a32, int module, int show_short, int show_long) +/* , + delay_callback rst_delay, + delay_callback inc_delay) */ +{ + int i; + int show; + int working; + unsigned int errors; + int delay, delay_mid, delay_range; + int delay_min = -1, delay_max = -1; + + delay = 0; + //rst_delay(a32, module); + sdram_read_leveling_rst_delay(a32, module); + while (1) { + errors = sdram_write_read_check_test_pattern(a32, module, 42); + errors += sdram_write_read_check_test_pattern(a32, module, 84); + working = errors == 0; + show = show_long; + + if (working && delay_min < 0) { + delay_min = delay; + break; + } + delay++; + if (delay >= 32) + break; + //inc_delay(a32, module); + sdram_read_leveling_inc_delay(a32, module); + } + delay++; + //inc_delay(a32, module); + sdram_read_leveling_inc_delay(a32, module); + while (1) { + errors = sdram_write_read_check_test_pattern(a32, module, 42); + errors += sdram_write_read_check_test_pattern(a32, module, 84); + working = errors == 0; + show = show_long; + + if (!working && delay_max < 0) { + delay_max = delay; + } + delay++; + if (delay >= 32) + break; + //inc_delay(a32, module); + sdram_read_leveling_inc_delay(a32, module); + } + if (delay_max < 0) { + delay_max = delay; + } + + delay_mid = (delay_min + delay_max) / 2 % 32; + delay_range = (delay_max - delay_min) / 2; + +//delay_mid = 25; + + //rst_delay(a32, module); + sdram_read_leveling_rst_delay(a32, module); + cdelay (100); + for (i = 0; i < delay_mid; i++) { + //inc_delay(a32, module); + sdram_read_leveling_inc_delay(a32, module); + cdelay (100); + } +} + +//__attribute__ ((section (".data.primary"))) int _sdram_write_leveling_bitslips[16]; + +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_rst_delay (uint32_t a32, int module) +{ + ddrphy_dly_sel_write(a32, 1 << module); + ddrphy_rdly_dq_rst_write(a32, 1); + ddrphy_dly_sel_write(a32, 0); +} +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_inc_delay (uint32_t a32, int module) +{ + ddrphy_dly_sel_write(a32, 1 << module); + ddrphy_rdly_dq_inc_write(a32, 1); + ddrphy_dly_sel_write(a32, 0); +} +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_rst_bitslip (uint32_t a32, char m) +{ + ddrphy_dly_sel_write(a32, 1 << m); + ddrphy_rdly_dq_bitslip_rst_write(a32, 1); + ddrphy_dly_sel_write(a32, 0); +} +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling_inc_bitslip (uint32_t a32, char m) +{ + ddrphy_dly_sel_write(a32, 1 << m); + ddrphy_rdly_dq_bitslip_write(a32, 1); + ddrphy_dly_sel_write(a32, 0); +} +__attribute__ ((section (".text.primary"))) static unsigned int +sdram_read_leveling_scan_module (uint32_t a32, int module, int bitslip, int show) +{ + const unsigned int max_errors = 2 * (4 * 2 * 32); + int i; + unsigned int score; + unsigned int errors; + score = 0; + + sdram_read_leveling_rst_delay(a32, module); + for (i = 0; i < 32; i++) { + int working; + int _show = show; + errors = sdram_write_read_check_test_pattern(a32, module, 42); + errors += sdram_write_read_check_test_pattern(a32, module, 84); + working = (errors == 0) ? 1 : 0; + score += (working * max_errors * 32) + (max_errors - errors); + + sdram_read_leveling_inc_delay(a32, module); + } + return score; +} +__attribute__ ((section (".text.primary"))) static void +sdram_read_leveling(uint32_t a32) +{ + int module; + int bitslip; + unsigned int score; + unsigned int best_score; + int best_bitslip; + for (module = 0; module < 16 / 8; module++) { + best_score = 0; + best_bitslip = 0; + sdram_read_leveling_rst_bitslip(a32, module); + for (bitslip = 0; bitslip < 8; bitslip++) { + score = sdram_read_leveling_scan_module(a32, module, bitslip, 1); + sdram_leveling_center_module(a32, module, 1, 0); + /*, + sdram_read_leveling_rst_delay, + sdram_read_leveling_inc_delay);*/ + if (score > best_score) { + best_bitslip = bitslip; + best_score = score; + } + if (bitslip == 8 - 1) + break; + sdram_read_leveling_inc_bitslip(a32, module); + } + +//best_bitslip = 1; + + sdram_read_leveling_rst_bitslip(a32, module); + for (bitslip = 0; bitslip < best_bitslip; bitslip++) + sdram_read_leveling_inc_bitslip(a32, module); + sdram_leveling_center_module(a32, module, 1, 0); + /*, + sdram_read_leveling_rst_delay, + sdram_read_leveling_inc_delay);*/ + } +} +__attribute__ ((section (".text.primary"))) static void +sdram_write_latency_calibration(uint32_t a32) +{ + int i; + int module; + int bitslip; + unsigned int score; + unsigned int subscore; + unsigned int best_score; + int best_bitslip; + int _sdram_write_leveling_bitslips[16] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; + for (module = 0; module < 16 / 8; module++) { + best_score = 0; + best_bitslip = -1; + for (bitslip = 0; bitslip < 8; bitslip += 2) { + score = 0; + ddrphy_dly_sel_write(a32, 1 << module); + ddrphy_wdly_dq_bitslip_rst_write(a32, 1); + for (i = 0; i < bitslip; i++) { + ddrphy_wdly_dq_bitslip_write(a32, 1); + } + ddrphy_dly_sel_write(a32, 0); + score = 0; + sdram_read_leveling_rst_bitslip(a32, module); + for (i = 0; i < 8; i++) { + subscore = sdram_read_leveling_scan_module(a32, module, i, 0); + score = subscore > score ? subscore : score; + sdram_read_leveling_inc_bitslip(a32, module); + } + if (score > best_score) { + best_bitslip = bitslip; + best_score = score; + } + } + if (_sdram_write_leveling_bitslips[module] < 0) + bitslip = best_bitslip; + else + bitslip = _sdram_write_leveling_bitslips[module]; +//bitslip = 0; + ddrphy_dly_sel_write(a32, 1 << module); + ddrphy_wdly_dq_bitslip_rst_write(a32, 1); + for (i = 0; i < bitslip; i++) { + ddrphy_wdly_dq_bitslip_write(a32, 1); + } + ddrphy_dly_sel_write(a32, 0); + } +} +__attribute__ ((section (".text.primary"))) static int +sdram_leveling(uint32_t a32) +{ + int module; + sdram_software_control_on(a32); + for (module = 0; module < 16 / 8; module++) { + sdram_read_leveling_rst_delay(a32, module); + sdram_read_leveling_rst_bitslip(a32, module); + } + sdram_write_latency_calibration(a32); + sdram_read_leveling(a32); + sdram_software_control_off(a32); + return 1; +} +int +sdram_init(uint32_t a32) // // attribute in header file +{ + ddrphy_rdphase_write(a32, 2); + ddrphy_wrphase_write(a32, 3); + sdram_software_control_on(a32); + ddrphy_rst_write(a32, 1); + cdelay (1000); + ddrphy_rst_write(a32, 0); + cdelay (1000); + init_sequence(a32); + sdram_leveling(a32); + sdram_software_control_off(a32); + return 1; +} diff --git a/nubus-to-ztex-gateware/nubus_to_fpga_export.py b/nubus-to-ztex-gateware/nubus_to_fpga_export.py index 12694e6..7aeb65f 100644 --- a/nubus-to-ztex-gateware/nubus_to_fpga_export.py +++ b/nubus-to-ztex-gateware/nubus_to_fpga_export.py @@ -15,7 +15,7 @@ from litex.soc.doc.module import gather_submodules, ModuleNotDocumented, Documen from litex.soc.doc.csr import DocumentedCSRRegion from litex.soc.interconnect.csr import _CompoundCSR -from litex.soc.integration.export import _get_rw_functions_c +#from litex.soc.integration.export import _get_rw_functions_c # for generating a timestamp in the description field, if none is otherwise given import datetime @@ -23,7 +23,7 @@ import time ### _get_rw_functions_c( reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions): -def _get_rw_functions_c_DIS(name, csr_name, reg_base, area_base, nwords, busword, alignment, read_only, with_access_functions): +def _get_rw_functions_c(name, csr_name, reg_base, area_base, nwords, busword, alignment, read_only, with_access_functions): reg_name = name + "_" + csr_name r = "" @@ -47,25 +47,25 @@ def _get_rw_functions_c_DIS(name, csr_name, reg_base, area_base, nwords, busword stride = alignment//8; if with_access_functions: - r += "static inline {} {}_read(struct nubusfpga_{}_softc *sc) {{\n".format(ctype, reg_name, name) + r += "static inline {} {}_read(uint32_t a32) {{\n".format(ctype, reg_name, name) if nwords > 1: - r += "\t{} r = bus_space_read_4(sc->slotid, {}L);\n".format(ctype, hex(reg_base - area_base)) + r += "\t{} r = __builtin_bswap32(*((volatile {}*)(a32 + {})));\n".format(ctype, ctype, addr_str) for sub in range(1, nwords): r += "\tr <<= {};\n".format(busword) - r += "\tr |= bus_space_read_4(sc->slotid, {}L);\n".format(hex(reg_base - area_base + sub*stride)) + r += "\tr |= __builtin_bswap32(*((volatile {}*)(a32 + {} + {})));\n".format(ctype, addr_str, (sub*stride)) r += "\treturn r;\n}\n" else: - r += "\treturn bus_space_read_4(sc->slotid, {}L);\n}}\n".format(hex(reg_base - area_base)) + r += "\treturn __builtin_bswap32(*((volatile {}*)(a32 + {})));\n}}\n".format(ctype, addr_str) if not read_only: - r += "static inline void {}_write(struct nubusfpga_{}_softc *sc, {} v) {{\n".format(reg_name, name, ctype) + r += "static inline void {}_write(uint32_t a32, {} v) {{\n".format(reg_name, ctype) for sub in range(nwords): shift = (nwords-sub-1)*busword if shift: v_shift = "v >> {}".format(shift) else: v_shift = "v" - r += "\tbus_space_write_4(sc->slotid, {}L, {});\n".format(hex(reg_base - area_base + sub*stride), v_shift) + r += "\t*((volatile {}*)(a32 + {} + {})) = __builtin_bswap32({});\n".format(ctype, addr_str, (sub*stride), v_shift) r += "}\n" return r @@ -81,17 +81,14 @@ def get_csr_header_split(regions, constants, csr_base=None, with_access_function origin = region.origin - csr_base r += "\n/* "+name+" */\n" r += "#ifndef CSR_BASE\n" - r += "#define CSR_BASE {}L\n".format(hex(csr_base)) + r += "#define CSR_BASE {}L\n".format(hex(csr_base & 0x00FFFFFF)) r += "#endif\n" r += "#ifndef CSR_"+name.upper()+"_BASE\n" r += "#define CSR_"+name.upper()+"_BASE (CSR_BASE + "+hex(origin)+"L)\n" if not isinstance(region.obj, Memory): for csr in region.obj: nr = (csr.size + region.busword - 1)//region.busword - r += _get_rw_functions_c(reg_name=csr.name, reg_base=origin, nwords=nr, busword=region.busword, alignment=alignment, - read_only=getattr(csr, "read_only", False), - csr_base=0, with_csr_base_define=False, - with_access_functions=with_access_functions) + r += _get_rw_functions_c(name = name, csr_name = csr.name, reg_base = origin, area_base = region.origin - csr_base, nwords = nr, busword = region.busword, alignment = alignment, read_only = getattr(csr, "read_only", False), with_access_functions = with_access_functions) origin += alignment//8*nr if hasattr(csr, "fields"): for field in csr.fields.fields: @@ -102,21 +99,21 @@ def get_csr_header_split(regions, constants, csr_base=None, with_access_function if with_access_functions and csr.size <= 32: # FIXME: Implement extract/read functions for csr.size > 32-bit. reg_name = name + "_" + csr.name.lower() field_name = reg_name + "_" + field.name.lower() - r += "static inline uint32_t " + field_name + "_extract(struct nubusfpga_" + name + "_softc *sc, uint32_t oldword) {\n" + r += "static inline uint32_t " + field_name + "_extract(uint32_t a32, uint32_t oldword) {\n" r += "\tuint32_t mask = ((1 << " + size + ")-1);\n" r += "\treturn ( (oldword >> " + offset + ") & mask );\n}\n" - r += "static inline uint32_t " + field_name + "_read(struct nubusfpga_" + name + "_softc *sc) {\n" - r += "\tuint32_t word = " + reg_name + "_read(sc);\n" - r += "\treturn " + field_name + "_extract(sc, word);\n" + r += "static inline uint32_t " + field_name + "_read(uint32_t a32) {\n" + r += "\tuint32_t word = " + reg_name + "_read(a32);\n" + r += "\treturn " + field_name + "_extract(a32, word);\n" r += "}\n" if not getattr(csr, "read_only", False): - r += "static inline uint32_t " + field_name + "_replace(struct nubusfpga_" + name + "_softc *sc, uint32_t oldword, uint32_t plain_value) {\n" + r += "static inline uint32_t " + field_name + "_replace(uint32_t a32, uint32_t oldword, uint32_t plain_value) {\n" r += "\tuint32_t mask = ((1 << " + size + ")-1);\n" r += "\treturn (oldword & (~(mask << " + offset + "))) | (mask & plain_value)<< " + offset + " ;\n}\n" - r += "static inline void " + field_name + "_write(struct nubusfpga_" + name + "_softc *sc, uint32_t plain_value) {\n" - r += "\tuint32_t oldword = " + reg_name + "_read(sc);\n" - r += "\tuint32_t newword = " + field_name + "_replace(sc, oldword, plain_value);\n" - r += "\t" + reg_name + "_write(sc, newword);\n" + r += "static inline void " + field_name + "_write(uint32_t a32, uint32_t plain_value) {\n" + r += "\tuint32_t oldword = " + reg_name + "_read(a32);\n" + r += "\tuint32_t newword = " + field_name + "_replace(a32, oldword, plain_value);\n" + r += "\t" + reg_name + "_write(a32, newword);\n" r += "}\n" r += "#endif // CSR_"+name.upper()+"_BASE\n" diff --git a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py index e3bfc1d..3ebe2b5 100644 --- a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py +++ b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py @@ -287,9 +287,9 @@ class NuBusFPGA(SoCCore): l2_cache_size = 0, ) avail_sdram = self.bus.regions["main_ram"].size - from sdram_init import DDR3FBInit - self.submodules.sdram_init = DDR3FBInit(sys_clk_freq=sys_clk_freq, bitslip=1, delay=25) - self.bus.add_master(name="DDR3Init", master=self.sdram_init.bus) + #from sdram_init import DDR3FBInit + #self.submodules.sdram_init = DDR3FBInit(sys_clk_freq=sys_clk_freq, bitslip=1, delay=25) + #self.bus.add_master(name="DDR3Init", master=self.sdram_init.bus) else: avail_sdram = 256 * 1024 * 1024 self.add_ram("ram", origin=0x8f800000, size=2**16, mode="rw") diff --git a/nubus-to-ztex-gateware/sdram_init.py b/nubus-to-ztex-gateware/sdram_init.py index a21b60e..6e83798 100644 --- a/nubus-to-ztex-gateware/sdram_init.py +++ b/nubus-to-ztex-gateware/sdram_init.py @@ -111,7 +111,7 @@ def ddr3_config_instructions(bitslip, delay): r = [] for module in range(2): r += [_WRITE_CMD, ddrphy_dly_sel, 1<