move SDRAM init from HW to SW

This commit is contained in:
Romain Dolbeau 2023-01-27 22:25:12 +01:00
parent 42c0a18371
commit b2ef57a8dc
9 changed files with 684 additions and 27 deletions

View File

@ -8,3 +8,4 @@ vid_decl_rom.srec
VidRom*
NuBusFPGADrvr*.s
NuBusFPGARAMDskDrvr*.s
*.o

View File

@ -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}

View File

@ -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")));

View File

@ -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

View File

@ -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 */

View 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;
}

View File

@ -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"

View File

@ -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")

View File

@ -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 ]