add initial support for the crisarchitecture used on foxboards to openwrt
[openwrt/svn-archive/archive.git] / target / linux / etrax-2.6 / image / e100boot / src / cbl / src / common.c
1 #include "hwregs.h"
2 #include "e100boot.h"
3
4 static void toggle_led(void);
5
6 static void read_load_info(void);
7 static void decode_load_info(void);
8
9 static void read_file(byte* addr, udword size);
10
11 #if USE_PRINT_DESCR
12 static void print_descr(dma_descr_T *d);
13 #endif
14
15 static int memory_test(udword addr, udword size, udword *failed_address);
16 static void memory_dump(udword *from, udword *to);
17
18 extern byte _Stext[];
19 extern byte _Edata[];
20
21 #ifdef USE_BAUDRATE_CHANGING
22 byte change_baudrate;
23 udword new_baudrate;
24 #endif
25
26 void
27 level2_boot(void)
28 {
29 #if USE_LEDS
30 REG_SET(R_PORT_PA_DATA, data_out, 0xaa);
31 #endif
32
33 #if 0
34 io_buf_next = (byte*)IO_BUF_START;
35 io_buf_cur = (byte*)IO_BUF_START;
36 #endif
37
38 #if 1
39 send_string("\r\n\r\nDevice ID = ");
40 send_hex(ntohl(tx_header.id), NL);
41 send_string(e100boot_version);
42 #endif
43
44 #if 1
45 {
46 udword sum = 0;
47 byte *b;
48
49 for (b = (byte*)_Stext; b != (byte*)_Edata; b++) {
50 sum += *b;
51 }
52 send_string("Checksum of bootloader is ");
53 send_hex(sum, NL);
54 }
55 #endif
56
57 read_load_info();
58
59 __asm__ volatile ("jump _start");
60 }
61
62 void
63 toggle_led(void)
64 {
65 #if USE_LEDS
66 REG_SET(R_PORT_PA_DATA, data_out, 0x55);
67
68 while (1) {
69 REG_SET(R_PORT_PA_DATA, data_out, ~REG_GET(R_PORT_PA_READ, data_in));
70 {
71 volatile udword i;
72
73 for (i = 0; i != 2000000; i++)
74 ;
75 }
76 }
77 #else
78 while (1) {
79 }
80 #endif
81 }
82
83 void
84 read_load_info(void)
85 {
86 #ifdef USE_BAUDRATE_CHANGING
87 change_baudrate = 0;
88 #endif
89
90 send_string("Waiting for load info.\r\n");
91
92 send_ack();
93
94 read_file((byte*)IO_BUF_START, IO_BUF_END - IO_BUF_START - CRC_LEN);
95 send_string("Got load info.\r\n");
96 decode_load_info();
97
98 #ifdef USE_BAUDRATE_CHANGING
99 if (change_baudrate) {
100 REG_WR(R_SERIAL0_BAUD, new_baudrate);
101 {
102 udword i = 0;
103
104 while (i++ < 1000000)
105 ;
106 }
107 send_ack();
108 }
109 #endif
110
111 toggle_led();
112 }
113
114 void
115 decode_load_info(void)
116 {
117 udword *type_p = (udword*)IO_BUF_START;
118 udword failed_address;
119 udword i;
120 command_T *cmd;
121
122 while (type_p != (udword*)(IO_BUF_END - CRC_LEN)) { /* !!! */
123 // send_hex(type_p, NL);
124 *type_p = ntohl(*type_p);
125 // send_hex(*type_p, NL);
126 type_p++;
127 }
128
129 // memory_dump(IO_BUF_START, IO_BUF_END);
130
131 cmd = (command_T*)IO_BUF_START;
132 while (cmd->type) {
133 switch (cmd->type) {
134 case PACKET_INFO:
135 send_string("PACKET_INFO\r\n");
136 send_hex(cmd->args.packet_info.addr, NL);
137 send_hex(cmd->args.packet_info.size, NL);
138
139 seq--;
140 send_ack();
141 seq++;
142
143 read_file((byte*)cmd->args.packet_info.addr, cmd->args.packet_info.size);
144
145 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.packet_info;
146 break;
147
148 case SET_REGISTER:
149 send_string("SET_REGISTER\r\n");
150 send_hex(cmd->args.set_register.addr, NL);
151 send_hex(cmd->args.set_register.val, NL);
152
153 *(udword*)cmd->args.set_register.addr = cmd->args.set_register.val;
154
155 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.set_register;
156 break;
157
158 case GET_REGISTER:
159 send_string("GET_REGISTER\r\n");
160 send_hex(cmd->args.get_register.addr, NL);
161 send_hex(*(udword*)cmd->args.get_register.addr, NL);
162
163 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.get_register;
164 break;
165
166 case PAUSE_LOOP:
167 send_string("PAUSE_LOOP\r\n");
168 send_hex(cmd->args.pause_loop.pause, NL);
169
170 for (i = cmd->args.pause_loop.pause; i; i--)
171 ;
172
173 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.pause_loop;
174 break;
175
176 case MEM_VERIFY:
177 send_string("MEM_VERIFY\r\n");
178 send_hex(cmd->args.mem_verify.addr, NL);
179 send_hex(cmd->args.mem_verify.val, NL);
180
181 if (*(udword*)cmd->args.mem_verify.addr != cmd->args.mem_verify.val) {
182 send_string("verify failed\r\n");
183 goto decode_failed;
184 }
185
186 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_verify;
187 break;
188
189 case MEM_TEST:
190 send_string("MEM_TEST\r\n");
191 send_hex(cmd->args.mem_test.from, NL);
192 send_hex(cmd->args.mem_test.to, NL);
193
194 if (!memory_test(cmd->args.mem_test.from,
195 cmd->args.mem_test.to,
196 &failed_address)) {
197 send_string("### Memory test failed at ");
198 send_hex(failed_address, NL);
199 memory_dump((udword*)DWORD_ALIGN(failed_address - 64),
200 (udword*)DWORD_ALIGN(failed_address + 64));
201 goto decode_failed;
202 }
203 send_string("Passed memory test.\r\n");
204
205 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_test;
206 break;
207
208 case MEM_DUMP:
209 send_string("MEM_DUMP\r\n");
210 send_hex(cmd->args.mem_dump.from_addr, NL);
211 send_hex(cmd->args.mem_dump.to_addr, NL);
212
213 memory_dump((udword*)cmd->args.mem_dump.from_addr,
214 (udword*)cmd->args.mem_dump.to_addr);
215
216 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_dump;
217 break;
218
219 case MEM_CLEAR:
220 send_string("MEM_CLEAR\r\n");
221 send_hex(cmd->args.mem_clear.from_addr, NL);
222 send_hex(cmd->args.mem_clear.to_addr, NL);
223
224 for (i = cmd->args.mem_clear.from_addr;
225 i <= cmd->args.mem_clear.to_addr;
226 i++) {
227 *(byte*)i = 0x00;
228 }
229
230 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.mem_clear;
231 break;
232
233 case FLASH:
234 send_string("FLASH\r\n");
235 send_hex((udword)cmd->args.flash.source, NL);
236 send_hex(cmd->args.flash.offset, NL);
237 send_hex(cmd->args.flash.size, NL);
238
239 if ((i = flash_write(cmd->args.flash.source,
240 cmd->args.flash.offset,
241 cmd->args.flash.size)) != ERR_FLASH_OK) {
242 if (i == ERR_FLASH_VERIFY) {
243 udword size =
244 (cmd->args.flash.size < 65536 ? cmd->args.flash.size : 65536);
245
246 /* Try to erase the first block(s) we tried to flash to prevent a
247 unit which failed to flash correctly from booting */
248 flash_write(NULL, cmd->args.flash.offset, size);
249 }
250
251 goto decode_failed;
252 }
253
254 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.flash;
255 break;
256
257 case JUMP:
258 #if 1
259 /* for the printf function in our libc */
260 REG_WR(R_DMA_CH8_FIRST, *(udword*)&tx_header.dest[0]);
261 REG_WR(R_DMA_CH9_FIRST, *(uword*)&tx_header.dest[4]);
262 // REG_WR(R_NETWORK_SA_1, &tx_header.dest[4]);
263 // REG_WR(R_NETWORK_SA_2, tx_header.id);
264 #endif
265 send_string("JUMP\r\n");
266 send_hex(cmd->args.jump.addr, NL);
267 send_string("END\r\n");
268
269 __asm__ volatile ("jump %0" :: "r" (cmd->args.jump.addr));
270
271 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.jump;
272 break;
273
274 case LOOP:
275 send_string("LOOP\r\n");
276 send_hex(cmd->args.bne.addr, NL);
277 send_hex(cmd->args.bne.target, NL);
278
279 if (*(udword*)cmd->args.bne.addr) {
280 (*(udword*)cmd->args.bne.addr)--;
281 (byte*)cmd = cmd->args.bne.target;
282 }
283 else {
284 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.bne;
285 }
286 break;
287
288 #ifdef USE_BAUDRATE_CHANGING
289 case BAUDRATE:
290 send_string("BAUDRATE\r\n");
291 send_hex(cmd->args.br.baudrate, NL);
292
293 new_baudrate = cmd->args.br.baudrate;
294
295 (byte*)cmd += sizeof cmd->type + sizeof cmd->args.br;
296 break;
297 #endif
298
299 default:
300 send_string("### Unknown type: ");
301 send_hex(cmd->type, NL);
302
303 goto decode_failed;
304 break;
305 }
306 }
307
308 decode_failed:
309 send_string("END\r\n");
310 }
311
312 void
313 read_file(byte* addr, udword size)
314 {
315 udword nbr_read_last;
316 udword sum;
317 byte *b;
318 byte *from;
319
320 /* send_string(">read_file\r\n"); */
321
322 nbr_read = 0;
323 nbr_read_last = 0;
324 target_address = (udword)addr;
325
326 if (interface == NETWORK) {
327 rx_descr2.buf = (udword)addr;
328 bytes_to_read = size;
329 rx_descr2.sw_len = size + CRC_LEN > 1500 ? 1500 : size + CRC_LEN;
330 /* rx_descr2.sw_len = 1500; */
331
332 REG_SET(R_DMA_CH1_FIRST, first, (udword)&rx_descr);
333
334 /* Restart receiver so descriptor is re-read. */
335 REG_SET(R_DMA_CH1_CMD, cmd, reset);
336 while (REG_EQL(R_DMA_CH1_CMD, cmd, reset)) {
337 }
338
339 REG_SET(R_DMA_CH1_CMD, cmd, start);
340
341 while (1) {
342 /* send_hex(rx_descr2.hw_len, NL); */
343 from = (byte*)rx_descr2.buf;
344 if (read_data()) {
345 if (nbr_read < size) {
346 REG_SET(R_DMA_CH1_CMD, cmd, start);
347 }
348
349 #if USE_PRINT_DESCR
350 print_descr(&rx_descr);
351 print_descr(&rx_descr2);
352 #endif
353
354 #if 0
355 send_string("Read ");
356 send_hex(rx_descr2.hw_len - CRC_LEN, NO_NL);
357 send_string(" bytes. ");
358 send_hex((udword)from, NO_NL);
359 send_string(" - ");
360 send_hex(rx_descr2.buf-1, NO_NL);
361 send_string(" (");
362 send_hex(nbr_read, NO_NL);
363 send_string("/");
364 send_hex(size, NO_NL);
365 send_string(")\r\n");
366 #endif
367
368 nbr_read_last = nbr_read;
369 /* from = (byte*)rx_descr2.buf; */
370
371 if (nbr_read >= size) {
372 break;
373 }
374 }
375 }
376 }
377 else { /* interface != NETWORK */
378 while (nbr_read < size) {
379 read_data();
380 }
381 }
382
383 sum = 0;
384 for (b = addr; b != (byte*)(addr+size); b++) {
385 sum += *b;
386 }
387 send_string("Checksum of file is ");
388 send_hex(sum, NL);
389
390 /* memory_dump((udword*)addr, (udword*)addr+size); */
391 /* send_string("<read_file\r\n"); */
392 }
393
394 #if USE_PRINT_DESCR
395 void
396 print_descr(dma_descr_T *d)
397 {
398 send_string("Descriptor at ");
399 send_hex((udword)d, NL);
400
401 send_string("ctrl : ");
402 send_hex(d->ctrl, NL);
403
404 send_string("sw_len : ");
405 send_hex(d->sw_len, NL);
406
407 send_string("next : ");
408 send_hex(d->next, NL);
409
410 send_string("buf : ");
411 send_hex(d->buf, NL);
412
413 send_string("status : ");
414 send_hex(d->status, NL);
415
416 send_string("hw_len : ");
417 send_hex(d->hw_len, NL);
418 }
419 #endif
420
421 int
422 memory_test(udword from, udword to, udword *failed_address)
423 {
424 udword i;
425 udword j;
426 byte b;
427
428 /* At each dword (but bytewise) write the inverse of the adress,
429 check that it worked, then write the inverse of the last byte
430 written. Exit on fail. The memory after a successfull test will
431 be:
432
433 0xC0000000 : 0xC0000000 0xC0000004 0xC0000008 0xC000000C
434 0xC0000010 : 0xC0000010 0xC0000014 0xC0000018 0xC000001C
435 */
436
437 for (i = from; i < to; i += 4) {
438 for (j = 0; (j != sizeof(udword)) && (i+j < to); j++) {
439 b = ((~i) >> (j*8)) & 0xff;
440 *(volatile byte*)(i+j) = b;
441 if (*(volatile byte*)(i+j) == b) {
442 *(volatile byte*)(i+j) = ~b;
443 }
444 else {
445 *failed_address = i+j;
446 send_string("### Memory test 1 failed at ");
447 send_hex(*failed_address, NL);
448 return FALSE;
449 }
450 }
451 }
452
453 /* Run through entire region, check bytewise that the dwords contain
454 the address to the dword. Exit on fail. */
455
456 for (i = from; i < to; i += 4) {
457 for (j = 0; (j != sizeof(udword)) && (i+j < to); j++) {
458 b = (i >> (j*8)) & 0xff;
459 if (*(volatile byte*)(i+j) != b) {
460 *failed_address = i+j;
461 send_string("### Memory test 2 failed at ");
462 send_hex(*failed_address, NL);
463 return FALSE;
464 }
465 }
466 }
467
468 return TRUE;
469 }
470
471 void
472 memory_dump(udword *from, udword *to)
473 {
474 udword *i = from;
475 int j;
476
477 for (; i <= to; i += 4) {
478 send_hex((udword)i, NO_NL);
479 send_string(" :");
480 for(j = 0; j != 4 && (i+j <= to); j++) {
481 send_string(" ");
482 send_hex(*(udword*)(i+j), NO_NL);
483 }
484 send_string("\r\n");
485 }
486 }