GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / mips / brcm-boards / bcm947xx / setup.c
blob4c3e2df5935edff45a7f002792dd775fb5220b48
1 /*
2 * HND MIPS boards setup routines
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: setup.c,v 1.23 2010-10-20 08:26:12 $
21 #include <linux/types.h>
22 #include <linux/version.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/serial.h>
26 #include <linux/serialP.h>
27 #include <linux/serial_core.h>
28 #include <linux/serial_8250.h> /* for early_serial_setup */
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
30 #include <linux/config.h>
31 #endif
32 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
33 #include <linux/blkdev.h>
34 #include <linux/ide.h>
35 #endif
36 #include <asm/bootinfo.h>
37 #include <asm/cpu.h>
38 #include <asm/time.h>
39 #include <asm/reboot.h>
41 #ifdef CONFIG_MTD_PARTITIONS
42 #include <linux/mtd/mtd.h>
43 #include <linux/mtd/partitions.h>
44 #include <linux/romfs_fs.h>
45 #include <linux/cramfs_fs.h>
46 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
47 #include <linux/squashfs_fs.h>
48 #else
49 /* #include <magic.h> */
50 #endif
51 #endif
52 #ifdef CONFIG_BLK_DEV_INITRD
53 #include <linux/initrd.h>
54 #endif
55 #include <typedefs.h>
56 #include <osl.h>
57 #include <bcmutils.h>
58 #include <bcmnvram.h>
59 #include <siutils.h>
60 #include <hndsoc.h>
61 #include <hndcpu.h>
62 #include <mips33_core.h>
63 #include <mips74k_core.h>
64 #include <sbchipc.h>
65 #include <hndchipc.h>
66 #include <hndpci.h>
67 #include <trxhdr.h>
68 #ifdef HNDCTF
69 #include <ctf/hndctf.h>
70 #endif /* HNDCTF */
71 #include "bcm947xx.h"
72 #ifdef CONFIG_MTD_NFLASH
73 #include "nflash.h"
74 #endif
75 #include "bcmdevs.h"
77 extern void bcm947xx_time_init(void);
78 extern void bcm947xx_timer_setup(struct irqaction *irq);
80 #ifdef CONFIG_KGDB
81 extern void set_debug_traps(void);
82 extern void rs_kgdb_hook(struct uart_port *);
83 extern void breakpoint(void);
84 #endif
86 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
87 extern struct ide_ops std_ide_ops;
88 #endif
90 struct dummy_super_block {
91 u32 s_magic ;
94 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
95 /* Enable CPU wait or not */
96 extern int cpu_wait_enable;
97 #else
98 int coherentio; /* init to 0 => no DMA cache coherency (may be set by user) */
99 int hw_coherentio;/* init to 0 => no HW DMA cache coherency (reflects real HW) */
100 #endif
102 /* Global SB handle */
103 si_t *bcm947xx_sih = NULL;
104 spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
105 EXPORT_SYMBOL(bcm947xx_sih);
106 EXPORT_SYMBOL(bcm947xx_sih_lock);
108 /* Convenience */
109 #define sih bcm947xx_sih
110 #define sih_lock bcm947xx_sih_lock
112 #ifdef HNDCTF
113 ctf_t *kcih = NULL;
114 EXPORT_SYMBOL(kcih);
115 ctf_attach_t ctf_attach_fn = NULL;
116 EXPORT_SYMBOL(ctf_attach_fn);
117 #endif /* HNDCTF */
119 /* Kernel command line */
120 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
121 extern char arcs_cmdline[CL_SIZE];
122 #endif
123 static int lanports_enable = 0;
126 EXPORT_SYMBOL( si_router_coma ); /* for loadable modules */
127 EXPORT_SYMBOL( hnd_jtagm_init );
128 EXPORT_SYMBOL( hnd_jtagm_disable );
129 EXPORT_SYMBOL( jtag_scan );
131 static void
132 bcm947xx_reboot_handler(void)
134 #ifndef BCMDBG
135 int wombo_reset;
136 #endif /* BCMDBG */
138 /* Reset the PCI(e) interfaces */
139 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
140 hndpci_deinit(sih);
142 if (lanports_enable) {
143 uint lp = 1 << lanports_enable;
145 si_gpioout(sih, lp, 0, GPIO_DRV_PRIORITY);
146 si_gpioouten(sih, lp, lp, GPIO_DRV_PRIORITY);
147 bcm_mdelay(1);
150 #ifndef BCMDBG
151 /* gpio 0 is also valid wombo_reset */
152 if ((wombo_reset = getgpiopin(NULL, "wombo_reset", GPIO_PIN_NOTDEFINED)) !=
153 GPIO_PIN_NOTDEFINED) {
154 int reset = 1 << wombo_reset;
156 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
157 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
158 bcm_mdelay(10);
160 #endif /* BCMDBG */
163 void
164 bcm947xx_machine_restart(char *command)
166 printk("Please stand by while rebooting the system...\n");
168 /* Set the watchdog timer to reset immediately */
169 local_irq_disable();
170 bcm947xx_reboot_handler();
171 hnd_cpu_reset(sih);
174 void
175 bcm947xx_machine_halt(void)
177 printk("System halted\n");
179 /* Disable interrupts and watchdog and spin forever */
180 local_irq_disable();
181 si_watchdog(sih, 0);
182 bcm947xx_reboot_handler();
183 while (1);
186 #ifdef CONFIG_SERIAL_CORE
188 static struct uart_port rs = {
189 line: 0,
190 flags: ASYNC_BOOT_AUTOCONF,
191 iotype: SERIAL_IO_MEM,
194 static void __init
195 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
197 rs.membase = regs;
198 rs.irq = irq + 2;
199 rs.uartclk = baud_base;
200 rs.regshift = reg_shift;
202 early_serial_setup(&rs);
204 rs.line++;
207 static void __init
208 serial_setup(si_t *sih)
210 si_serial_init(sih, serial_add);
212 #ifdef CONFIG_KGDB
213 /* Use the last port for kernel debugging */
214 if (rs.membase)
215 rs_kgdb_hook(&rs);
216 #endif
219 #endif /* CONFIG_SERIAL_CORE */
221 static int boot_flags(void)
223 int bootflags = 0;
224 char *val;
226 /* Only support chipcommon revision == 38 or BCM4706 for now */
227 if ((CHIPID(sih->chip) == BCM4706_CHIP_ID) || sih->ccrev == 38) {
228 if (sih->ccrev == 38 && (sih->chipst & (1 << 4)) != 0) {
229 /* This is NANDBOOT */
230 bootflags = FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH;
232 else if ((val = nvram_get("bootflags"))) {
233 bootflags = simple_strtol(val, NULL, 0);
234 bootflags &= FLASH_KERNEL_NFLASH;
238 return bootflags;
241 static int rootfs_mtdblock(void)
243 int bootflags;
244 int block = 0;
246 bootflags = boot_flags();
248 /* NANDBOOT */
249 if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) ==
250 (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH))
251 return 3;
253 /* SFLASH/PFLASH only */
254 if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) == 0)
255 return 2;
257 #ifdef BCMCONFMTD
258 block++;
259 #endif
260 /* Boot from norflash and kernel in nandflash */
261 return block+3;
264 void __init
265 brcm_setup(void)
267 char *value;
269 /* Get global SB handle */
270 sih = si_kattach(SI_OSH);
272 /* Initialize clocks and interrupts */
273 si_mips_init(sih, SBMIPS_VIRTIRQ_BASE);
275 if (BCM330X(current_cpu_data.processor_id) &&
276 (read_c0_diag() & BRCM_PFC_AVAIL)) {
278 * Now that the sih is inited set the proper PFC value
280 printk("Setting the PFC to its default value\n");
281 enable_pfc(PFC_AUTO);
285 #ifdef CONFIG_SERIAL_CORE
286 /* Initialize UARTs */
287 serial_setup(sih);
288 #endif /* CONFIG_SERIAL_CORE */
290 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
291 ide_ops = &std_ide_ops;
292 #endif
294 sprintf(arcs_cmdline, "root=/dev/mtdblock%d console=ttyS0,115200 init=/sbin/preinit", rootfs_mtdblock());
296 /* Override default command line arguments */
297 value = nvram_get("kernel_args");
298 if (value && strlen(value) && strncmp(value, "empty", 5))
299 strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
302 if ((lanports_enable = getgpiopin(NULL, "lanports_enable", GPIO_PIN_NOTDEFINED)) ==
303 GPIO_PIN_NOTDEFINED)
304 lanports_enable = 0;
307 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
308 /* Check if we want to enable cpu wait */
309 if (nvram_match("wait", "1"))
310 cpu_wait_enable = 1;
311 #endif
313 /* Generic setup */
314 _machine_restart = bcm947xx_machine_restart;
315 _machine_halt = bcm947xx_machine_halt;
316 pm_power_off = bcm947xx_machine_halt;
318 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
319 board_time_init = bcm947xx_time_init;
320 #endif
323 const char *
324 get_system_type(void)
326 static char s[32];
328 if (bcm947xx_sih) {
329 sprintf(s, "Broadcom BCM%X chip rev %d", bcm947xx_sih->chip,
330 bcm947xx_sih->chiprev);
331 return s;
333 else
334 return "Broadcom BCM947XX";
337 void __init
338 bus_error_init(void)
342 void __init
343 plat_mem_setup(void)
345 brcm_setup();
346 return;
349 #ifdef CONFIG_MTD_PARTITIONS
351 static struct mutex *mtd_mutex = NULL;
353 struct mutex *partitions_mutex_init(void)
355 if (!mtd_mutex) {
356 mtd_mutex = (struct mutex *)kzalloc(sizeof(struct mutex), GFP_KERNEL);
357 if (!mtd_mutex)
358 return NULL;
359 mutex_init(mtd_mutex);
361 return mtd_mutex;
363 EXPORT_SYMBOL(partitions_mutex_init);
365 /* Find out prom size */
366 static uint32 boot_partition_size(uint32 flash_phys) {
367 uint32 bootsz, *bisz;
369 /* Default is 256K boot partition */
370 bootsz = 256 * 1024;
372 /* Do we have a self-describing binary image? */
373 bisz = (uint32 *)KSEG1ADDR(flash_phys + BISZ_OFFSET);
374 if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) {
375 int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX];
377 if (isz > (1024 * 1024))
378 bootsz = 2048 * 1024;
379 else if (isz > (512 * 1024))
380 bootsz = 1024 * 1024;
381 else if (isz > (256 * 1024))
382 bootsz = 512 * 1024;
383 else if (isz <= (128 * 1024))
384 bootsz = 128 * 1024;
386 return bootsz;
389 #if defined(BCMCONFMTD) && defined(PLC)
390 #define FLASH_PARTS_NUM 7
391 #elif defined(BCMCONFMTD) || defined(PLC)
392 #define FLASH_PARTS_NUM 6
393 #else
394 #define FLASH_PARTS_NUM 5 /* boot;nvram;kernel;rootfs;empty */
395 #endif
397 static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
399 static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size)
401 struct romfs_super_block *romfsb;
402 struct cramfs_super *cramfsb;
403 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
404 struct squashfs_super_block *squashfsb;
405 #else
406 struct dummy_super_block *squashfsb;
407 #endif
408 struct trx_header *trx;
409 unsigned char buf[512];
410 int off;
411 size_t len;
413 romfsb = (struct romfs_super_block *) buf;
414 cramfsb = (struct cramfs_super *) buf;
415 squashfsb = (void *) buf;
416 trx = (struct trx_header *) buf;
418 /* Look at every 64 KB boundary */
419 for (off = 0; off < size; off += (64 * 1024)) {
420 memset(buf, 0xe5, sizeof(buf));
423 * Read block 0 to test for romfs and cramfs superblock
425 if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
426 len != sizeof(buf))
427 continue;
429 /* Try looking at TRX header for rootfs offset */
430 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
431 *trx_off = off;
432 if (trx->offsets[1] == 0)
433 continue;
435 * Read to test for romfs and cramfs superblock
437 off += le32_to_cpu(trx->offsets[1]);
438 memset(buf, 0xe5, sizeof(buf));
439 if (mtd->read(mtd, off, sizeof(buf), &len, buf) || len != sizeof(buf))
440 continue;
443 /* romfs is at block zero too */
444 if (romfsb->word0 == ROMSB_WORD0 &&
445 romfsb->word1 == ROMSB_WORD1) {
446 printk(KERN_NOTICE
447 "%s: romfs filesystem found at block %d\n",
448 mtd->name, off / mtd->erasesize);
449 break;
452 /* so is cramfs */
453 if (cramfsb->magic == CRAMFS_MAGIC) {
454 printk(KERN_NOTICE
455 "%s: cramfs filesystem found at block %d\n",
456 mtd->name, off / mtd->erasesize);
457 break;
459 if (squashfsb->s_magic == SQUASHFS_MAGIC) {
460 printk(KERN_NOTICE
461 "%s: squash filesystem found at block %d\n",
462 mtd->name, off / mtd->erasesize);
463 break;
467 return off;
469 struct mtd_partition *
470 init_mtd_partitions(struct mtd_info *mtd, size_t size)
472 int bootflags;
473 int nparts = 0;
474 uint32 offset = 0;
475 uint rfs_off = 0;
476 uint vmlz_off, knl_size;
477 uint32 top = 0;
478 uint32 bootsz;
480 bootflags = boot_flags();
482 if ((bootflags & FLASH_KERNEL_NFLASH) != FLASH_KERNEL_NFLASH) {
483 rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size);
485 /* Size pmon */
486 bcm947xx_flash_parts[nparts].name = "boot";
487 bcm947xx_flash_parts[nparts].size = vmlz_off;
488 bcm947xx_flash_parts[nparts].offset = top;
489 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
490 nparts++;
492 /* Setup kernel MTD partition */
493 bcm947xx_flash_parts[nparts].name = "linux";
494 bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
496 #ifdef PLC
497 /* Reserve for PLC */
498 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
499 #endif
500 /* Reserve for NVRAM */
501 bcm947xx_flash_parts[nparts].size -= ROUNDUP(NVRAM_SPACE, mtd->erasesize);
503 #ifdef BCMCONFMTD
504 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
505 #endif
506 bcm947xx_flash_parts[nparts].offset = vmlz_off;
507 knl_size = bcm947xx_flash_parts[nparts].size;
508 offset = bcm947xx_flash_parts[nparts].offset + knl_size;
509 nparts++;
511 /* Setup rootfs MTD partition */
512 bcm947xx_flash_parts[nparts].name = "rootfs";
513 bcm947xx_flash_parts[nparts].size = knl_size - (rfs_off - vmlz_off);
514 bcm947xx_flash_parts[nparts].offset = rfs_off;
515 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
516 nparts++;
517 } else {
518 bootsz = boot_partition_size(SI_FLASH2);
519 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
520 /* Size pmon */
521 bcm947xx_flash_parts[nparts].name = "boot";
522 bcm947xx_flash_parts[nparts].size = bootsz;
523 bcm947xx_flash_parts[nparts].offset = top;
524 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
525 offset = bcm947xx_flash_parts[nparts].size;
526 nparts++;
529 #ifdef BCMCONFMTD
530 /* Setup CONF MTD partition */
531 bcm947xx_flash_parts[nparts].name = "confmtd";
532 bcm947xx_flash_parts[nparts].size = mtd->erasesize * 4;
533 bcm947xx_flash_parts[nparts].offset = offset;
534 offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
535 nparts++;
536 #endif /* BCMCONFMTD */
538 #ifdef PLC
539 /* Setup plc MTD partition */
540 bcm947xx_flash_parts[nparts].name = "plc";
541 bcm947xx_flash_parts[nparts].size = ROUNDUP(0x1000, mtd->erasesize);
542 bcm947xx_flash_parts[nparts].offset = size - (ROUNDUP(NVRAM_SPACE, mtd->erasesize) + ROUNDUP(0x1000, mtd->erasesize));
543 nparts++;
544 #endif
546 /* Setup nvram MTD partition */
547 bcm947xx_flash_parts[nparts].name = "nvram";
548 bcm947xx_flash_parts[nparts].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
549 bcm947xx_flash_parts[nparts].offset = size - bcm947xx_flash_parts[nparts].size;
550 nparts++;
552 return bcm947xx_flash_parts;
555 EXPORT_SYMBOL(init_mtd_partitions);
557 #ifdef CONFIG_MTD_NFLASH
558 #define NFLASH_PARTS_NUM 6
559 static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {{0}};
561 static uint lookup_nflash_rootfs_offset(struct mtd_info *mtd, int offset, size_t size)
563 struct romfs_super_block *romfsb;
564 struct cramfs_super *cramfsb;
565 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
566 struct squashfs_super_block *squashfsb;
567 #else
568 struct dummy_super_block *squashfsb;
569 #endif
570 struct trx_header *trx;
571 unsigned char buf[NFL_SECTOR_SIZE];
572 uint blocksize, mask, blk_offset, off, shift = 0;
573 chipcregs_t *cc;
574 int ret;
576 romfsb = (struct romfs_super_block *) buf;
577 cramfsb = (struct cramfs_super *) buf;
578 squashfsb = (void *) buf;
579 trx = (struct trx_header *) buf;
581 if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL)
582 return 0;
584 /* Look at every block boundary till 16MB; higher space is reserved for application data. */
585 blocksize = mtd->erasesize;
586 printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
587 for (off = offset; off < NFL_BOOT_OS_SIZE; off += blocksize) {
588 mask = blocksize - 1;
589 blk_offset = off & ~mask;
590 if (nflash_checkbadb(sih, cc, blk_offset) != 0)
591 continue;
592 memset(buf, 0xe5, sizeof(buf));
593 if ((ret = nflash_read(sih, cc, off, sizeof(buf), buf)) != sizeof(buf)) {
594 printk(KERN_NOTICE
595 "%s: nflash_read return %d\n", mtd->name, ret);
596 continue;
599 /* Try looking at TRX header for rootfs offset */
600 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
601 mask = NFL_SECTOR_SIZE - 1;
602 off = offset + (le32_to_cpu(trx->offsets[1]) & ~mask) - blocksize;
603 shift = (le32_to_cpu(trx->offsets[1]) & mask);
604 romfsb = (struct romfs_super_block *)((unsigned char *)romfsb + shift);
605 cramfsb = (struct cramfs_super *)((unsigned char *)cramfsb + shift);
606 squashfsb = (void *)((unsigned char *)squashfsb + shift);
607 continue;
610 /* romfs is at block zero too */
611 if (romfsb->word0 == ROMSB_WORD0 &&
612 romfsb->word1 == ROMSB_WORD1) {
613 printk(KERN_NOTICE
614 "%s: romfs filesystem found at block %d\n",
615 mtd->name, off / blocksize);
616 break;
619 /* so is cramfs */
620 if (cramfsb->magic == CRAMFS_MAGIC) {
621 printk(KERN_NOTICE
622 "%s: cramfs filesystem found at block %d\n",
623 mtd->name, off / blocksize);
624 break;
627 if (squashfsb->s_magic == SQUASHFS_MAGIC) {
628 printk(KERN_NOTICE
629 "%s: squash filesystem found at block %d\n",
630 mtd->name, off / blocksize);
631 break;
634 return shift + off;
637 struct mtd_partition * init_nflash_mtd_partitions(struct mtd_info *mtd, size_t size)
639 int bootflags;
640 int nparts = 0;
641 uint32 offset = 0;
642 uint shift = 0;
643 uint32 top = 0;
644 uint32 bootsz;
646 bootflags = boot_flags();
647 if ((bootflags & FLASH_BOOT_NFLASH) == FLASH_BOOT_NFLASH) {
648 bootsz = boot_partition_size(SI_FLASH1);
649 if (bootsz > mtd->erasesize) {
650 /* Prepare double space in case of bad blocks */
651 bootsz = (bootsz << 1);
652 } else {
653 /* CFE occupies at least one block */
654 bootsz = mtd->erasesize;
656 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
658 /* Size pmon */
659 bcm947xx_nflash_parts[nparts].name = "boot";
660 bcm947xx_nflash_parts[nparts].size = bootsz;
661 bcm947xx_nflash_parts[nparts].offset = top;
662 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
663 offset = bcm947xx_nflash_parts[nparts].size;
664 nparts++;
666 /* Setup NVRAM MTD partition */
667 bcm947xx_nflash_parts[nparts].name = "nvram";
668 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_SIZE - offset;
669 bcm947xx_nflash_parts[nparts].offset = offset;
671 offset = NFL_BOOT_SIZE;
672 nparts++;
675 if ((bootflags & FLASH_KERNEL_NFLASH) == FLASH_KERNEL_NFLASH) {
676 /* Setup kernel MTD partition */
677 bcm947xx_nflash_parts[nparts].name = "linux";
678 bcm947xx_nflash_parts[nparts].size = nparts ? (NFL_BOOT_OS_SIZE - NFL_BOOT_SIZE) : NFL_BOOT_OS_SIZE;
679 bcm947xx_nflash_parts[nparts].offset = offset;
681 shift = lookup_nflash_rootfs_offset(mtd, offset, size);
683 offset = NFL_BOOT_OS_SIZE;
684 nparts++;
686 /* Setup rootfs MTD partition */
687 bcm947xx_nflash_parts[nparts].name = "rootfs";
688 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
689 bcm947xx_nflash_parts[nparts].offset = shift;
690 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
692 nparts++;
695 return bcm947xx_nflash_parts;
698 EXPORT_SYMBOL(init_nflash_mtd_partitions);
699 #endif /* CONFIG_MTD_NFLASH */
701 #ifdef CONFIG_BLK_DEV_INITRD
702 extern char _end;
704 /* The check_ramdisk_trx has more exact qualification to look at TRX header from end of linux */
705 static __init int
706 check_ramdisk_trx(unsigned long offset, unsigned long ram_size)
708 struct trx_header *trx;
709 uint32 crc;
710 unsigned int len;
711 uint8 *ptr = (uint8 *)offset;
713 trx = (struct trx_header *)ptr;
715 /* Not a TRX_MAGIC */
716 if (le32_to_cpu(trx->magic) != TRX_MAGIC) {
717 printk("check_ramdisk_trx: not a valid TRX magic\n");
718 return -1;
721 /* TRX len invalid */
722 len = le32_to_cpu(trx->len);
723 if (offset + len > ram_size) {
724 printk("check_ramdisk_trx: not a valid TRX length\n");
725 return -1;
728 /* Checksum over header */
729 crc = hndcrc32((uint8 *) &trx->flag_version,
730 sizeof(struct trx_header) - OFFSETOF(struct trx_header, flag_version),
731 CRC32_INIT_VALUE);
733 /* Move ptr to data */
734 ptr += sizeof(struct trx_header);
735 len -= sizeof(struct trx_header);
737 /* Checksum over data */
738 crc = hndcrc32(ptr, len, crc);
740 /* Verify checksum */
741 if (le32_to_cpu(trx->crc32) != crc) {
742 printk("check_ramdisk_trx: checksum invalid\n");
743 return -1;
746 return 0;
749 void __init init_ramdisk(unsigned long mem_end)
751 struct trx_header *trx = NULL;
752 char *from_rootfs, *to_rootfs;
753 unsigned long rootfs_size = 0;
754 unsigned long ram_size = mem_end + 0x80000000;
755 unsigned long offset;
756 char *root_cmd = "root=/dev/ram0 console=ttyS0,115200 rdinit=/sbin/preinit";
758 to_rootfs = (char *)(((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK);
759 offset = ((unsigned long)&_end +0xffff) & ~0xffff;
761 /* Look at TRX header from end of linux */
762 for (; offset < ram_size; offset += 0x10000) {
763 trx = (struct trx_header *)offset;
764 if (le32_to_cpu(trx->magic) == TRX_MAGIC &&
765 check_ramdisk_trx(offset, ram_size) == 0) {
766 printk(KERN_NOTICE
767 "Found TRX image at %08lx\n", offset);
768 from_rootfs = (char *)((unsigned long)trx + le32_to_cpu(trx->offsets[1]));
769 rootfs_size = le32_to_cpu(trx->len) - le32_to_cpu(trx->offsets[1]);
770 rootfs_size = (rootfs_size + 0xffff) & ~0xffff;
771 printk("rootfs size is %ld bytes at 0x%p, copying to 0x%p\n", rootfs_size, from_rootfs, to_rootfs);
772 memmove(to_rootfs, from_rootfs, rootfs_size);
774 initrd_start = (int)to_rootfs;
775 initrd_end = initrd_start + rootfs_size;
776 strncpy(arcs_cmdline, root_cmd, sizeof(arcs_cmdline));
778 * In case the system warm boot, the memory won't be zeroed.
779 * So we have to erase trx magic.
781 if (initrd_end < (unsigned long)trx)
782 trx->magic = 0;
783 break;
787 #endif
788 #endif