#include #include typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; #define WL_CALIB_SIZE 28 enum ddr_speed { DDR_400, DDR_533, DDR_667, DDR_800, DDR_1066 }; static const u16 wl_cntl_calib[4][WL_CALIB_SIZE] = { [DDR_533] = { // same as 667 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x850, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0x860, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x870, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0x880, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x910, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0x920, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0x930, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xB40, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xB50, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0xB60, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xB70, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0xB80, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0xA10, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0xA20, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0xA30, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xC40, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xC50, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0xC60, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xC70, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0xC80, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0xD10, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0xD20, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0xD30, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xD40, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xD50, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 010100b 14h 24o */ }, [DDR_800] = { 0x60, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x60, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x60, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x83C, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 001111b fh 17o */ 0x848, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0x854, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 010101b 15h 25o */ 0x860, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x90C, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 000011b 3h 3o */ 0x918, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0x924, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001001b 9h 11o */ 0xB30, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xB3C, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 001111b fh 17o */ 0xB48, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0xB54, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010101b 15h 25o */ 0xB60, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xA0C, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 000011b 3h 3o */ 0xA18, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0xA24, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001001b 9h 11o */ 0xC30, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xC3C, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 001111b fh 17o */ 0xC48, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0xC54, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010101b 15h 25o */ 0xC60, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xD0C, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 000011b 3h 3o */ 0xD18, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0xD24, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001001b 9h 11o */ 0xD30, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xD3C, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001111b fh 17o */ }, [DDR_400] = { 0xC0, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0xC0, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0xC0, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0x878, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011110b 1eh 36o */ 0x890, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 100100b 24h 44o */ 0x8A8, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 101010b 2ah 52o */ 0x8C0, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0x918, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0x930, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001100b ch 14o */ 0x948, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0xB60, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xB78, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011110b 1eh 36o */ 0xB90, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 100100b 24h 44o */ 0xBA8, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 101010b 2ah 52o */ 0xBC0, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0xA18, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0xA30, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xA48, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0xC60, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xC78, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011110b 1eh 36o */ 0xC90, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 100100b 24h 44o */ 0xCA8, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 101010b 2ah 52o */ 0xCC0, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 110000b 30h 60o */ 0xD18, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 000110b 6h 6o */ 0xD30, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xD48, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 010010b 12h 22o */ 0xD60, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xD78, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 011110b 1eh 36o */ }, [DDR_667] = { // same as 533 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x80, /* 11:8 WL_CNTRL 0000b 0h 0o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x850, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0x860, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0x870, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0x880, /* 11:8 WL_CNTRL 1000b 8h 10o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0x910, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0x920, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0x930, /* 11:8 WL_CNTRL 1001b 9h 11o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xB40, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xB50, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0xB60, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xB70, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0xB80, /* 11:8 WL_CNTRL 1011b bh 13o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0xA10, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0xA20, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0xA30, /* 11:8 WL_CNTRL 1010b ah 12o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xC40, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xC50, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 010100b 14h 24o */ 0xC60, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011000b 18h 30o */ 0xC70, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 011100b 1ch 34o */ 0xC80, /* 11:8 WL_CNTRL 1100b ch 14o * 7:2 WDLL_CNTL 100000b 20h 40o */ 0xD10, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 000100b 4h 4o */ 0xD20, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001000b 8h 10o */ 0xD30, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 001100b ch 14o */ 0xD40, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 010000b 10h 20o */ 0xD50, /* 11:8 WL_CNTRL 1101b dh 15o * 7:2 WDLL_CNTL 010100b 14h 24o */ }, }; static const u32 wdll_misc_calib[WL_CALIB_SIZE] = { // Delay CK[5:3] // CK_L[5:3] /*0*/ 0x1200002, 0x1200002, 0x1200002, // 24:24 WLCKDLY 1b 1h 1o // 22:16 WL_PHSEL_MODE 0100000b 20h 40o // 11:8 WL_CNTRL 0000b 0h 0o 0 // 7:4 WL_CNTRL_A 0000b 0h 0o // 2:0 WL_CMD_DLY 010b 2h 2o /*3*/ 0x1200902, 0x1200902, 0x1200902, 0x1200902, 0x1200902, 0x1200902, 0x1200902, // 24:24 WLCKDLY 1b 1h 1o // 22:16 WL_PHSEL_MODE 0100000b 20h 40o // 11:8 WL_CNTRL 1001b 9h 11o 1/4 CLK // 7:4 WL_CNTRL_A 0000b 0h 0o // 2:0 WL_CMD_DLY 010b 2h 2o /*10*/ 0x1200802, 0x1200802, 0x1200802, 0x1200802, 0x1200802, 0x1200802, 0x1200802, 0x1200802, // 24:24 WLCKDLY 1b 1h 1o // 22:16 WL_PHSEL_MODE 0100000b 20h 40o // 11:8 WL_CNTRL 1000b 8h 10o 1/2 CLK // 7:4 WL_CNTRL_A 0000b 0h 0o // 2:0 WL_CMD_DLY 010b 2h 2o /*18*/ 0x1200B02, 0x1200B02, 0x1200B02, 0x1200B02, 0x1200B02, 0x1200B02, 0x1200B02, 0x1200B02, // 24:24 WLCKDLY 1b 1h 1o // 22:16 WL_PHSEL_MODE 0100000b 20h 40o // 11:8 WL_CNTRL 1011b bh 13o 3/4 CLK // 7:4 WL_CNTRL_A 0000b 0h 0o // 2:0 WL_CMD_DLY 010b 2h 2o /*26*/ 0x1200C02, 0x1200C02, // 24:24 WLCKDLY 1b 1h 1o // 22:16 WL_PHSEL_MODE 0100000b 20h 40o // 11:8 WL_CNTRL 1100b ch 14o 1 CLK // 7:4 WL_CNTRL_A 0000b 0h 0o // 2:0 WL_CMD_DLY 010b 2h 2o }; static const int freq_to_int[] = { [DDR_800] = 800, [DDR_667] = 667, [DDR_533] = 533, [DDR_400] = 400, }; static const int ck_period[] = { /* clock period in 10*picoseconds */ [DDR_800] = 250, /* 2.5ns */ [DDR_667] = 300, /* 3ns */ [DDR_533] = 375, /* 3.75ns */ [DDR_400] = 500, /* 5ns */ }; #define WL_CNTRL(a) (((a)>>8)&0xf) #define WDLL_CNTRL(a) (((a)>>2)&0x3f) #define debug printf static double delay(u8 wl_cntrl, double wdll_dly, double clk) { if (((wl_cntrl >> 3) & 1) == 0) return 0; switch (wl_cntrl) { case 8: return wdll_dly; case 0x9: debug("WILD GUESS... "); return 0.25*clk+wdll_dly; case 0xb: return 0.25*clk+wdll_dly; case 0xa: debug("WILD GUESS... "); return 0.5*clk+wdll_dly; case 0xc: return 0.5*clk+wdll_dly; case 0xd: return 0.75*clk+wdll_dly; case 0x19: return 0.25*clk; case 0x18: return 0.5*clk; case 0x1b: return 0.75*clk; case 0x1c: return clk; } return 42424242; } #define MASTCNTL(speed) ((speed) == DDR_400 ? 6 : (speed) == DDR_533 ? 4 : (speed) == DDR_667 ? 4 : /* DDR_800 */ 3 ) static double wdll_dly(u8 wdll_cntrl, double clk, int mastcntl) { double delay_uncomp = 100; double delay_element = (0.25*clk - delay_uncomp) / (mastcntl + 0.5); return (delay_element * wdll_cntrl) / 8; } int main(void) { int i; int f; FILE *fi; char fname[10]; for (f = 0; f < 4; f++) { sprintf(fname, "%d.dat", freq_to_int[f]); fi = fopen(fname, "w"); for (i = 0; i < WL_CALIB_SIZE; i++) { u32 wl_cntl = wl_cntl_calib[f][i]; u32 wdll_misc = wdll_misc_calib[i]; u8 wdll_misc_wl_cntrl = (wdll_misc >> 8) & 0xf; u8 wl_cntrl = WL_CNTRL(wl_cntl); u8 wdll_cntrl = WDLL_CNTRL(wl_cntl); int clk = ck_period[f]*10; double dly = wdll_dly(wdll_cntrl, clk, MASTCNTL(f)); printf("%d WL_CNTRL=%x WDLL_CNTRL=%02x CLK=%d WDLL_DLY=%lf delay=%lf\n", i, wl_cntrl, wdll_cntrl, clk, dly, delay(wl_cntrl, dly, clk)); if (wl_cntrl != wdll_misc_wl_cntrl) printf("WARNING: WDLL_MISC.WL_CNTRL=%x\n", wdll_misc_wl_cntrl); fprintf(fi, "%d %lf\n", i, delay(wl_cntrl, dly, clk)); } fclose(fi); } }