mirror of
https://github.com/rdolbeau/NuBusFPGA.git
synced 2024-11-10 10:07:01 +00:00
651 lines
18 KiB
C
651 lines
18 KiB
C
#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;
|
|
}
|