allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / mips / brcm-boards / bcm947xx / setup.c
blob97747eecaf067ea38f9e0752ac354f21950ad7f7
1 /*
2 * HND MIPS boards setup routines
4 * Copyright (C) 2011, 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/config.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 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
29 #include <linux/blkdev.h>
30 #include <linux/ide.h>
31 #endif
32 #include <asm/bootinfo.h>
33 #include <asm/cpu.h>
34 #include <asm/time.h>
35 #include <asm/reboot.h>
37 #ifdef CONFIG_MTD_PARTITIONS
38 #include <linux/mtd/mtd.h>
39 #include <linux/mtd/partitions.h>
40 #include <linux/romfs_fs.h>
41 #include <linux/cramfs_fs.h>
42 #include <linux/squashfs_fs.h>
43 #endif
44 #ifdef CONFIG_BLK_DEV_INITRD
45 #include <linux/initrd.h>
46 #endif
47 #include <typedefs.h>
48 #include <osl.h>
49 #include <bcmutils.h>
50 #include <bcmnvram.h>
51 #include <siutils.h>
52 #include <hndsoc.h>
53 #include <hndcpu.h>
54 #include <mips33_core.h>
55 #include <mips74k_core.h>
56 #include <sbchipc.h>
57 #include <hndchipc.h>
58 #include <hndpci.h>
59 #include <trxhdr.h>
60 #ifdef HNDCTF
61 #include <ctf/hndctf.h>
62 #endif /* HNDCTF */
63 #include "bcm947xx.h"
64 #ifdef CONFIG_MTD_NFLASH
65 #include "nflash.h"
66 #endif
67 #include "bcmdevs.h"
69 extern void bcm947xx_time_init(void);
70 extern void bcm947xx_timer_setup(struct irqaction *irq);
72 #ifdef CONFIG_KGDB
73 extern void set_debug_traps(void);
74 extern void rs_kgdb_hook(struct uart_port *);
75 extern void breakpoint(void);
76 #endif
78 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
79 extern struct ide_ops std_ide_ops;
80 #endif
82 /* Enable CPU wait or not */
83 extern int cpu_wait_enable;
85 /* Global assert type */
86 extern uint32 g_assert_type;
88 /* Global SB handle */
89 si_t *bcm947xx_sih = NULL;
90 spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
91 EXPORT_SYMBOL(bcm947xx_sih);
92 EXPORT_SYMBOL(bcm947xx_sih_lock);
94 /* CPU freq */
95 int bcm947xx_cpu_clk;
96 EXPORT_SYMBOL(bcm947xx_cpu_clk);
98 /* Convenience */
99 #define sih bcm947xx_sih
100 #define sih_lock bcm947xx_sih_lock
102 #ifdef HNDCTF
103 ctf_t *kcih = NULL;
104 EXPORT_SYMBOL(kcih);
105 ctf_attach_t ctf_attach_fn = NULL;
106 EXPORT_SYMBOL(ctf_attach_fn);
107 #endif /* HNDCTF */
109 /* Kernel command line */
110 extern char arcs_cmdline[CL_SIZE];
111 static int lanports_enable = 0;
113 static void
114 bcm947xx_reboot_handler(void)
116 #ifndef BCMDBG
117 int wombo_reset;
118 #endif /* BCMDBG */
120 /* Reset the PCI(e) interfaces */
121 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
122 hndpci_deinit(sih);
124 if (lanports_enable) {
125 uint lp = 1 << lanports_enable;
127 si_gpioout(sih, lp, 0, GPIO_DRV_PRIORITY);
128 si_gpioouten(sih, lp, lp, GPIO_DRV_PRIORITY);
129 bcm_mdelay(1);
132 #ifndef BCMDBG
133 /* gpio 0 is also valid wombo_reset */
134 if ((wombo_reset = getgpiopin(NULL, "wombo_reset", GPIO_PIN_NOTDEFINED)) !=
135 GPIO_PIN_NOTDEFINED) {
136 int reset = 1 << wombo_reset;
138 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
139 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
140 bcm_mdelay(10);
142 #endif /* BCMDBG */
145 void
146 bcm947xx_machine_restart(char *command)
148 printk("Please stand by while rebooting the system...\n");
150 /* Set the watchdog timer to reset immediately */
151 local_irq_disable();
152 bcm947xx_reboot_handler();
153 hnd_cpu_reset(sih);
156 void
157 bcm947xx_machine_halt(void)
159 printk("System halted\n");
161 /* Disable interrupts and watchdog and spin forever */
162 local_irq_disable();
163 si_watchdog(sih, 0);
164 bcm947xx_reboot_handler();
165 while (1);
168 #ifdef CONFIG_SERIAL_CORE
170 static struct uart_port rs = {
171 line: 0,
172 flags: ASYNC_BOOT_AUTOCONF,
173 iotype: SERIAL_IO_MEM,
176 static void __init
177 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
179 rs.membase = regs;
180 rs.irq = irq + 2;
181 rs.uartclk = baud_base;
182 rs.regshift = reg_shift;
184 early_serial_setup(&rs);
186 rs.line++;
189 static void __init
190 serial_setup(si_t *sih)
192 si_serial_init(sih, serial_add);
194 #ifdef CONFIG_KGDB
195 /* Use the last port for kernel debugging */
196 if (rs.membase)
197 rs_kgdb_hook(&rs);
198 #endif
201 #endif /* CONFIG_SERIAL_CORE */
203 int boot_flags(void)
205 int bootflags = 0;
206 char *val;
208 /* Only support chipcommon revision == 38 or BCM4706 for now */
209 if ((CHIPID(sih->chip) == BCM4706_CHIP_ID) || sih->ccrev == 38) {
210 if (sih->ccrev == 38 && (sih->chipst & (1 << 4)) != 0) {
211 /* This is NANDBOOT */
212 bootflags = FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH;
214 else if ((val = nvram_get("bootflags"))) {
215 bootflags = simple_strtol(val, NULL, 0);
216 bootflags &= FLASH_KERNEL_NFLASH;
220 return bootflags;
223 static int rootfs_mtdblock(void)
225 int bootflags;
226 int block = 0;
227 #ifdef CONFIG_FAILSAFE_UPGRADE
228 char *img_boot = nvram_get(BOOTPARTITION);
229 #endif
230 bootflags = boot_flags();
232 /* NANDBOOT */
233 if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) ==
234 (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH))
235 #ifdef CONFIG_FAILSAFE_UPGRADE
237 if (img_boot && simple_strtol(img_boot, NULL, 10))
238 return 5;
239 else
240 return 3;
242 #else
243 return 3;
244 #endif
246 /* SFLASH/PFLASH only */
247 if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) == 0)
248 #ifdef CONFIG_FAILSAFE_UPGRADE
250 if (img_boot && simple_strtol(img_boot, NULL, 10))
251 return 4;
252 else
253 return 2;
255 #else
256 return 2;
257 #endif
259 #ifdef BCMCONFMTD
260 block++;
261 #endif
262 #ifdef CONFIG_FAILSAFE_UPGRADE
263 if (img_boot && simple_strtol(img_boot, NULL, 10))
264 block+=2;
265 #endif
266 /* Boot from norflash and kernel in nandflash */
267 return block+3;
270 void __init
271 brcm_setup(void)
273 uint leave_coma;
274 char *value;
275 int disable_usb;
277 /* Get global SB handle */
278 sih = si_kattach(SI_OSH);
280 /* Initialize clocks and interrupts */
281 si_mips_init(sih, SBMIPS_VIRTIRQ_BASE);
283 if (BCM330X(current_cpu_data.processor_id) &&
284 (read_c0_diag() & BRCM_PFC_AVAIL)) {
286 * Now that the sih is inited set the proper PFC value
288 printk("Setting the PFC to its default value\n");
289 enable_pfc(PFC_AUTO);
293 #ifdef CONFIG_SERIAL_CORE
294 /* Initialize UARTs */
295 serial_setup(sih);
296 #endif /* CONFIG_SERIAL_CORE */
298 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
299 ide_ops = &std_ide_ops;
300 #endif
302 if (strncmp(arcs_cmdline, "root=/dev/mtdblock", strlen("root=/dev/mtdblock")) == 0)
303 sprintf(arcs_cmdline, "root=/dev/mtdblock%d console=ttyS0,115200", rootfs_mtdblock());
305 /* Override default command line arguments */
306 value = nvram_get("kernel_args");
307 if (value && strlen(value) && strncmp(value, "empty", 5))
308 strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
311 value = nvram_get("assert_type");
312 if (value && strlen(value))
313 g_assert_type = simple_strtoul(value, NULL, 10);
316 if ((lanports_enable = getgpiopin(NULL, "lanports_enable", GPIO_PIN_NOTDEFINED)) ==
317 GPIO_PIN_NOTDEFINED)
318 lanports_enable = 0;
320 /* Init gpio status for coma mode support via wps button */
321 leave_coma = getgpiopin(NULL, "leave_coma", GPIO_PIN_NOTDEFINED);
322 if (leave_coma != GPIO_PIN_NOTDEFINED) {
323 int leave_coma_mask = 1 << leave_coma;
325 si_gpioout(sih, leave_coma_mask, 0, GPIO_HI_PRIORITY);
326 si_gpioouten(sih, leave_coma_mask, leave_coma_mask, GPIO_HI_PRIORITY);
329 /* Set gpio HIGH to turn on USB VBUS power */
330 disable_usb = getgpiopin(NULL, "disable_usb", GPIO_PIN_NOTDEFINED);
331 if (disable_usb != GPIO_PIN_NOTDEFINED) {
332 int disable_usb_mask = 1 << disable_usb;
334 si_gpioout(sih, disable_usb_mask, disable_usb_mask, GPIO_DRV_PRIORITY);
335 si_gpioouten(sih, disable_usb_mask, disable_usb_mask, GPIO_DRV_PRIORITY);
338 /* Check if we want to enable cpu wait */
339 if (nvram_match("wait", "1"))
340 cpu_wait_enable = 1;
342 /* Generic setup */
343 _machine_restart = bcm947xx_machine_restart;
344 _machine_halt = bcm947xx_machine_halt;
345 pm_power_off = bcm947xx_machine_halt;
347 board_time_init = bcm947xx_time_init;
350 const char *
351 get_system_type(void)
353 static char s[32];
355 if (bcm947xx_sih) {
356 sprintf(s, "Broadcom BCM%X chip rev %d", bcm947xx_sih->chip,
357 bcm947xx_sih->chiprev);
358 return s;
360 else
361 return "Broadcom BCM947XX";
364 void __init
365 bus_error_init(void)
369 void __init
370 plat_mem_setup(void)
372 brcm_setup();
373 return;
376 #ifdef CONFIG_MTD_PARTITIONS
378 static struct mutex *mtd_mutex = NULL;
380 struct mutex *partitions_mutex_init()
382 if (!mtd_mutex) {
383 mtd_mutex = (struct mutex *)kzalloc(sizeof(struct mutex), GFP_KERNEL);
384 if (!mtd_mutex)
385 return NULL;
386 mutex_init(mtd_mutex);
388 return mtd_mutex;
390 EXPORT_SYMBOL(partitions_mutex_init);
392 /* Find out prom size */
393 static uint32 boot_partition_size(uint32 flash_phys) {
394 uint32 bootsz, *bisz;
396 /* Default is 256K boot partition */
397 bootsz = 256 * 1024;
399 /* Do we have a self-describing binary image? */
400 bisz = (uint32 *)KSEG1ADDR(flash_phys + BISZ_OFFSET);
401 if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) {
402 int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX];
404 if (isz > (1024 * 1024))
405 bootsz = 2048 * 1024;
406 else if (isz > (512 * 1024))
407 bootsz = 1024 * 1024;
408 else if (isz > (256 * 1024))
409 bootsz = 512 * 1024;
410 else if (isz <= (128 * 1024))
411 bootsz = 128 * 1024;
413 return bootsz;
417 #if defined(BCMCONFMTD)
418 #define MTD_PARTS 1
419 #else
420 #define MTD_PARTS 0
421 #endif
422 #if defined(PLC)
423 #define PLC_PARTS 1
424 #else
425 #define PLC_PARTS 0
426 #endif
427 #if defined(CONFIG_FAILSAFE_UPGRADE)
428 #define FAILSAFE_PARTS 2
429 #else
430 #define FAILSAFE_PARTS 0
431 #endif
432 /* boot;nvram;kernel;rootfs;empty */
433 #define FLASH_PARTS_NUM (5+MTD_PARTS+PLC_PARTS+FAILSAFE_PARTS)
435 static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
437 static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size)
439 struct romfs_super_block *romfsb;
440 struct cramfs_super *cramfsb;
441 struct squashfs_super_block *squashfsb;
442 struct trx_header *trx;
443 unsigned char buf[512];
444 int off;
445 size_t len;
447 romfsb = (struct romfs_super_block *) buf;
448 cramfsb = (struct cramfs_super *) buf;
449 squashfsb = (struct squashfs_super_block *) buf;
450 trx = (struct trx_header *) buf;
452 /* Look at every 64 KB boundary */
453 for (off = *trx_off; off < size; off += (64 * 1024)) {
454 memset(buf, 0xe5, sizeof(buf));
457 * Read block 0 to test for romfs and cramfs superblock
459 if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
460 len != sizeof(buf))
461 continue;
463 /* Try looking at TRX header for rootfs offset */
464 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
465 *trx_off = off;
466 if (trx->offsets[1] == 0)
467 continue;
469 * Read to test for romfs and cramfs superblock
471 off += le32_to_cpu(trx->offsets[1]);
472 memset(buf, 0xe5, sizeof(buf));
473 if (mtd->read(mtd, off, sizeof(buf), &len, buf) || len != sizeof(buf))
474 continue;
477 /* romfs is at block zero too */
478 if (romfsb->word0 == ROMSB_WORD0 &&
479 romfsb->word1 == ROMSB_WORD1) {
480 printk(KERN_NOTICE
481 "%s: romfs filesystem found at block %d\n",
482 mtd->name, off / mtd->erasesize);
483 break;
486 /* so is cramfs */
487 if (cramfsb->magic == CRAMFS_MAGIC) {
488 printk(KERN_NOTICE
489 "%s: cramfs filesystem found at block %d\n",
490 mtd->name, off / mtd->erasesize);
491 break;
494 if (squashfsb->s_magic == SQUASHFS_MAGIC_LZMA) {
495 printk(KERN_NOTICE
496 "%s: squash filesystem with lzma found at block %d\n",
497 mtd->name, off / mtd->erasesize);
498 break;
502 return off;
504 struct mtd_partition *
505 init_mtd_partitions(struct mtd_info *mtd, size_t size)
507 int bootflags;
508 int nparts = 0;
509 uint32 offset = 0;
510 uint rfs_off = 0;
511 uint vmlz_off, knl_size;
512 uint32 top = 0;
513 uint32 bootsz;
514 #ifdef CONFIG_FAILSAFE_UPGRADE
515 char *img_boot = nvram_get(BOOTPARTITION);
516 char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
517 char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
518 unsigned int image_first_offset=0;
519 unsigned int image_second_offset=0;
520 char dual_image_on = 0;
522 /* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
523 * image
525 dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
527 if (dual_image_on) {
528 image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
529 image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
530 printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
531 image_second_offset);
534 #endif
536 bootflags = boot_flags();
538 if ((bootflags & FLASH_KERNEL_NFLASH) != FLASH_KERNEL_NFLASH) {
539 vmlz_off = 0;
540 rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size);
542 /* Size pmon */
543 bcm947xx_flash_parts[nparts].name = "boot";
544 bcm947xx_flash_parts[nparts].size = vmlz_off;
545 bcm947xx_flash_parts[nparts].offset = top;
546 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
547 nparts++;
549 /* Setup kernel MTD partition */
550 bcm947xx_flash_parts[nparts].name = "linux";
551 #ifdef CONFIG_FAILSAFE_UPGRADE
552 if (dual_image_on) {
553 bcm947xx_flash_parts[nparts].size = image_second_offset-image_first_offset;
554 } else {
555 bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
557 /* Reserve for NVRAM */
558 bcm947xx_flash_parts[nparts].size -= ROUNDUP(NVRAM_SPACE, mtd->erasesize);
559 #ifdef PLC
560 /* Reserve for PLC */
561 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
562 #endif
563 #ifdef BCMCONFMTD
564 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
565 #endif
567 #else
569 bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
571 #ifdef PLC
572 /* Reserve for PLC */
573 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
574 #endif
575 /* Reserve for NVRAM */
576 bcm947xx_flash_parts[nparts].size -= ROUNDUP(NVRAM_SPACE, mtd->erasesize);
578 #ifdef BCMCONFMTD
579 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
580 #endif
581 #endif
582 bcm947xx_flash_parts[nparts].offset = vmlz_off;
583 knl_size = bcm947xx_flash_parts[nparts].size;
584 offset = bcm947xx_flash_parts[nparts].offset + knl_size;
585 nparts++;
587 /* Setup rootfs MTD partition */
588 bcm947xx_flash_parts[nparts].name = "rootfs";
589 bcm947xx_flash_parts[nparts].size = knl_size - (rfs_off - vmlz_off);
590 bcm947xx_flash_parts[nparts].offset = rfs_off;
591 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
592 nparts++;
593 #ifdef CONFIG_FAILSAFE_UPGRADE
594 if (dual_image_on) {
595 offset = image_second_offset;
596 rfs_off = lookup_flash_rootfs_offset(mtd, &offset, size);
597 vmlz_off = offset;
598 /* Setup kernel2 MTD partition */
599 bcm947xx_flash_parts[nparts].name = "linux2";
600 bcm947xx_flash_parts[nparts].size = mtd->size - image_second_offset;
601 /* Reserve for NVRAM */
602 bcm947xx_flash_parts[nparts].size -= ROUNDUP(NVRAM_SPACE, mtd->erasesize);
604 #ifdef BCMCONFMTD
605 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
606 #endif
607 #ifdef PLC
608 /* Reserve for PLC */
609 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
610 #endif
611 bcm947xx_flash_parts[nparts].offset = image_second_offset;
612 knl_size = bcm947xx_flash_parts[nparts].size;
613 offset = bcm947xx_flash_parts[nparts].offset + knl_size;
614 nparts++;
616 /* Setup rootfs MTD partition */
617 bcm947xx_flash_parts[nparts].name = "rootfs2";
618 bcm947xx_flash_parts[nparts].size = knl_size - (rfs_off - image_second_offset);
619 bcm947xx_flash_parts[nparts].offset = rfs_off;
620 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
621 nparts++;
623 #endif
625 } else {
626 bootsz = boot_partition_size(SI_FLASH2);
627 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
628 /* Size pmon */
629 bcm947xx_flash_parts[nparts].name = "pmon";
630 bcm947xx_flash_parts[nparts].size = bootsz;
631 bcm947xx_flash_parts[nparts].offset = top;
632 //bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
633 offset = bcm947xx_flash_parts[nparts].size;
634 nparts++;
637 #ifdef BCMCONFMTD
638 /* Setup CONF MTD partition */
639 bcm947xx_flash_parts[nparts].name = "confmtd";
640 bcm947xx_flash_parts[nparts].size = mtd->erasesize * 4;
641 bcm947xx_flash_parts[nparts].offset = offset;
642 offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
643 nparts++;
644 #endif /* BCMCONFMTD */
646 #ifdef PLC
647 /* Setup plc MTD partition */
648 bcm947xx_flash_parts[nparts].name = "plc";
649 bcm947xx_flash_parts[nparts].size = ROUNDUP(0x1000, mtd->erasesize);
650 bcm947xx_flash_parts[nparts].offset = size - (ROUNDUP(NVRAM_SPACE, mtd->erasesize) + ROUNDUP(0x1000, mtd->erasesize));
651 nparts++;
652 #endif
654 /* Setup nvram MTD partition */
655 bcm947xx_flash_parts[nparts].name = "nvram";
656 bcm947xx_flash_parts[nparts].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
657 bcm947xx_flash_parts[nparts].offset = size - bcm947xx_flash_parts[nparts].size;
658 nparts++;
660 return bcm947xx_flash_parts;
663 EXPORT_SYMBOL(init_mtd_partitions);
665 #ifdef CONFIG_MTD_NFLASH
666 #define NFLASH_PARTS_NUM 6
667 static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {{0}};
669 static uint lookup_nflash_rootfs_offset(struct mtd_info *mtd, int offset, size_t size)
671 struct romfs_super_block *romfsb;
672 struct cramfs_super *cramfsb;
673 struct squashfs_super_block *squashfsb;
674 struct trx_header *trx;
675 unsigned char buf[NFL_SECTOR_SIZE];
676 uint blocksize, mask, blk_offset, off, shift = 0;
677 chipcregs_t *cc;
678 int ret;
680 romfsb = (struct romfs_super_block *) buf;
681 cramfsb = (struct cramfs_super *) buf;
682 squashfsb = (struct squashfs_super_block *) buf;
683 trx = (struct trx_header *) buf;
685 if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL)
686 return 0;
688 /* Look at every block boundary till 16MB; higher space is reserved for application data. */
689 blocksize = mtd->erasesize;
690 printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
691 for (off = offset; off < NFL_BOOT_OS_SIZE; off += blocksize) {
692 mask = blocksize - 1;
693 blk_offset = off & ~mask;
694 if (nflash_checkbadb(sih, cc, blk_offset) != 0)
695 continue;
696 memset(buf, 0xe5, sizeof(buf));
697 if ((ret = nflash_read(sih, cc, off, sizeof(buf), buf)) != sizeof(buf)) {
698 printk(KERN_NOTICE
699 "%s: nflash_read return %d\n", mtd->name, ret);
700 continue;
703 /* Try looking at TRX header for rootfs offset */
704 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
705 mask = NFL_SECTOR_SIZE - 1;
706 off = offset + (le32_to_cpu(trx->offsets[1]) & ~mask) - blocksize;
707 shift = (le32_to_cpu(trx->offsets[1]) & mask);
708 romfsb = (struct romfs_super_block *)((unsigned char *)romfsb + shift);
709 cramfsb = (struct cramfs_super *)((unsigned char *)cramfsb + shift);
710 squashfsb = (struct squashfs_super_block *)((unsigned char *)squashfsb + shift);
711 continue;
714 /* romfs is at block zero too */
715 if (romfsb->word0 == ROMSB_WORD0 &&
716 romfsb->word1 == ROMSB_WORD1) {
717 printk(KERN_NOTICE
718 "%s: romfs filesystem found at block %d\n",
719 mtd->name, off / blocksize);
720 break;
723 /* so is cramfs */
724 if (cramfsb->magic == CRAMFS_MAGIC) {
725 printk(KERN_NOTICE
726 "%s: cramfs filesystem found at block %d\n",
727 mtd->name, off / blocksize);
728 break;
731 if (squashfsb->s_magic == SQUASHFS_MAGIC_LZMA) {
732 printk(KERN_NOTICE
733 "%s: squash filesystem with lzma found at block %d\n",
734 mtd->name, off / blocksize);
735 break;
739 return shift + off;
742 struct mtd_partition * init_nflash_mtd_partitions(struct mtd_info *mtd, size_t size)
744 int bootflags;
745 int nparts = 0;
746 uint32 offset = 0;
747 uint shift = 0;
748 uint32 top = 0;
749 uint32 bootsz;
750 #ifdef CONFIG_FAILSAFE_UPGRADE
751 char *img_boot = nvram_get(BOOTPARTITION);
752 char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
753 char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
754 unsigned int image_first_offset=0;
755 unsigned int image_second_offset=0;
756 char dual_image_on = 0;
758 /* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
759 * image
761 dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
763 if (dual_image_on) {
764 image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
765 image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
766 printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
767 image_second_offset);
770 #endif
772 bootflags = boot_flags();
773 if ((bootflags & FLASH_BOOT_NFLASH) == FLASH_BOOT_NFLASH) {
774 bootsz = boot_partition_size(SI_FLASH1);
775 if (bootsz > mtd->erasesize) {
776 /* Prepare double space in case of bad blocks */
777 bootsz = (bootsz << 1);
778 } else {
779 /* CFE occupies at least one block */
780 bootsz = mtd->erasesize;
782 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
784 /* Size pmon */
785 bcm947xx_nflash_parts[nparts].name = "boot";
786 bcm947xx_nflash_parts[nparts].size = bootsz;
787 bcm947xx_nflash_parts[nparts].offset = top;
788 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
789 offset = bcm947xx_nflash_parts[nparts].size;
790 nparts++;
792 /* Setup NVRAM MTD partition */
793 bcm947xx_nflash_parts[nparts].name = "nvram";
794 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_SIZE - offset;
795 bcm947xx_nflash_parts[nparts].offset = offset;
797 offset = NFL_BOOT_SIZE;
798 nparts++;
801 if ((bootflags & FLASH_KERNEL_NFLASH) == FLASH_KERNEL_NFLASH) {
802 /* Setup kernel MTD partition */
803 bcm947xx_nflash_parts[nparts].name = "linux";
804 #ifdef CONFIG_FAILSAFE_UPGRADE
805 if (dual_image_on)
806 bcm947xx_nflash_parts[nparts].size = image_second_offset - image_first_offset;
807 else
808 #endif
809 bcm947xx_nflash_parts[nparts].size = nparts ? (NFL_BOOT_OS_SIZE - NFL_BOOT_SIZE) : NFL_BOOT_OS_SIZE;
810 bcm947xx_nflash_parts[nparts].offset = offset;
812 shift = lookup_nflash_rootfs_offset(mtd, offset, bcm947xx_nflash_parts[nparts].size);
814 #ifdef CONFIG_FAILSAFE_UPGRADE
815 if (dual_image_on)
816 offset = image_second_offset;
817 else
818 #endif
819 offset = NFL_BOOT_OS_SIZE;
820 nparts++;
822 /* Setup rootfs MTD partition */
823 bcm947xx_nflash_parts[nparts].name = "rootfs";
824 #ifdef CONFIG_FAILSAFE_UPGRADE
825 if (dual_image_on)
826 bcm947xx_nflash_parts[nparts].size = image_second_offset - shift;
827 else
828 #endif
829 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
830 bcm947xx_nflash_parts[nparts].offset = shift;
831 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
833 nparts++;
835 #ifdef CONFIG_FAILSAFE_UPGRADE
836 /* Setup 2nd kernel MTD partition */
837 if (dual_image_on) {
838 bcm947xx_nflash_parts[nparts].name = "linux2";
839 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - image_second_offset;
840 bcm947xx_nflash_parts[nparts].offset = image_second_offset;
841 shift = lookup_nflash_rootfs_offset(mtd, image_second_offset,
842 bcm947xx_nflash_parts[nparts].size);
843 nparts++;
844 /* Setup rootfs MTD partition */
845 bcm947xx_nflash_parts[nparts].name = "rootfs2";
846 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
847 bcm947xx_nflash_parts[nparts].offset = shift;
848 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
849 nparts++;
851 #endif
855 return bcm947xx_nflash_parts;
858 EXPORT_SYMBOL(init_nflash_mtd_partitions);
859 #endif /* CONFIG_MTD_NFLASH */
861 #ifdef CONFIG_BLK_DEV_INITRD
862 extern char _end;
864 /* The check_ramdisk_trx has more exact qualification to look at TRX header from end of linux */
865 static __init int
866 check_ramdisk_trx(unsigned long offset, unsigned long ram_size)
868 struct trx_header *trx;
869 uint32 crc;
870 unsigned int len;
871 uint8 *ptr = (uint8 *)offset;
873 trx = (struct trx_header *)ptr;
875 /* Not a TRX_MAGIC */
876 if (le32_to_cpu(trx->magic) != TRX_MAGIC) {
877 printk("check_ramdisk_trx: not a valid TRX magic\n");
878 return -1;
881 /* TRX len invalid */
882 len = le32_to_cpu(trx->len);
883 if (offset + len > ram_size) {
884 printk("check_ramdisk_trx: not a valid TRX length\n");
885 return -1;
888 /* Checksum over header */
889 crc = hndcrc32((uint8 *) &trx->flag_version,
890 sizeof(struct trx_header) - OFFSETOF(struct trx_header, flag_version),
891 CRC32_INIT_VALUE);
893 /* Move ptr to data */
894 ptr += sizeof(struct trx_header);
895 len -= sizeof(struct trx_header);
897 /* Checksum over data */
898 crc = hndcrc32(ptr, len, crc);
900 /* Verify checksum */
901 if (le32_to_cpu(trx->crc32) != crc) {
902 printk("check_ramdisk_trx: checksum invalid\n");
903 return -1;
906 return 0;
909 void __init init_ramdisk(unsigned long mem_end)
911 struct trx_header *trx = NULL;
912 char *from_rootfs, *to_rootfs;
913 unsigned long rootfs_size = 0;
914 unsigned long ram_size = mem_end + 0x80000000;
915 unsigned long offset;
916 char *root_cmd = "root=/dev/ram0 console=ttyS0,115200";
918 to_rootfs = (char *)(((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK);
919 offset = ((unsigned long)&_end +0xffff) & ~0xffff;
921 /* Look at TRX header from end of linux */
922 for (; offset < ram_size; offset += 0x10000) {
923 trx = (struct trx_header *)offset;
924 if (le32_to_cpu(trx->magic) == TRX_MAGIC &&
925 check_ramdisk_trx(offset, ram_size) == 0) {
926 printk(KERN_NOTICE
927 "Found TRX image at %08lx\n", offset);
928 from_rootfs = (char *)((unsigned long)trx + le32_to_cpu(trx->offsets[1]));
929 rootfs_size = le32_to_cpu(trx->len) - le32_to_cpu(trx->offsets[1]);
930 rootfs_size = (rootfs_size + 0xffff) & ~0xffff;
931 printk("rootfs size is %ld bytes at 0x%p, copying to 0x%p\n", rootfs_size, from_rootfs, to_rootfs);
932 memmove(to_rootfs, from_rootfs, rootfs_size);
934 initrd_start = (int)to_rootfs;
935 initrd_end = initrd_start + rootfs_size;
936 strncpy(arcs_cmdline, root_cmd, sizeof(arcs_cmdline));
939 * In case the system warm boot, the memory won't be zeroed.
940 * So we have to erase trx magic.
942 if (initrd_end < (unsigned long)trx)
943 trx->magic = 0;
944 break;
948 #endif
949 #endif