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>
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
)
54 while (!(nasys_printf_uart
->np_uartstatus
&
55 np_uartstatus_trdy_mask
));
56 nasys_printf_uart
->np_uarttxdata
= *s
++;
61 static void puts(unsigned char *s
)
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;
73 #define outchar(X) { \
74 while (!(nasys_printf_uart->np_uartstatus & np_uartstatus_trdy_mask)); \
75 nasys_printf_uart->np_uarttxdata = (X); }
77 #define outchar(X) putchar(X)
79 #define outhex(X,Y) { \
81 __w = ((X) >> (Y)) & 0xf; \
82 __w = __w > 0x9 ? 'A' + __w - 0xa : '0' + __w; \
84 #define outhex8(X) { \
87 #define outhex16(X) { \
92 #define outhex32(X) { \
104 static unsigned long testvar
= 0xdeadbeef;
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
,
174 U32
Calc_CRC( const U8
*p
, U32 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] = {
199 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
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))
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]*/
228 long int tm_gmtoff
; /* Seconds east of UTC. */
229 __const
char *tm_zone
; /* Timezone abbreviation. */
231 long int __tm_gmtoff
; /* Seconds east of UTC. */
232 __const
char *__tm_zone
; /* Timezone abbreviation. */
236 void __tm_conv(struct tm
*tmbuf
, time_t *t
, time_t offset
)
240 register const unsigned short int *ip
;
244 days
= *t
/ SECS_PER_DAY
;
245 rem
= *t
% SECS_PER_DAY
;
252 while (rem
>= SECS_PER_DAY
)
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)
269 while (days
>= (rem
= __isleap(y
) ? 366 : 365))
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
)
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];
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 );
310 /******************************************************/
313 /* hjz: polled-I/O: Get a char if one is ready, or return -1 */
316 if ( nasys_printf_uart
->np_uartstatus
& np_uartstatus_rrdy_mask
)
317 return nasys_printf_uart
->np_uartrxdata
;
323 typedef unsigned long off_t
;
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 + "..."
336 int Test_Flash_Regions(void)
338 FLASH_REGION_DESC
*pRegion
= (FLASH_REGION_DESC
*)&__CRC_Table_Begin
;
341 int nrFailedRegions
= 0;
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." );
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
)
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
378 return nrFailedRegions
;
380 #endif /* CONFIG_CRC_CHECK */
384 extern void start_kernel(void);
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
;
400 puts("MAIN: starting c\n");
403 #ifdef CONFIG_KGDB /* builtin GDB stub */
405 /* Set up GDB stub, and make the first trap into it */
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();
413 #endif /* CONFIG_KGDB */
417 puts("Testing RAM\n");
420 for (dest
= (unsigned long *)0x40000000; dest
< (unsigned long *)0x40080000; dest
++) {
421 *dest
= (unsigned long)0x5a5a5a5a ^ (unsigned long)dest
;
425 for (dest
= (unsigned long *)0x40000000; dest
< (unsigned long *)0x40080000; dest
++) {
426 tmp
= (unsigned long)0x5a5a5a5a ^ (unsigned long)dest
;
429 outhex32((unsigned long)dest
);
439 if (testvar
== 0xdeadbeef) puts("Found my key\n");
440 else puts("My keys are missing!\n");
442 // src = &__data_rom_start;
444 dest
= &__data_start
;
445 while (dest
< &__data_end
) *(dest
++) = *(src
++);
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");
458 #ifdef CONFIG_CRC_CHECK
459 #ifdef CONFIG_PROMPT_ON_MISSING_CRC_TABLES
460 if ( Test_Flash_Regions() )
462 if ( Test_Flash_Regions() > 0 )
467 while ( getc() != -1 ) // flush input
470 putsNoNewLine( " Do you wish to continue (Y/N) ? " );
480 sprintf( tmp
, "\b%c", c
);
481 putsNoNewLine( tmp
);
491 puts( NL
"***Trapping to monitor..." );
496 puts( "***Starting kernel..." );
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;
508 goto badshiftci_label
; //;dgt;
510 if(ALT_CI_ALIGN_32(2, 0xA9876543, //;dgt;
511 0xB210FEDC) != 0xFEDCA987) //;dgt;
513 goto badshiftci_label
; //;dgt;
515 if(ALT_CI_ALIGN_32(3, 0xA9876543, //;dgt;
516 0xB210FEDC) != 0xDCA98765) //;dgt;
518 goto badshiftci_label
; //;dgt;
521 goto gudshiftci_label
; //;dgt;
522 badshiftci_label
: //;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;
535 strlen(BadCImsg
)); //;dgt;
536 jtaguart_console_write(&(juart_console
), //;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;
554 gudshiftci_label
: //;dgt;