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