233d1912da8c454a03eed106b05310ca4efde3b7
[litex.git] / software / bios / sdram.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <hw/dfii.h>
5 #include <hw/mem.h>
6 #include <csrbase.h>
7
8 #include "sdram.h"
9
10 static void cdelay(int i)
11 {
12 while(i > 0) {
13 __asm__ volatile("nop");
14 i--;
15 }
16 }
17
18 static void setaddr(int a)
19 {
20 CSR_DFII_AH_P0 = (a & 0xff00) >> 8;
21 CSR_DFII_AL_P0 = a & 0x00ff;
22 CSR_DFII_AH_P1 = (a & 0xff00) >> 8;
23 CSR_DFII_AL_P1 = a & 0x00ff;
24 }
25
26 static void init_sequence(void)
27 {
28 int i;
29
30 /* Bring CKE high */
31 setaddr(0x0000);
32 CSR_DFII_BA_P0 = 0;
33 CSR_DFII_CONTROL = DFII_CONTROL_CKE;
34
35 /* Precharge All */
36 setaddr(0x0400);
37 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
38
39 /* Load Extended Mode Register */
40 CSR_DFII_BA_P0 = 1;
41 setaddr(0x0000);
42 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
43 CSR_DFII_BA_P0 = 0;
44
45 /* Load Mode Register */
46 setaddr(0x0132); /* Reset DLL, CL=3, BL=4 */
47 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
48 cdelay(200);
49
50 /* Precharge All */
51 setaddr(0x0400);
52 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
53
54 /* 2x Auto Refresh */
55 for(i=0;i<2;i++) {
56 setaddr(0);
57 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS;
58 cdelay(4);
59 }
60
61 /* Load Mode Register */
62 setaddr(0x0032); /* CL=3, BL=4 */
63 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
64 cdelay(200);
65 }
66
67 void ddrsw(void)
68 {
69 CSR_DFII_CONTROL = DFII_CONTROL_CKE;
70 printf("DDR now under software control\n");
71 }
72
73 void ddrhw(void)
74 {
75 CSR_DFII_CONTROL = DFII_CONTROL_SEL|DFII_CONTROL_CKE;
76 printf("DDR now under hardware control\n");
77 }
78
79 void ddrrow(char *_row)
80 {
81 char *c;
82 unsigned int row;
83
84 if(*_row == 0) {
85 setaddr(0x0000);
86 CSR_DFII_BA_P0 = 0;
87 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
88 cdelay(15);
89 printf("Precharged\n");
90 } else {
91 row = strtoul(_row, &c, 0);
92 if(*c != 0) {
93 printf("incorrect row\n");
94 return;
95 }
96 setaddr(row);
97 CSR_DFII_BA_P0 = 0;
98 CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CS;
99 cdelay(15);
100 printf("Activated row %d\n", row);
101 }
102 }
103
104 void ddrrd(char *startaddr)
105 {
106 char *c;
107 unsigned int addr;
108 int i;
109
110 if(*startaddr == 0) {
111 printf("ddrrd <address>\n");
112 return;
113 }
114 addr = strtoul(startaddr, &c, 0);
115 if(*c != 0) {
116 printf("incorrect address\n");
117 return;
118 }
119
120 setaddr(addr);
121 CSR_DFII_BA_P0 = 0;
122 CSR_DFII_COMMAND_P0 = DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA;
123 cdelay(15);
124
125 for(i=0;i<8;i++)
126 printf("%02x", MMPTR(0xe0000834+4*i));
127 for(i=0;i<8;i++)
128 printf("%02x", MMPTR(0xe0000884+4*i));
129 printf("\n");
130 }
131
132 void ddrwr(char *startaddr)
133 {
134 char *c;
135 unsigned int addr;
136 int i;
137
138 if(*startaddr == 0) {
139 printf("ddrrd <address>\n");
140 return;
141 }
142 addr = strtoul(startaddr, &c, 0);
143 if(*c != 0) {
144 printf("incorrect address\n");
145 return;
146 }
147
148 for(i=0;i<8;i++) {
149 MMPTR(0xe0000814+4*i) = i;
150 MMPTR(0xe0000864+4*i) = 0xf0 + i;
151 }
152
153 setaddr(addr);
154 CSR_DFII_BA_P1 = 0;
155 CSR_DFII_COMMAND_P1 = DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA;
156 }
157
158 #define TEST_SIZE (4*1024*1024)
159
160 int memtest_silent(void)
161 {
162 volatile unsigned int *array = (unsigned int *)SDRAM_BASE;
163 int i;
164 unsigned int prv;
165
166 prv = 0;
167 for(i=0;i<TEST_SIZE/4;i++) {
168 prv = 1664525*prv + 1013904223;
169 array[i] = prv;
170 }
171
172 prv = 0;
173 for(i=0;i<TEST_SIZE/4;i++) {
174 prv = 1664525*prv + 1013904223;
175 if(array[i] != prv)
176 return 0;
177 }
178 return 1;
179 }
180
181 void memtest(void)
182 {
183 if(memtest_silent())
184 printf("OK\n");
185 else
186 printf("Failed\n");
187 }
188
189 int ddrinit(void)
190 {
191 printf("Initializing DDR SDRAM...\n");
192
193 init_sequence();
194 CSR_DFII_CONTROL = DFII_CONTROL_SEL|DFII_CONTROL_CKE;
195 if(!memtest_silent())
196 return 0;
197
198 return 1;
199 }
200
201 static const char *format_slot_state(int state)
202 {
203 switch(state) {
204 case 0: return "Empty";
205 case 1: return "Pending";
206 case 2: return "Processing";
207 default: return "UNEXPECTED VALUE";
208 }
209 }
210
211 void asmiprobe(void)
212 {
213 volatile unsigned int *regs = (unsigned int *)ASMIPROBE_BASE;
214 int slot_count;
215 int trace_depth;
216 int i;
217 int offset;
218
219 offset = 0;
220 slot_count = regs[offset++];
221 trace_depth = regs[offset++];
222 for(i=0;i<slot_count;i++)
223 printf("Slot #%d: %s\n", i, format_slot_state(regs[offset++]));
224 printf("Latest tags:\n");
225 for(i=0;i<trace_depth;i++)
226 printf("%d ", regs[offset++]);
227 printf("\n");
228 }