• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/mips/brcm-boards/bcm947xx/
1/*
2 * HND MIPS boards setup routines
3 *
4 * Copyright (C) 2013, 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.
17 *
18 * $Id: setup.c,v 1.23 2010-10-20 08:26:12 $
19 */
20
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>
40
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"
76
77extern void bcm947xx_time_init(void);
78extern void bcm947xx_timer_setup(struct irqaction *irq);
79
80#ifdef CONFIG_KGDB
81extern void set_debug_traps(void);
82extern void rs_kgdb_hook(struct uart_port *);
83extern void breakpoint(void);
84#endif
85
86#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
87extern struct ide_ops std_ide_ops;
88#endif
89
90struct dummy_super_block {
91	u32	s_magic ;
92};
93
94#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
95/* Enable CPU wait or not */
96extern int cpu_wait_enable;
97#else
98int coherentio;   /* init to 0 => no DMA cache coherency (may be set by user) */
99int hw_coherentio;/* init to 0 => no HW DMA cache coherency (reflects real HW) */
100#endif
101
102/* Global SB handle */
103si_t *bcm947xx_sih = NULL;
104spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
105EXPORT_SYMBOL(bcm947xx_sih);
106EXPORT_SYMBOL(bcm947xx_sih_lock);
107
108/* Convenience */
109#define sih bcm947xx_sih
110#define sih_lock bcm947xx_sih_lock
111
112#ifdef HNDCTF
113ctf_t *kcih = NULL;
114EXPORT_SYMBOL(kcih);
115ctf_attach_t ctf_attach_fn = NULL;
116EXPORT_SYMBOL(ctf_attach_fn);
117#endif /* HNDCTF */
118
119/* Kernel command line */
120#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
121extern char arcs_cmdline[CL_SIZE];
122#endif
123static int lanports_enable = 0;
124
125
126EXPORT_SYMBOL( si_router_coma );	/* for loadable modules */
127EXPORT_SYMBOL( hnd_jtagm_init );
128EXPORT_SYMBOL( hnd_jtagm_disable );
129EXPORT_SYMBOL( jtag_scan );
130
131static void
132bcm947xx_reboot_handler(void)
133{
134#ifndef BCMDBG
135	int wombo_reset;
136#endif /* BCMDBG */
137
138	/* Reset the PCI(e) interfaces */
139	if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
140		hndpci_deinit(sih);
141
142	if (lanports_enable) {
143		uint lp = 1 << lanports_enable;
144
145		si_gpioout(sih, lp, 0, GPIO_DRV_PRIORITY);
146		si_gpioouten(sih, lp, lp, GPIO_DRV_PRIORITY);
147		bcm_mdelay(1);
148	}
149
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;
155
156		si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
157		si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
158		bcm_mdelay(10);
159	}
160#endif /* BCMDBG */
161}
162
163void
164bcm947xx_machine_restart(char *command)
165{
166	printk("Please stand by while rebooting the system...\n");
167
168	/* Set the watchdog timer to reset immediately */
169	local_irq_disable();
170	bcm947xx_reboot_handler();
171	hnd_cpu_reset(sih);
172}
173
174void
175bcm947xx_machine_halt(void)
176{
177	printk("System halted\n");
178
179	/* Disable interrupts and watchdog and spin forever */
180	local_irq_disable();
181	si_watchdog(sih, 0);
182	bcm947xx_reboot_handler();
183	while (1);
184}
185
186#ifdef CONFIG_SERIAL_CORE
187
188static struct uart_port rs = {
189	line: 0,
190	flags: ASYNC_BOOT_AUTOCONF,
191	iotype: SERIAL_IO_MEM,
192};
193
194static void __init
195serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
196{
197	rs.membase = regs;
198	rs.irq = irq + 2;
199	rs.uartclk = baud_base;
200	rs.regshift = reg_shift;
201
202	early_serial_setup(&rs);
203
204	rs.line++;
205}
206
207static void __init
208serial_setup(si_t *sih)
209{
210	si_serial_init(sih, serial_add);
211
212#ifdef CONFIG_KGDB
213	/* Use the last port for kernel debugging */
214	if (rs.membase)
215		rs_kgdb_hook(&rs);
216#endif
217}
218
219#endif /* CONFIG_SERIAL_CORE */
220
221static int boot_flags(void)
222{
223	int bootflags = 0;
224	char *val;
225
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;
231		}
232		else if ((val = nvram_get("bootflags"))) {
233			bootflags = simple_strtol(val, NULL, 0);
234			bootflags &= FLASH_KERNEL_NFLASH;
235		}
236	}
237
238	return bootflags;
239}
240
241static int rootfs_mtdblock(void)
242{
243	int bootflags;
244	int block = 0;
245
246	bootflags = boot_flags();
247
248	/* NANDBOOT */
249	if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) ==
250		(FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH))
251		return 3;
252
253	/* SFLASH/PFLASH only */
254	if ((bootflags & (FLASH_BOOT_NFLASH | FLASH_KERNEL_NFLASH)) == 0)
255		return 2;
256
257#ifdef BCMCONFMTD
258	block++;
259#endif
260	/* Boot from norflash and kernel in nandflash */
261	return block+3;
262}
263
264void __init
265brcm_setup(void)
266{
267	char *value;
268
269	/* Get global SB handle */
270	sih = si_kattach(SI_OSH);
271
272	/* Initialize clocks and interrupts */
273	si_mips_init(sih, SBMIPS_VIRTIRQ_BASE);
274
275	if (BCM330X(current_cpu_data.processor_id) &&
276		(read_c0_diag() & BRCM_PFC_AVAIL)) {
277		/*
278		 * Now that the sih is inited set the  proper PFC value
279		 */
280		printk("Setting the PFC to its default value\n");
281		enable_pfc(PFC_AUTO);
282	}
283
284
285#ifdef CONFIG_SERIAL_CORE
286	/* Initialize UARTs */
287	serial_setup(sih);
288#endif /* CONFIG_SERIAL_CORE */
289
290#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
291	ide_ops = &std_ide_ops;
292#endif
293
294	sprintf(arcs_cmdline, "root=/dev/mtdblock%d console=ttyS0,115200 init=/sbin/preinit", rootfs_mtdblock());
295
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));
300
301
302	if ((lanports_enable = getgpiopin(NULL, "lanports_enable", GPIO_PIN_NOTDEFINED)) ==
303		GPIO_PIN_NOTDEFINED)
304		lanports_enable = 0;
305
306
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
312
313	/* Generic setup */
314	_machine_restart = bcm947xx_machine_restart;
315	_machine_halt = bcm947xx_machine_halt;
316	pm_power_off = bcm947xx_machine_halt;
317
318#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
319	board_time_init = bcm947xx_time_init;
320#endif
321}
322
323const char *
324get_system_type(void)
325{
326	static char s[32];
327
328	if (bcm947xx_sih) {
329		sprintf(s, "Broadcom BCM%X chip rev %d", bcm947xx_sih->chip,
330			bcm947xx_sih->chiprev);
331		return s;
332	}
333	else
334		return "Broadcom BCM947XX";
335}
336
337void __init
338bus_error_init(void)
339{
340}
341
342void __init
343plat_mem_setup(void)
344{
345	brcm_setup();
346	return;
347}
348
349#ifdef CONFIG_MTD_PARTITIONS
350
351static struct mutex *mtd_mutex = NULL;
352
353struct mutex *partitions_mutex_init(void)
354{
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);
360	}
361	return mtd_mutex;
362}
363EXPORT_SYMBOL(partitions_mutex_init);
364
365/* Find out prom size */
366static uint32 boot_partition_size(uint32 flash_phys) {
367	uint32 bootsz, *bisz;
368
369	/* Default is 256K boot partition */
370	bootsz = 256 * 1024;
371
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];
376
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;
385	}
386	return bootsz;
387}
388
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
396
397static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
398
399static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size)
400{
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;
412
413	romfsb = (struct romfs_super_block *) buf;
414	cramfsb = (struct cramfs_super *) buf;
415	squashfsb = (void *) buf;
416	trx = (struct trx_header *) buf;
417
418	/* Look at every 64 KB boundary */
419	for (off = 0; off < size; off += (64 * 1024)) {
420		memset(buf, 0xe5, sizeof(buf));
421
422		/*
423		 * Read block 0 to test for romfs and cramfs superblock
424		 */
425		if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
426		    len != sizeof(buf))
427			continue;
428
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;
434			/*
435			 * Read to test for romfs and cramfs superblock
436			 */
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;
441		}
442
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;
450		}
451
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;
458		}
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;
464		}
465	}
466
467	return off;
468}
469struct mtd_partition *
470init_mtd_partitions(struct mtd_info *mtd, size_t size)
471{
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;
479
480	bootflags = boot_flags();
481
482	if ((bootflags & FLASH_KERNEL_NFLASH) != FLASH_KERNEL_NFLASH) {
483		rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size);
484
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++;
491
492		/* Setup kernel MTD partition */
493		bcm947xx_flash_parts[nparts].name = "linux";
494		bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
495
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);
502
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++;
510
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++;
527	}
528
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 */
537
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
545
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++;
551
552	return bcm947xx_flash_parts;
553}
554
555EXPORT_SYMBOL(init_mtd_partitions);
556
557#ifdef CONFIG_MTD_NFLASH
558#define NFLASH_PARTS_NUM	6
559static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {{0}};
560
561static uint lookup_nflash_rootfs_offset(struct mtd_info *mtd, int offset, size_t size)
562{
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;
575
576	romfsb = (struct romfs_super_block *) buf;
577	cramfsb = (struct cramfs_super *) buf;
578	squashfsb = (void *) buf;
579	trx = (struct trx_header *) buf;
580
581	if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL)
582		return 0;
583
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;
597		}
598
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;
608		}
609
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;
617		}
618
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;
625		}
626
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;
632		}
633	}
634	return shift + off;
635}
636
637struct mtd_partition * init_nflash_mtd_partitions(struct mtd_info *mtd, size_t size)
638{
639	int bootflags;
640	int nparts = 0;
641	uint32 offset = 0;
642	uint shift = 0;
643	uint32 top = 0;
644	uint32 bootsz;
645
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;
655		}
656		printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
657
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++;
665
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;
670
671		offset = NFL_BOOT_SIZE;
672		nparts++;
673	}
674
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;
680
681		shift = lookup_nflash_rootfs_offset(mtd, offset, size);
682
683		offset = NFL_BOOT_OS_SIZE;
684		nparts++;
685
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;
691
692		nparts++;
693	}
694
695	return bcm947xx_nflash_parts;
696}
697
698EXPORT_SYMBOL(init_nflash_mtd_partitions);
699#endif /* CONFIG_MTD_NFLASH */
700
701#ifdef CONFIG_BLK_DEV_INITRD
702extern char _end;
703
704/* The check_ramdisk_trx has more exact qualification to look at TRX header from end of linux */
705static __init int
706check_ramdisk_trx(unsigned long offset, unsigned long ram_size)
707{
708	struct trx_header *trx;
709	uint32 crc;
710	unsigned int len;
711	uint8 *ptr = (uint8 *)offset;
712
713	trx = (struct trx_header *)ptr;
714
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;
719	}
720
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;
726	}
727
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);
732
733	/* Move ptr to data */
734	ptr += sizeof(struct trx_header);
735	len -= sizeof(struct trx_header);
736
737	/* Checksum over data */
738	crc = hndcrc32(ptr, len, crc);
739
740	/* Verify checksum */
741	if (le32_to_cpu(trx->crc32) != crc) {
742		printk("check_ramdisk_trx: checksum invalid\n");
743		return -1;
744	}
745
746	return 0;
747}
748
749void __init init_ramdisk(unsigned long mem_end)
750{
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";
757
758	to_rootfs = (char *)(((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK);
759	offset = ((unsigned long)&_end +0xffff) & ~0xffff;
760
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);
773
774			initrd_start = (int)to_rootfs;
775			initrd_end = initrd_start + rootfs_size;
776			strncpy(arcs_cmdline, root_cmd, sizeof(arcs_cmdline));
777			/*
778			 * In case the system warm boot, the memory won't be zeroed.
779			 * So we have to erase trx magic.
780			 */
781			if (initrd_end < (unsigned long)trx)
782				trx->magic = 0;
783			break;
784		}
785	}
786}
787#endif
788#endif
789