mirror of
https://github.com/rdolbeau/NuBusFPGA.git
synced 2025-01-18 02:32:12 +00:00
move SDRAM init from HW to SW
This commit is contained in:
parent
42c0a18371
commit
b2ef57a8dc
1
nubus-to-ztex-gateware/DeclROM/.gitignore
vendored
1
nubus-to-ztex-gateware/DeclROM/.gitignore
vendored
@ -8,3 +8,4 @@ vid_decl_rom.srec
|
||||
VidRom*
|
||||
NuBusFPGADrvr*.s
|
||||
NuBusFPGARAMDskDrvr*.s
|
||||
*.o
|
||||
|
@ -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}
|
||||
|
@ -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")));
|
||||
|
||||
|
@ -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
|
||||
|
@ -33,6 +33,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 ? */
|
||||
a32_l0 = a32;
|
||||
@ -148,3 +151,5 @@ UInt32 Primary(SEBlock* seblock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SDRAM INIT */
|
||||
|
||||
|
650
nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_RamInit.c
Normal file
650
nubus-to-ztex-gateware/DeclROM/NuBusFPGAPrimaryInit_RamInit.c
Normal file
@ -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;
|
||||
}
|
@ -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"
|
||||
|
@ -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")
|
||||
|
@ -111,7 +111,7 @@ def ddr3_config_instructions(bitslip, delay):
|
||||
r = []
|
||||
for module in range(2):
|
||||
r += [_WRITE_CMD, ddrphy_dly_sel, 1<<module ]
|
||||
r += [_WRITE_CMD, ddrphy_wdly_dq_bitslip_rst, 1<<module ]
|
||||
r += [_WRITE_CMD, ddrphy_wdly_dq_bitslip_rst, 1<<module ] # checkme ? should be ?
|
||||
r += [_WRITE_CMD, ddrphy_dly_sel, 0 ]
|
||||
for module in range(2):
|
||||
r += [_WRITE_CMD, ddrphy_dly_sel, 1<<module ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user