support DDR2-based board

This commit is contained in:
Romain Dolbeau
2026-03-25 23:01:24 +01:00
parent 413b7beec5
commit 77b3ca81cf
5 changed files with 158 additions and 20 deletions

View File

@@ -228,7 +228,7 @@ OSErr cNuBusFPGACtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
a32 += vPInfo->csPage * 1024 * 1024 * 4; /* fixme */
SwapMMUMode ( &busMode );
#if 0
#if 1
if ((dStore->curMode != kDepthMode5) && (dStore->curMode != kDepthMode6)) {
/* grey the screen */
a32_l0 = a32;
@@ -437,6 +437,7 @@ OSErr reconfHW(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned
if (mode != dStore->curMode) {
UInt8 id = mode - nativeVidMode;
short timeout;
unsigned short i;
for (i = nativeVidMode ; i <= dStore->maxMode ; i++) {
// disable spurious resources, enable only the right one
@@ -487,16 +488,16 @@ OSErr reconfHW(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned
#error "Unknown input clock for MMCM"
#endif
short timeout = 1000;
timeout = 1000;
while ((read_reg(dce, GOBOFB_VIDEOCTRL) & 0x2 != 0) && timeout) {
/* wait for the reset process to be over */
/* otherwise without a clock it won't finish */
timeout --;
delay(100);
}
if (timeout == 0)
err = ioErr;
// first reset the MCMM and set new values
litex_clk_assert_reg(DRP_RESET);
@@ -566,6 +567,14 @@ OSErr reconfHW(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned
write_reg(dce, GOBOFB_VRES_START, __builtin_bswap32(vo));
write_reg(dce, GOBOFB_HRES_END, __builtin_bswap32(ho + dStore->hres[id]));
write_reg(dce, GOBOFB_VRES_END, __builtin_bswap32(vo + dStore->vres[id]));
timeout = 1000;
while ((read_reg(dce, GOBOFB_VIDEOCTRL) & 0x2 != 0) && timeout) {
/* wait for the reset process to be over */
timeout --;
}
if (timeout == 0)
err = ioErr;
}
if (depth != dStore->curDepth) {

View File

@@ -11,6 +11,7 @@
#pragma parameter __D0 Primary(__A0)
UInt32 Primary(SEBlock* seblock) {
#ifndef DISABLE_GOBLIN
UInt32 a32 = 0xF0000000 | ((UInt32)seblock->seSlot << 24);
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
@@ -37,7 +38,9 @@ UInt32 Primary(SEBlock* seblock) {
/* initialize DRAM controller */
#if !defined(QEMU) && !defined(IISIFPGA)
// IIisFPGA should have the hardware initializer, as SDRAM needs to work before the Mac ROM probes it for memory expansion
// IIsiFPGA should have the hardware initializer, as SDRAM needs to work before the Mac ROM probes it for memory expansion
// to calibrate the HW initialiazer, DDR_RECORD_RESULTS in the SW initlializer can be used to store bitslip/delay in the acceleration SRAM
// ... without the acceleration INIT installed (the acceleration stack will trample the recorded results)
sdram_init(a32);
#endif
@@ -152,6 +155,7 @@ UInt32 Primary(SEBlock* seblock) {
#endif
seblock->seStatus = 1;
#endif // DISABLE_GOBLIN
return 0;
}

View File

@@ -18,6 +18,9 @@
#error "no board defined"
#endif
// for bringup of hardware initializer
//#define DDR_RECORD_RESULTS
/* auto-generated sdram_phy.h + sc */
#define DFII_CONTROL_SEL 0x01
#define DFII_CONTROL_CKE 0x02
@@ -31,6 +34,11 @@
#define DFII_COMMAND_WRDATA 0x10
#define DFII_COMMAND_RDDATA 0x20
#ifndef SDRAM_DDR2
// so DDR3 (V1.0)
#ifndef SDRAM_DDR3
#define SDRAM_DDR3
#endif
#define SDRAM_PHY_A7DDRPHY
#define SDRAM_PHY_XDR 2
#define SDRAM_PHY_DATABITS 16
@@ -45,6 +53,24 @@
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
#define SDRAM_PHY_DELAYS 32
#define SDRAM_PHY_BITSLIPS 8
#else
// DDR2 (V3.0)
#define SDRAM_PHY_A7DDRPHY
#define SDRAM_PHY_XDR 2
#define SDRAM_PHY_DATABITS 16
#define SDRAM_PHY_DFI_DATABITS 32
#define SDRAM_PHY_PHASES 2
#define SDRAM_PHY_CL 3
#define SDRAM_PHY_CWL 2
#define SDRAM_PHY_CMD_LATENCY 0
#define SDRAM_PHY_RDPHASE 1
#define SDRAM_PHY_WRPHASE 0
#define SDRAM_PHY_READ_LEVELING_CAPABLE
#define SDRAM_PHY_DQ_DQS_RATIO 8
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
#define SDRAM_PHY_DELAYS 32
#define SDRAM_PHY_BITSLIPS 8
#endif
__attribute__ ((section (".text.primary"))) static void cdelay(int i);
@@ -63,6 +89,7 @@ __attribute__ ((section (".text.primary"))) static inline void command_p1(uint32
sdram_dfii_pi1_command_write(a32, cmd);
sdram_dfii_pi1_command_issue_write(a32, 1);
}
#if (SDRAM_PHY_PHASES > 2)
__attribute__ ((section (".text.primary"))) static inline void command_p2(uint32_t a32, int cmd)
{
sdram_dfii_pi2_command_write(a32, cmd);
@@ -73,6 +100,7 @@ __attribute__ ((section (".text.primary"))) static inline void command_p3(uint32
sdram_dfii_pi3_command_write(a32, cmd);
sdram_dfii_pi3_command_issue_write(a32, 1);
}
#endif
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
@@ -81,8 +109,10 @@ __attribute__ ((section (".text.primary"))) static inline unsigned long sdram_df
switch (phase) {
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
#if (SDRAM_PHY_PHASES > 2)
case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_WRDATA_ADDR;
#endif
default: return 0;
}
}
@@ -92,8 +122,10 @@ __attribute__ ((section (".text.primary"))) static inline unsigned long sdram_df
switch (phase) {
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
#if (SDRAM_PHY_PHASES > 2)
case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR;
#endif
default: return 0;
}
}
@@ -114,6 +146,71 @@ __attribute__ ((section (".text.primary"))) static inline void init_sequence(uin
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);
#ifdef SDRAM_DDR2
//DDR2
cdelay(20000);
/* Precharge All */
sdram_dfii_pi0_address_write(a32, 0x400);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Extended 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 Extended Mode Register 2 */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 2);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Extended Mode Register */
sdram_dfii_pi0_address_write(a32, 0x0);
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 / Reset DLL, CL=3, BL=4 */
sdram_dfii_pi0_address_write(a32, 0x532);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
cdelay(200);
/* Precharge All */
sdram_dfii_pi0_address_write(a32, 0x400);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Auto Refresh */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS);
cdelay(4);
/* Auto Refresh */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS);
cdelay(4);
/* Load Mode Register / CL=3, BL=4 */
sdram_dfii_pi0_address_write(a32, 0x432);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
cdelay(200);
/* Load Extended Mode Register / OCD Default */
sdram_dfii_pi0_address_write(a32, 0x380);
sdram_dfii_pi0_baddress_write(a32, 1);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Extended Mode Register / OCD Exit */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 1);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
#else // !SDRAM_DDR2
// DDR3
cdelay(10000);
/* Load Mode Register 2, CWL=5 */
@@ -142,6 +239,7 @@ __attribute__ ((section (".text.primary"))) static inline void init_sequence(uin
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_WE|DFII_COMMAND_CS);
cdelay(200);
#endif // SDRAM_DDR2
}
#include "nubusfpga_csr_common.h"
@@ -248,12 +346,14 @@ __attribute__ ((section (".text.primary"))) static void
sdram_dfii_pix_address_write(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
#if (SDRAM_PHY_PHASES > 2)
case 3:
sdram_dfii_pi3_address_write(a32, value);
break;
case 2:
sdram_dfii_pi2_address_write(a32, value);
break;
#endif
case 1:
sdram_dfii_pi1_address_write(a32, value);
break;
@@ -277,12 +377,14 @@ __attribute__ ((section (".text.primary"))) static void
sdram_dfii_pix_baddress_write(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
#if (SDRAM_PHY_PHASES > 2)
case 3:
sdram_dfii_pi3_baddress_write(a32, value);
break;
case 2:
sdram_dfii_pi2_baddress_write(a32, value);
break;
#endif
case 1:
sdram_dfii_pi1_baddress_write(a32, value);
break;
@@ -306,12 +408,14 @@ __attribute__ ((section (".text.primary"))) static void
command_px(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
#if (SDRAM_PHY_PHASES > 2)
case 3:
command_p3(a32, value);
break;
case 2:
command_p2(a32, value);
break;
#endif
case 1:
command_p1(a32, value);
break;
@@ -396,14 +500,14 @@ sdram_write_read_check_test_pattern (uint32_t a32, int module, unsigned int seed
unsigned char tst[1 * 32 / 8];
unsigned char prs[4][1 * 32 / 8];
prv = seed;
for (p = 0; p < 4; p++) {
for (p = 0; p < SDRAM_PHY_PHASES; 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++)
for (p = 0; p < SDRAM_PHY_PHASES; 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);
@@ -415,13 +519,13 @@ sdram_write_read_check_test_pattern (uint32_t a32, int module, unsigned int seed
cdelay (15);
sdram_precharge_test_row(a32);
errors = 0;
for (p = 0; p < 4; p++) {
for (p = 0; p < SDRAM_PHY_PHASES; 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]);
popcount (prs[p][SDRAM_PHY_MODULES - 1 - module] ^ tst[SDRAM_PHY_MODULES - 1 - module]);
errors +=
popcount (prs[p][2 * 16 / 8 - 1 - module] ^
tst[2 * 16 / 8 - 1 - module]);
popcount (prs[p][2 * SDRAM_PHY_MODULES - 1 - module] ^
tst[2 * SDRAM_PHY_MODULES - 1 - module]);
}
return errors;
}
@@ -481,8 +585,16 @@ sdram_leveling_center_module (uint32_t a32, int module, int show_short, int show
delay_mid = (delay_min + delay_max) / 2 % 32;
delay_range = (delay_max - delay_min) / 2;
//delay_mid = 25;
#ifdef DDR_RECORD_RESULTS
{
//long *rec_addr = (long*)(a32 + 8*1024*1024 - 4); // last word of the FB
long *rec_addr = (long*)(a32 + 0x00902000 + 4092); // end of the accel SRAM
*(rec_addr - SDRAM_PHY_MODULES - module) = delay_mid;
//long *rec_addr = (long*)(0x90000000); // superslot on the IIsi
//*(rec_addr + SDRAM_PHY_MODULES + module) = delay_mid;
}
#endif
//rst_delay(a32, module);
sdram_read_leveling_rst_delay(a32, module);
@@ -554,7 +666,7 @@ sdram_read_leveling(uint32_t a32)
unsigned int score;
unsigned int best_score;
int best_bitslip;
for (module = 0; module < 16 / 8; module++) {
for (module = 0; module < SDRAM_PHY_MODULES; module++) {
best_score = 0;
best_bitslip = 0;
sdram_read_leveling_rst_bitslip(a32, module);
@@ -572,9 +684,15 @@ sdram_read_leveling(uint32_t a32)
break;
sdram_read_leveling_inc_bitslip(a32, module);
}
//best_bitslip = 1;
#ifdef DDR_RECORD_RESULTS
{
//long *rec_addr = (long*)(a32 + 8*1024*1024 - 4); // last word of the FB
long *rec_addr = (long*)(a32 + 0x00902000 + 4092); // end of the accel SRAM
*(rec_addr - module) = best_bitslip;
//long *rec_addr = (long*)(0x90000000); // superslot on the IIsi
//*(rec_addr + module) = best_bitslip;
}
#endif
sdram_read_leveling_rst_bitslip(a32, module);
for (bitslip = 0; bitslip < best_bitslip; bitslip++)
sdram_read_leveling_inc_bitslip(a32, module);
@@ -596,7 +714,7 @@ sdram_write_latency_calibration(uint32_t a32)
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++) {
for (module = 0; module < SDRAM_PHY_MODULES; module++) {
best_score = 0;
best_bitslip = -1;
for (bitslip = 0; bitslip < 8; bitslip += 2) {
@@ -637,11 +755,13 @@ sdram_leveling(uint32_t a32)
{
int module;
sdram_software_control_on(a32);
for (module = 0; module < 16 / 8; module++) {
for (module = 0; module < SDRAM_PHY_MODULES; module++) {
sdram_read_leveling_rst_delay(a32, module);
sdram_read_leveling_rst_bitslip(a32, module);
}
#ifdef SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
sdram_write_latency_calibration(a32);
#endif
sdram_read_leveling(a32);
sdram_software_control_off(a32);
return 1;
@@ -649,8 +769,8 @@ sdram_leveling(uint32_t a32)
int
sdram_init(uint32_t a32) // // attribute in header file
{
ddrphy_rdphase_write(a32, 2);
ddrphy_wrphase_write(a32, 3);
ddrphy_rdphase_write(a32, SDRAM_PHY_RDPHASE);
ddrphy_wrphase_write(a32, SDRAM_PHY_WRPHASE);
sdram_software_control_on(a32);
ddrphy_rst_write(a32, 1);
cdelay (1000);
@@ -661,3 +781,4 @@ sdram_init(uint32_t a32) // // attribute in header file
sdram_software_control_off(a32);
return 1;
}

View File

@@ -7,6 +7,7 @@
#pragma parameter __D0 Primary(__A0)
UInt32 Secondary(SEBlock* seblock) {
#ifndef DISABLE_GOBLIN
UInt32 a32 = 0xF0000000 | ((UInt32)seblock->seSlot << 24);
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
@@ -87,6 +88,7 @@ UInt32 Secondary(SEBlock* seblock) {
#endif
seblock->seStatus = 1;
#endif // DISABLE_GOBLIN
return 0;
}

View File

@@ -352,6 +352,7 @@ int main(int argc, char **argv) {
return -1;
}
fprintf(fd, "_sRsrcDir:\n");
#ifndef DISABLE_GOBLIN
fprintf(fd, "\tOSLstEntry\tsRsrc_Board,_sRsrc_Board\t/* board sRsrc List */\n");
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
@@ -365,6 +366,7 @@ int main(int argc, char **argv) {
#endif
}
}
#endif
#ifdef ENABLE_HDMIAUDIO
fprintf(fd, "\tOSLstEntry\tsRsrc_HDMIAudio,_sRsrc_HDMIAudio\n");
#endif