3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
6 * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <asm/byteorder.h>
29 #ifdef CONFIG_HAS_DATAFLASH
30 #include <dataflash.h>
32 //Patch by QNAP:Fix detect LCM
33 extern unsigned long mvGppValueGet(unsigned int group
, unsigned long mask
);
34 ///////////////////////////////////////
36 extern int do_reset (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[]);
37 extern void mvEgigaStrToMac( char *source
, char *dest
);
39 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
40 defined (CONFIG_CMDLINE_TAG) || \
41 defined (CONFIG_INITRD_TAG) || \
42 defined (CONFIG_SERIAL_TAG) || \
43 defined (CONFIG_REVISION_TAG) || \
44 defined (CONFIG_VFD) || \
45 defined (CONFIG_LCD) || \
46 defined (CONFIG_MARVELL_TAG)
49 static void setup_start_tag (bd_t
*bd
);
51 # ifdef CONFIG_SETUP_MEMORY_TAGS
52 static void setup_memory_tags (bd_t
*bd
);
54 static void setup_commandline_tag (bd_t
*bd
, char *commandline
);
57 static void setup_ramdisk_tag (bd_t
*bd
);
59 # ifdef CONFIG_INITRD_TAG
60 static void setup_initrd_tag (bd_t
*bd
, ulong initrd_start
,
63 static void setup_end_tag (bd_t
*bd
);
65 # if defined (CONFIG_VFD) || defined (CONFIG_LCD)
66 static void setup_videolfb_tag (gd_t
*gd
);
69 #if defined (CONFIG_MARVELL_TAG)
70 static void setup_marvell_tag(void);
73 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
74 static struct tag
*params
[2];
76 static struct tag
*params
[1];
78 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
80 #ifdef CONFIG_SHOW_BOOT_PROGRESS
81 # include <status_led.h>
82 # define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
84 # define SHOW_BOOT_PROGRESS(arg)
87 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
88 extern image_header_t header
[2]; /* from cmd_bootm.c */
90 extern image_header_t header
[1]; /* from cmd_bootm.c */
92 //Patch by QNAP:Fix detect LCM
93 extern int model_name_number
;
94 //////////////////////////////
95 void do_bootm_linux (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[],
96 ulong addr
, ulong
*len_ptr
, int verify
)
98 DECLARE_GLOBAL_DATA_PTR
;
100 ulong len
= 0, checksum
;
101 ulong initrd_start
, initrd_end
;
103 void (*theKernel
)(int zero
, int arch
, uint params
);
106 unsigned int cpu
= 0;
107 unsigned int cpuindex
= 0;
109 #ifdef CONFIG_CMDLINE_TAG
111 #ifdef CONFIG_MARVELL
116 commandline
= getenv ("bootargs");
119 commandline
= getenv ("bootargs2");
122 commandline
= getenv ("bootargs");
124 //Patch by QNAP:Fix detect LCM
125 if(model_name_number
<= 7){ // Model = TS419x
126 if(!mvGppValueGet(1,0x00002000)){
128 char *ptr
= strstr(commandline
,"console");
131 for(i
=0;i
< strlen(commandline
);i
++,ptr
++){
132 if(*ptr
!= ' ' && *ptr
!= '\n' && *ptr
!= 0x0)
139 ////////////////////////////////////
141 #if defined(DUAL_OS_SHARED_MEM_78200)
144 hdr
= &header
[cpuindex
];
145 theKernel
= (void (*)(int, int, uint
))ntohl(hdr
->ih_ep
);
147 debug(" theKernel %x\n", theKernel
);
150 * Check if there is an initrd image
153 SHOW_BOOT_PROGRESS (9);
155 addr
= simple_strtoul (argv
[2], NULL
, 16);
157 printf ("## Loading Ramdisk Image at %08lx ...\n", addr
);
159 /* Copy header so we can blank CRC field for re-calculation */
160 #ifdef CONFIG_HAS_DATAFLASH
161 if (addr_dataflash (addr
)) {
162 read_dataflash (addr
, sizeof (image_header_t
),
163 (char *) &header
[cpuindex
]);
166 memcpy (&header
[cpuindex
], (char *) addr
,
167 sizeof (image_header_t
));
169 if (ntohl (hdr
->ih_magic
) != IH_MAGIC
) {
170 printf ("Bad Magic Number\n");
171 SHOW_BOOT_PROGRESS (-10);
172 do_reset (cmdtp
, flag
, argc
, argv
);
175 data
= (ulong
) &header
[cpuindex
];
176 len
= sizeof (image_header_t
);
178 checksum
= ntohl (hdr
->ih_hcrc
);
181 if (crc32 (0, (const char *) data
, len
) != checksum
) {
182 printf ("Bad Header Checksum\n");
183 SHOW_BOOT_PROGRESS (-11);
184 do_reset (cmdtp
, flag
, argc
, argv
);
187 SHOW_BOOT_PROGRESS (10);
189 print_image_hdr (hdr
);
191 data
= addr
+ sizeof (image_header_t
);
192 len
= ntohl (hdr
->ih_size
);
194 #ifdef CONFIG_HAS_DATAFLASH
195 if (addr_dataflash (addr
)) {
196 read_dataflash (data
, len
, (char *) CFG_LOAD_ADDR
);
197 data
= CFG_LOAD_ADDR
;
204 printf (" Verifying Checksum ... ");
205 csum
= crc32 (0, (const char *) data
, len
);
206 if (csum
!= ntohl (hdr
->ih_dcrc
)) {
207 printf ("Bad Data CRC\n");
208 SHOW_BOOT_PROGRESS (-12);
209 do_reset (cmdtp
, flag
, argc
, argv
);
214 SHOW_BOOT_PROGRESS (11);
216 if ((hdr
->ih_os
!= IH_OS_LINUX
) ||
217 (hdr
->ih_arch
!= IH_CPU_ARM
) ||
218 (hdr
->ih_type
!= IH_TYPE_RAMDISK
)) {
219 printf ("No Linux ARM Ramdisk Image\n");
220 SHOW_BOOT_PROGRESS (-13);
221 do_reset (cmdtp
, flag
, argc
, argv
);
224 #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
226 *we need to copy the ramdisk to SRAM to let Linux boot
228 memmove ((void *) ntohl(hdr
->ih_load
), (uchar
*)data
, len
);
229 data
= ntohl(hdr
->ih_load
);
230 #endif /* CONFIG_B2 || CONFIG_EVB4510 */
233 * Now check if we have a multifile image
235 } else if ((hdr
->ih_type
== IH_TYPE_MULTI
) && (len_ptr
[1])) {
236 ulong tail
= ntohl (len_ptr
[0]) % 4;
239 SHOW_BOOT_PROGRESS (13);
241 /* skip kernel length and terminator */
242 data
= (ulong
) (&len_ptr
[2]);
243 /* skip any additional image length fields */
244 for (i
= 1; len_ptr
[i
]; ++i
)
246 /* add kernel length, and align */
247 data
+= ntohl (len_ptr
[0]);
252 len
= ntohl (len_ptr
[1]);
258 SHOW_BOOT_PROGRESS (14);
265 printf ("No initrd\n");
271 initrd_end
= initrd_start
+ len
;
277 SHOW_BOOT_PROGRESS (15);
279 debug ("## Transferring control to Linux (at address %08lx) ...\n",
282 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
283 /*Calculate boot params offset*/
284 bd
->bi_boot_params
= ntohl(hdr
->ih_ep
)-0x8000+0x100;
287 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
288 defined (CONFIG_CMDLINE_TAG) || \
289 defined (CONFIG_INITRD_TAG) || \
290 defined (CONFIG_SERIAL_TAG) || \
291 defined (CONFIG_REVISION_TAG) || \
292 defined (CONFIG_LCD) || \
293 defined (CONFIG_VFD) || \
294 defined (CONFIG_MARVELL_TAG)
295 setup_start_tag (bd
);
296 #ifdef CONFIG_SERIAL_TAG
297 setup_serial_tag (¶ms
[cpuindex
]);
299 #ifdef CONFIG_REVISION_TAG
300 setup_revision_tag (¶ms
[cpuindex
]);
302 #ifdef CONFIG_SETUP_MEMORY_TAGS
303 setup_memory_tags (bd
);
305 #ifdef CONFIG_CMDLINE_TAG
306 setup_commandline_tag (bd
, commandline
);
308 #ifdef CONFIG_INITRD_TAG
309 if (initrd_start
&& initrd_end
)
310 setup_initrd_tag (bd
, initrd_start
, initrd_end
);
312 #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
313 setup_videolfb_tag ((gd_t
*) gd
);
315 #if defined (CONFIG_MARVELL_TAG)
316 /* Linux open port doesn't support the Marvell TAG */
317 char *env
= getenv("mainlineLinux");
318 if(!env
|| ((strcmp(env
,"no") == 0) || (strcmp(env
,"No") == 0)))
319 setup_marvell_tag ();
324 /* we assume that the kernel is in place */
325 printf ("\nStarting kernel ...\n\n");
327 #ifdef CONFIG_USB_DEVICE
329 extern void udc_disconnect (void);
334 cleanup_before_linux ();
335 #if defined(CONFIG_MARVELL) && defined(DUAL_OS_SHARED_MEM_78200)
338 theKernel (0, bd
->bi_arch_number
, bd
->bi_boot_params
);
342 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
343 defined (CONFIG_CMDLINE_TAG) || \
344 defined (CONFIG_INITRD_TAG) || \
345 defined (CONFIG_SERIAL_TAG) || \
346 defined (CONFIG_REVISION_TAG) || \
347 defined (CONFIG_LCD) || \
348 defined (CONFIG_VFD) || \
349 defined (CONFIG_MARVELL_TAG)
350 static void setup_start_tag (bd_t
*bd
)
352 unsigned int cpu
= 0;
353 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
356 params
[cpu
] = (struct tag
*) bd
->bi_boot_params
;
357 params
[cpu
]->hdr
.tag
= ATAG_CORE
;
358 params
[cpu
]->hdr
.size
= tag_size (tag_core
);
360 params
[cpu
]->u
.core
.flags
= 0;
361 params
[cpu
]->u
.core
.pagesize
= 0;
362 params
[cpu
]->u
.core
.rootdev
= 0;
364 params
[cpu
] = tag_next (params
[cpu
]);
368 #ifdef CONFIG_SETUP_MEMORY_TAGS
369 static void setup_memory_tags (bd_t
*bd
)
372 unsigned int cpu
= 0;
373 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
377 for (i
= 0; i
< CONFIG_NR_DRAM_BANKS
; i
++) {
378 params
[cpu
]->hdr
.tag
= ATAG_MEM
;
379 params
[cpu
]->hdr
.size
= tag_size (tag_mem32
);
381 params
[cpu
]->u
.mem
.start
= bd
->bi_dram
[i
].start
;
382 params
[cpu
]->u
.mem
.size
= bd
->bi_dram
[i
].size
;
384 params
[cpu
] = tag_next (params
[cpu
]);
387 #endif /* CONFIG_SETUP_MEMORY_TAGS */
390 static void setup_commandline_tag (bd_t
*bd
, char *commandline
)
393 unsigned int cpu
= 0;
394 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
401 /* eat leading white space */
402 for (p
= commandline
; *p
== ' '; p
++);
404 /* skip non-existent command lines so the kernel will still
405 * use its default command line.
410 params
[cpu
]->hdr
.tag
= ATAG_CMDLINE
;
411 params
[cpu
]->hdr
.size
=
412 (sizeof (struct tag_header
) + strlen (p
) + 1 + 4) >> 2;
414 strcpy (params
[cpu
]->u
.cmdline
.cmdline
, p
);
415 params
[cpu
] = tag_next (params
[cpu
]);
419 #ifdef CONFIG_INITRD_TAG
420 static void setup_initrd_tag (bd_t
*bd
, ulong initrd_start
, ulong initrd_end
)
422 unsigned int cpu
= 0;
423 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
427 /* an ATAG_INITRD node tells the kernel where the compressed
428 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
430 params
[cpu
]->hdr
.tag
= ATAG_INITRD2
;
431 params
[cpu
]->hdr
.size
= tag_size (tag_initrd
);
433 params
[cpu
]->u
.initrd
.start
= initrd_start
;
434 params
[cpu
]->u
.initrd
.size
= initrd_end
- initrd_start
;
436 params
[cpu
] = tag_next (params
[cpu
]);
438 #endif /* CONFIG_INITRD_TAG */
441 #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
442 extern ulong
calc_fbsize (void);
443 static void setup_videolfb_tag (gd_t
*gd
)
445 unsigned int cpu
= 0;
446 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
450 /* An ATAG_VIDEOLFB node tells the kernel where and how large
451 * the framebuffer for video was allocated (among other things).
452 * Note that a _physical_ address is passed !
454 * We only use it to pass the address and size, the other entries
455 * in the tag_videolfb are not of interest.
457 params
[cpu
]->hdr
.tag
= ATAG_VIDEOLFB
;
458 params
[cpu
]->hdr
.size
= tag_size (tag_videolfb
);
460 params
[cpu
]->u
.videolfb
.lfb_base
= (u32
) gd
->fb_base
;
461 /* Fb size is calculated according to parameters for our panel
463 params
[cpu
]->u
.videolfb
.lfb_size
= calc_fbsize();
465 params
[cpu
] = tag_next (params
[cpu
]);
467 #endif /* CONFIG_VFD || CONFIG_LCD */
469 #if defined(CONFIG_MARVELL_TAG)
470 static void setup_marvell_tag (void)
475 unsigned int boardId
;
476 unsigned int cpu
= 0;
477 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
481 params
[cpu
]->hdr
.tag
= ATAG_MARVELL
;
482 params
[cpu
]->hdr
.size
= tag_size (tag_mv_uboot
);
484 params
[cpu
]->u
.mv_uboot
.uboot_version
= VER_NUM
;
485 if(strcmp(getenv("nandEcc"), "4bit") == 0)
487 params
[cpu
]->u
.mv_uboot
.nand_ecc
= 4;
489 else if(strcmp(getenv("nandEcc"), "1bit") == 0)
491 params
[cpu
]->u
.mv_uboot
.nand_ecc
= 1;
494 extern unsigned int mvBoardIdGet(void);
496 boardId
= mvBoardIdGet();
497 params
[cpu
]->u
.mv_uboot
.uboot_version
|= boardId
;
499 params
[cpu
]->u
.mv_uboot
.tclk
= CFG_TCLK
;
500 params
[cpu
]->u
.mv_uboot
.sysclk
= CFG_BUS_CLK
;
503 /* Dual CPU Firmware load address */
504 env
= getenv("fw_image_base");
506 params
[cpu
]->u
.mv_uboot
.fw_image_base
= simple_strtoul(env
, NULL
, 16);
508 params
[cpu
]->u
.mv_uboot
.fw_image_base
= 0;
510 /* Dual CPU Firmware size */
511 env
= getenv("fw_image_size");
513 params
[cpu
]->u
.mv_uboot
.fw_image_size
= simple_strtoul(env
, NULL
, 16);
515 params
[cpu
]->u
.mv_uboot
.fw_image_size
= 0;
518 #if defined(MV_INCLUDE_USB)
519 extern unsigned int mvCtrlUsbMaxGet(void);
521 for (i
= 0 ; i
< mvCtrlUsbMaxGet(); i
++)
523 sprintf( temp
, "usb%dMode", i
);
525 if((!env
) || (strcmp(env
,"Host") == 0 ) || (strcmp(env
,"host") == 0) )
526 params
[cpu
]->u
.mv_uboot
.isUsbHost
|= (1 << i
);
528 params
[cpu
]->u
.mv_uboot
.isUsbHost
&= ~(1 << i
);
531 #endif /*#if defined(MV_INCLUDE_USB)*/
532 #if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH)
533 extern unsigned int mvCtrlEthMaxPortGet(void);
534 extern int mvMacStrToHex(const char* macStr
, unsigned char* macHex
);
536 for (i
= 0 ;i
< 4;i
++)
538 memset(params
[cpu
]->u
.mv_uboot
.macAddr
[i
], 0, sizeof(params
[cpu
]->u
.mv_uboot
.macAddr
[i
]));
539 params
[cpu
]->u
.mv_uboot
.mtu
[i
] = 0;
542 for (i
= 0 ;i
< mvCtrlEthMaxPortGet();i
++)
544 /* only on RD-6281-A egiga0 defined as eth1 */
545 #if defined (RD_88F6281A)
546 sprintf( temp
,(i
==0 ? "eth1addr" : "ethaddr"));
548 sprintf( temp
,(i
? "eth%daddr" : "ethaddr"), i
);
553 mvMacStrToHex(env
, params
[cpu
]->u
.mv_uboot
.macAddr
[i
]);
555 /* only on RD-6281-A egiga0 defined as eth1 */
556 #if defined (RD_88F6281A)
557 sprintf( temp
,(i
==0 ? "eth1mtu" : "ethmtu"));
559 sprintf( temp
,(i
? "eth%dmtu" : "ethmtu"), i
);
564 params
[cpu
]->u
.mv_uboot
.mtu
[i
] = simple_strtoul(env
, NULL
, 10);
566 #endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */
568 params
[cpu
] = tag_next (params
[cpu
]);
572 #ifdef CONFIG_SERIAL_TAG
573 void setup_serial_tag (struct tag
**tmp
)
575 struct tag
*params
= *tmp
;
576 struct tag_serialnr serialnr
;
577 void get_board_serial(struct tag_serialnr
*serialnr
);
578 unsigned int cpu
= 0;
579 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
583 get_board_serial(&serialnr
);
584 params
[cpu
]->hdr
.tag
= ATAG_SERIAL
;
585 params
[cpu
]->hdr
.size
= tag_size (tag_serialnr
);
586 params
[cpu
]->u
.serialnr
.low
= serialnr
.low
;
587 params
[cpu
]->u
.serialnr
.high
= serialnr
.high
;
588 params
[cpu
] = tag_next (params
[cpu
]);
593 #ifdef CONFIG_REVISION_TAG
594 void setup_revision_tag(struct tag
**in_params
)
597 u32
get_board_rev(void);
598 unsigned int cpu
= 0;
599 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
603 rev
= get_board_rev();
604 params
[cpu
]->hdr
.tag
= ATAG_REVISION
;
605 params
[cpu
]->hdr
.size
= tag_size (tag_revision
);
606 params
[cpu
]->u
.revision
.rev
= rev
;
607 params
[cpu
] = tag_next (params
[cpu
]);
609 #endif /* CONFIG_REVISION_TAG */
612 static void setup_end_tag (bd_t
*bd
)
614 unsigned int cpu
= 0;
615 #if defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
619 params
[cpu
]->hdr
.tag
= ATAG_NONE
;
620 params
[cpu
]->hdr
.size
= 0;
623 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */