MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / nios2nommu / kernel / start.c
blob62ad6c06bd766cb59f963cda77945b7f7ec8ec22
1 /*--------------------------------------------------------------------
3 * arch/nios2nommu/kernel/start.c
5 * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
7 * Copyright (C) 2004 Microtronix Datacom Ltd
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 * Jan/20/2004 dgt NiosII
21 * May/20/2005 dgt Altera NiosII Custom shift instr(s)
22 * possibly assumed by memcpy, etc; ensure
23 * "correct" core loaded therefore if so.
25 ---------------------------------------------------------------------*/
28 #include <asm/system.h>
29 #include <asm/nios.h>
30 #include <linux/kernel.h>
31 #include <linux/ctype.h>
32 #include <linux/string.h>
33 #include <linux/time.h>
35 #ifdef CONFIG_SERIAL_AJUART //;dgt;20may05;
36 #ifdef CONFIG_SERIAL_AJUART_CONSOLE //;dgt;20may05;
38 #include <linux/console.h> //;dgt;20may05;
39 #include <asm/altera_juart.h> //;dgt;20may05;
41 extern struct console juart_console; //;dgt;20may05;
43 #endif // CONFIG_SERIAL_AJUART //;dgt;20may05;
44 #endif // CONFIG_SERIAL_AJUART_CONSOLE //;dgt;20may05;
46 //;dgt;20may05; #ifdef CONFIG_CRC_CHECK
48 // #if defined(CONFIG_NIOS_SERIAL) //;dgt;20may05;
49 // #if defined(CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;20may05;
50 #if defined(nasys_printf_uart) //;dgt;20may05;
51 static void putsNoNewLine( unsigned char *s )
53 while(*s) {
54 while (!(nasys_printf_uart->np_uartstatus &
55 np_uartstatus_trdy_mask));
56 nasys_printf_uart->np_uarttxdata = *s++;
60 #define NL "\r\n"
61 static void puts(unsigned char *s)
63 putsNoNewLine( s );
64 putsNoNewLine( NL );
66 #endif // nasys_printf_uart //;dgt;20may05;
67 // #endif // CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;20may05;
68 // #endif // CONFIG_NIOS_SERIAL) //;dgt;20may05;
70 #ifdef CONFIG_CRC_CHECK //;dgt;20may05;
72 #if 1
73 #define outchar(X) { \
74 while (!(nasys_printf_uart->np_uartstatus & np_uartstatus_trdy_mask)); \
75 nasys_printf_uart->np_uarttxdata = (X); }
76 #else
77 #define outchar(X) putchar(X)
78 #endif
79 #define outhex(X,Y) { \
80 unsigned long __w; \
81 __w = ((X) >> (Y)) & 0xf; \
82 __w = __w > 0x9 ? 'A' + __w - 0xa : '0' + __w; \
83 outchar(__w); }
84 #define outhex8(X) { \
85 outhex(X,4); \
86 outhex(X,0); }
87 #define outhex16(X) { \
88 outhex(X,12); \
89 outhex(X,8); \
90 outhex(X,4); \
91 outhex(X,0); }
92 #define outhex32(X) { \
93 outhex(X,28); \
94 outhex(X,24); \
95 outhex(X,20); \
96 outhex(X,16); \
97 outhex(X,12); \
98 outhex(X,8); \
99 outhex(X,4); \
100 outhex(X,0); }
101 #endif
103 #if 0
104 static unsigned long testvar = 0xdeadbeef;
105 #endif
107 #ifdef CONFIG_CRC_CHECK
110 /******************************************************/
113 extern unsigned long __CRC_Table_Begin;
115 typedef unsigned char U8;
116 typedef unsigned long U32;
118 /* Table of CRC-32's of all single byte values */
119 const U32 crc_32_tab[] = {
120 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
121 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
122 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
123 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
124 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
125 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
126 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
127 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
128 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
129 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
130 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
131 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
132 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
133 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
134 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
135 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
136 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
137 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
138 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
139 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
140 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
141 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
142 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
143 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
144 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
145 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
146 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
147 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
148 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
149 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
150 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
151 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
152 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
153 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
154 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
155 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
156 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
157 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
158 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
159 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
160 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
161 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
162 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
163 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
164 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
165 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
166 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
167 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
168 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
169 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
170 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
171 0x2d02ef8dL
174 U32 Calc_CRC( const U8 *p, U32 len )
176 U32 crc = (U32)~0L;
177 while (len--)
178 crc = crc_32_tab[0xFF & (crc ^ *p++)] ^ (crc >> 8);
180 return crc ^ (U32)~0L;
185 /******************************************************/
188 /* hjz: Following time stuff is hacked and modified from uC-libc (various files), which in turn was... */
189 /* This is adapted from glibc */
190 /* Copyright (C) 1991, 1993 Free Software Foundation, Inc */
192 #define SECS_PER_HOUR 3600L
193 #define SECS_PER_DAY 86400L
194 typedef unsigned long time_t;
197 static const unsigned short int __mon_lengths[2][12] = {
198 /* Normal years. */
199 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
200 /* Leap years. */
201 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
203 /* This global is exported to the wide world in keeping
204 * with the interface in time.h */
205 long int timezone = 0;
207 static const char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
208 static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
209 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
211 /* Nonzero if YEAR is a leap year (every 4 years,
212 except every 100th isn't, and every 400th is). */
213 # define __isleap(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
215 struct tm
217 int tm_sec; /* Seconds. [0-60] (1 leap second) */
218 int tm_min; /* Minutes. [0-59] */
219 int tm_hour; /* Hours. [0-23] */
220 int tm_mday; /* Day. [1-31] */
221 int tm_mon; /* Month. [0-11] */
222 int tm_year; /* Year - 1900. */
223 int tm_wday; /* Day of week. [0-6] */
224 int tm_yday; /* Days in year.[0-365] */
225 int tm_isdst; /* DST. [-1/0/1]*/
227 # ifdef __USE_BSD
228 long int tm_gmtoff; /* Seconds east of UTC. */
229 __const char *tm_zone; /* Timezone abbreviation. */
230 # else
231 long int __tm_gmtoff; /* Seconds east of UTC. */
232 __const char *__tm_zone; /* Timezone abbreviation. */
233 # endif
236 void __tm_conv(struct tm *tmbuf, time_t *t, time_t offset)
238 long days, rem;
239 register int y;
240 register const unsigned short int *ip;
242 timezone = -offset;
244 days = *t / SECS_PER_DAY;
245 rem = *t % SECS_PER_DAY;
246 rem += offset;
247 while (rem < 0)
249 rem += SECS_PER_DAY;
250 days--;
252 while (rem >= SECS_PER_DAY)
254 rem -= SECS_PER_DAY;
255 days++;
258 tmbuf->tm_hour = rem / SECS_PER_HOUR;
259 rem %= SECS_PER_HOUR;
260 tmbuf->tm_min = rem / 60;
261 tmbuf->tm_sec = rem % 60;
263 /* January 1, 1970 was a Thursday. */
264 tmbuf->tm_wday = (4 + days) % 7;
265 if (tmbuf->tm_wday < 0)
266 tmbuf->tm_wday += 7;
268 y = 1970;
269 while (days >= (rem = __isleap(y) ? 366 : 365))
271 y++;
272 days -= rem;
275 while (days < 0)
277 y--;
278 days += __isleap(y) ? 366 : 365;
281 tmbuf->tm_year = y - 1900;
282 tmbuf->tm_yday = days;
284 ip = __mon_lengths[__isleap(y)];
285 for (y = 0; days >= ip[y]; ++y)
286 days -= ip[y];
288 tmbuf->tm_mon = y;
289 tmbuf->tm_mday = days + 1;
290 tmbuf->tm_isdst = -1;
295 /* hjz: NOT your traditional ctime: This one includes timezone */
296 /* (UTC) and excludes the traditional trailing newline. */
297 char *CTime( time_t *t )
299 static char theTime[29];
300 struct tm tm;
302 __tm_conv( &tm, t, 0 );
303 sprintf( theTime, "%s %s %02d %02d:%02d:%02d UTC %04d",
304 dayOfWeek[tm.tm_wday], month[tm.tm_mon], tm.tm_mday,
305 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900 );
307 return theTime;
310 /******************************************************/
313 /* hjz: polled-I/O: Get a char if one is ready, or return -1 */
314 int getc( void )
316 if ( nasys_printf_uart->np_uartstatus & np_uartstatus_rrdy_mask )
317 return nasys_printf_uart->np_uartrxdata;
318 else
319 return -1;
323 typedef unsigned long off_t;
324 typedef struct
326 U8 *startAddr;
327 U8 *endAddr;
328 U32 CRC;
329 time_t mtime;
330 off_t size; // File size
331 char id[44]; // Filename. If path exceeds available size, name is "..." + last 40 chars of given filename
332 char host[32]; // hostname. If name exceeds available size name is first 28 chars of hostname + "..."
333 } FLASH_REGION_DESC;
336 int Test_Flash_Regions(void)
338 FLASH_REGION_DESC *pRegion = (FLASH_REGION_DESC *)&__CRC_Table_Begin;
339 U32 crc;
340 char cBuff[256];
341 int nrFailedRegions = 0;
342 int regionStatus;
343 int i;
344 unsigned int startAddr = (int) pRegion->startAddr;
345 unsigned int endAddr = (int) pRegion->endAddr;
347 puts( "***Checking flash CRC's" );
348 if ( (startAddr == -1) || (startAddr >= endAddr)
349 || !( ((startAddr >= (int) NIOS_FLASH_START) && (endAddr < (int) NIOS_FLASH_END))
350 || ((startAddr >= (int) na_flash) && (endAddr < (int) na_flash_end)) ) )
352 puts( " No Flash regions defined." );
353 return -1;
357 for ( i = 0; pRegion->startAddr && pRegion->startAddr != (U8 *)~0L; pRegion++, i++ )
359 crc = Calc_CRC( pRegion->startAddr, pRegion->endAddr - pRegion->startAddr );
360 if ( crc != pRegion->CRC )
362 regionStatus = 1;
363 nrFailedRegions++;
365 else
366 regionStatus = 0;
368 sprintf( cBuff, " Region %d: 0x%08lX - 0x%08lX, CRC = 0x%08lX --> %s" NL
369 " From file `%s' on host `%s'" NL
370 " Dated %s, size = %lu bytes",
371 i, (U32)pRegion->startAddr, (U32)pRegion->endAddr, pRegion->CRC,
372 regionStatus ? "***Failed" : "Passed",
373 pRegion->id, pRegion->host, CTime( &pRegion->mtime ), pRegion->size
375 puts( cBuff );
378 return nrFailedRegions;
380 #endif /* CONFIG_CRC_CHECK */
383 int main(void) {
384 extern void start_kernel(void);
386 #if 0
387 // extern unsigned long __data_rom_start;
388 extern unsigned long __data_start;
389 extern unsigned long __data_end;
390 extern unsigned long __bss_start;
391 extern unsigned long __bss_end;
393 unsigned long *src;
394 unsigned long *dest;
395 unsigned long tmp;
396 #endif
399 #ifdef DEBUG
400 puts("MAIN: starting c\n");
401 #endif
403 #ifdef CONFIG_KGDB /* builtin GDB stub */
405 /* Set up GDB stub, and make the first trap into it */
406 nios_gdb_install(1);
407 #ifdef CONFIG_BREAK_ON_START
408 puts( "MAIN: trapping to debugger - make sure nios-elf-gdb is running on host." );
409 nios_gdb_breakpoint();
410 nop();
411 #endif
413 #endif /* CONFIG_KGDB */
416 #if 0
417 puts("Testing RAM\n");
419 puts("Write...\n");
420 for (dest = (unsigned long *)0x40000000; dest < (unsigned long *)0x40080000; dest++) {
421 *dest = (unsigned long)0x5a5a5a5a ^ (unsigned long)dest;
424 puts("Read...\n");
425 for (dest = (unsigned long *)0x40000000; dest < (unsigned long *)0x40080000; dest++) {
426 tmp = (unsigned long)0x5a5a5a5a ^ (unsigned long)dest;
427 if (*dest != tmp) {
428 puts("Failed.");
429 outhex32((unsigned long)dest);
430 puts("is");
431 outhex32(*dest);
432 puts("wrote");
433 outhex32(tmp);
434 while(1);
438 puts("512k RAM\n");
439 if (testvar == 0xdeadbeef) puts("Found my key\n");
440 else puts("My keys are missing!\n");
442 // src = &__data_rom_start;
443 src = &__data_start;
444 dest = &__data_start;
445 while (dest < &__data_end) *(dest++) = *(src++);
447 dest = &__bss_start;
448 while (dest < &__bss_end) *(dest++) = 0;
450 puts("Moved .data\n");
451 if (testvar == 0xdeadbeef) puts("Found my key\n");
452 else puts("My keys are missing!\n");
454 testvar = 0;
455 #endif
458 #ifdef CONFIG_CRC_CHECK
459 #ifdef CONFIG_PROMPT_ON_MISSING_CRC_TABLES
460 if ( Test_Flash_Regions() )
461 #else
462 if ( Test_Flash_Regions() > 0 )
463 #endif
465 int c;
466 char tmp[3];
467 while ( getc() != -1 ) // flush input
470 putsNoNewLine( " Do you wish to continue (Y/N) ? " );
471 while ( 1 )
473 c = getc();
474 if ( c == -1 )
475 continue;
477 if ( !isprint( c ) )
478 c = '?';
480 sprintf( tmp, "\b%c", c );
481 putsNoNewLine( tmp );
482 c = toupper( c );
483 if ( c == 'Y' )
485 puts( "" );
486 break;
489 if ( c == 'N' )
491 puts( NL "***Trapping to monitor..." );
492 return -1;
496 puts( "***Starting kernel..." );
498 #endif
500 // Altera NiosII Custom shift instr(s) possibly //;dgt;
501 // assumed by memcpy, etc; ensure "correct" core //;dgt;
502 // loaded therefore if so. //;dgt;
504 #if defined(ALT_CI_ALIGN_32_N) //;dgt;
505 if(ALT_CI_ALIGN_32(1, 0xA9876543, //;dgt;
506 0xB210FEDC) != 0x10FEDCA9) //;dgt;
507 { //;dgt;
508 goto badshiftci_label; //;dgt;
509 } //;dgt;
510 if(ALT_CI_ALIGN_32(2, 0xA9876543, //;dgt;
511 0xB210FEDC) != 0xFEDCA987) //;dgt;
512 { //;dgt;
513 goto badshiftci_label; //;dgt;
514 } //;dgt;
515 if(ALT_CI_ALIGN_32(3, 0xA9876543, //;dgt;
516 0xB210FEDC) != 0xDCA98765) //;dgt;
517 { //;dgt;
518 goto badshiftci_label; //;dgt;
519 } //;dgt;
520 #endif //;dgt;
521 goto gudshiftci_label; //;dgt;
522 badshiftci_label: //;dgt;
523 { //;dgt;
524 unsigned char BadCImsg[] = //;dgt;
525 "?...ALT_CI_ALIGNn_321() NOT expected" //;dgt;
526 " NiosII custom instruction\n"; //;dgt;
527 unsigned char CIabortMsg[] = //;dgt;
528 " ...aborting uClinux startup..."; //;dgt;
530 #ifdef CONFIG_SERIAL_AJUART //;dgt;
531 #ifdef CONFIG_SERIAL_AJUART_CONSOLE //;dgt;
532 juart_console.index = 0; //;dgt;
533 jtaguart_console_write(&(juart_console), //;dgt;
534 BadCImsg, //;dgt;
535 strlen(BadCImsg)); //;dgt;
536 jtaguart_console_write(&(juart_console), //;dgt;
537 CIabortMsg, //;dgt;
538 strlen(CIabortMsg)); //;dgt;
539 #endif // CONFIG_SERIAL_AJUART //;dgt;
540 #endif // CONFIG_SERIAL_AJUART_CONSOLE //;dgt;
542 // #if defined(CONFIG_NIOS_SERIAL) //;dgt;
543 // #if defined(CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;
544 #if defined(nasys_printf_uart) //;dgt;
545 puts(BadCImsg); //;dgt;
546 puts(CIabortMsg); //;dgt;
547 #endif // nasys_printf_uart //;dgt;
548 // #endif // CONFIG_NIOS_SERIAL_CONSOLE) //;dgt;
549 // #endif // CONFIG_NIOS_SERIAL) //;dgt;
551 panic(" ...wrong fpga core?..."); //;dgt;
552 } //;dgt;
554 gudshiftci_label: //;dgt;
556 start_kernel();
557 return 0;