• 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/arch/arm/mach-brcm-hnd/
1
2#include <linux/types.h>
3#include <linux/version.h>
4#include <linux/init.h>
5#include <linux/platform_device.h>
6
7#include <asm/setup.h>
8#include <asm/mach-types.h>
9#include <asm/mach/arch.h>
10#include <asm/mach/time.h>
11#include <asm/clkdev.h>
12
13#include <mach/clkdev.h>
14#include <mach/hardware.h>
15#include <mach/memory.h>
16#include <mach/io_map.h>
17
18#include <plat/bsp.h>
19#include <plat/mpcore.h>
20#include <plat/plat-bcm5301x.h>
21
22#ifdef CONFIG_MTD_PARTITIONS
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/nand.h>
25#include <linux/mtd/partitions.h>
26#include <linux/romfs_fs.h>
27#include <linux/cramfs_fs.h>
28#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
29#include <linux/squashfs_fs.h>
30#else
31/* #include <magic.h> */
32#endif
33#endif
34
35#include <typedefs.h>
36#include <osl.h>
37#include <bcmutils.h>
38#include <bcmnvram.h>
39#include <bcmendian.h>
40#include <hndsoc.h>
41#include <siutils.h>
42#include <hndcpu.h>
43#include <hndpci.h>
44#include <pcicfg.h>
45#include <bcmdevs.h>
46#include <trxhdr.h>
47#ifdef HNDCTF
48#include <ctf/hndctf.h>
49#endif /* HNDCTF */
50#include <hndsflash.h>
51#ifdef CONFIG_MTD_NFLASH
52#include <hndnand.h>
53#endif
54
55extern char __initdata saved_root_name[];
56
57/* Global SB handle */
58si_t *bcm947xx_sih = NULL;
59spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
60EXPORT_SYMBOL(bcm947xx_sih);
61EXPORT_SYMBOL(bcm947xx_sih_lock);
62
63/* Convenience */
64#define sih bcm947xx_sih
65#define sih_lock bcm947xx_sih_lock
66
67#define WATCHDOG_MIN    3000    /* milliseconds */
68extern int panic_timeout;
69extern int panic_on_oops;
70static int watchdog = 0;
71
72#ifdef HNDCTF
73ctf_t *kcih = NULL;
74EXPORT_SYMBOL(kcih);
75ctf_attach_t ctf_attach_fn = NULL;
76EXPORT_SYMBOL(ctf_attach_fn);
77#endif /* HNDCTF */
78
79
80struct dummy_super_block {
81	u32	s_magic ;
82};
83
84/* This is the main reference clock 25MHz from external crystal */
85static struct clk clk_ref = {
86	.name = "Refclk",
87	.rate = 25 * 1000000,	/* run-time override */
88	.fixed = 1,
89	.type	= CLK_XTAL,
90};
91
92
93static struct clk_lookup board_clk_lookups[] = {
94	{
95	.con_id		= "refclk",
96	.clk		= &clk_ref,
97	}
98};
99
100extern int _memsize;
101
102void __init board_map_io(void)
103{
104early_printk("board_map_io\n");
105	/* Install clock sources into the lookup table */
106	clkdev_add_table(board_clk_lookups,
107			ARRAY_SIZE(board_clk_lookups));
108
109	/* Map SoC specific I/O */
110	soc_map_io( &clk_ref );
111}
112
113
114void __init board_init_irq(void)
115{
116early_printk("board_init_irq\n");
117	soc_init_irq();
118
119	/* serial_setup(sih); */
120}
121
122void board_init_timer(void)
123{
124early_printk("board_init_timer\n");
125	soc_init_timer();
126}
127
128static int __init rootfs_mtdblock(void)
129{
130	int bootdev;
131	int knldev;
132	int block = 0;
133#ifdef CONFIG_FAILSAFE_UPGRADE
134	char *img_boot = nvram_get(BOOTPARTITION);
135#endif
136
137	bootdev = soc_boot_dev((void *)sih);
138	knldev = soc_knl_dev((void *)sih);
139
140	/* NANDBOOT */
141	if (bootdev == SOC_BOOTDEV_NANDFLASH &&
142	    knldev == SOC_KNLDEV_NANDFLASH) {
143#ifdef CONFIG_FAILSAFE_UPGRADE
144		if (img_boot && simple_strtol(img_boot, NULL, 10))
145			return 5;
146		else
147			return 3;
148#else
149		return 3;
150#endif
151	}
152
153	/* SFLASH/PFLASH only */
154	if (bootdev != SOC_BOOTDEV_NANDFLASH &&
155	    knldev != SOC_KNLDEV_NANDFLASH) {
156#ifdef CONFIG_FAILSAFE_UPGRADE
157		if (img_boot && simple_strtol(img_boot, NULL, 10))
158			return 4;
159		else
160			return 2;
161#else
162		return 2;
163#endif
164	}
165
166#ifdef BCMCONFMTD
167	block++;
168#endif
169#ifdef CONFIG_FAILSAFE_UPGRADE
170	if (img_boot && simple_strtol(img_boot, NULL, 10))
171		block += 2;
172#endif
173	/* Boot from norflash and kernel in nandflash */
174	return block+3;
175}
176
177static void __init brcm_setup(void)
178{
179	/* Get global SB handle */
180	sih = si_kattach(SI_OSH);
181
182	if (strncmp(boot_command_line, "root=/dev/mtdblock", strlen("root=/dev/mtdblock")) == 0)
183		sprintf(saved_root_name, "/dev/mtdblock%d", rootfs_mtdblock());
184
185	/* Set watchdog interval in ms */
186        watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);
187
188	/* Ensure at least WATCHDOG_MIN */
189	if ((watchdog > 0) && (watchdog < WATCHDOG_MIN))
190		watchdog = WATCHDOG_MIN;
191
192	/* Set panic timeout in seconds */
193	panic_timeout = watchdog / 1000;
194	panic_on_oops = watchdog / 1000;
195}
196
197void soc_watchdog(void)
198{
199	if (watchdog > 0)
200		si_watchdog_ms(sih, watchdog);
201}
202
203#define CFE_UPDATE 1            // added by Chen-I for mac/regulation update
204
205#ifdef CFE_UPDATE
206void bcm947xx_watchdog_disable(void)
207{
208	watchdog=0;
209	si_watchdog_ms(sih, 0);
210}
211#endif
212
213void __init board_init(void)
214{
215early_printk("board_init\n");
216	brcm_setup();
217	/*
218	 * Add common platform devices that do not have board dependent HW
219	 * configurations
220	 */
221	soc_add_devices();
222
223	return;
224}
225
226static void __init board_fixup(
227	struct machine_desc *desc,
228	struct tag *t,
229	char **cmdline,
230	struct meminfo *mi
231	)
232{
233	u32 mem_size, lo_size ;
234        early_printk("board_fixup\n" );
235
236	/* Fuxup reference clock rate */
237	if (desc->nr == MACH_TYPE_BRCM_NS_QT )
238		clk_ref.rate = 17594;	/* Emulator ref clock rate */
239
240
241	mem_size = _memsize;
242
243	early_printk("board_fixup: mem=%uMiB\n", mem_size >> 20);
244
245	lo_size = min(mem_size, DRAM_MEMORY_REGION_SIZE);
246
247	mi->bank[0].start = PHYS_OFFSET;
248	mi->bank[0].size = lo_size;
249	mi->nr_banks++;
250
251	if (lo_size == mem_size)
252		return;
253
254	mi->bank[1].start = PHYS_OFFSET2;
255	mi->bank[1].size = mem_size - lo_size;
256	mi->nr_banks++;
257}
258
259#ifdef CONFIG_ZONE_DMA
260/*
261 * Adjust the zones if there are restrictions for DMA access.
262 */
263void __init bcm47xx_adjust_zones(unsigned long *size, unsigned long *hole)
264{
265	unsigned long dma_size = SZ_128M >> PAGE_SHIFT;
266
267	if (size[0] <= dma_size)
268		return;
269
270	size[ZONE_NORMAL] = size[0] - dma_size;
271	size[ZONE_DMA] = dma_size;
272	hole[ZONE_NORMAL] = hole[0];
273	hole[ZONE_DMA] = 0;
274}
275#endif /* CONFIG_ZONE_DMA */
276
277static struct sys_timer board_timer = {
278   .init = board_init_timer,
279};
280
281#if (( (IO_BASE_VA >>18) & 0xfffc) != 0x3c40)
282#error IO_BASE_VA
283#endif
284
285MACHINE_START(BRCM_NS, "Northstar Prototype")
286   .phys_io = 					/* UART I/O mapping */
287	IO_BASE_PA,
288   .io_pg_offst = 				/* for early debug */
289	(IO_BASE_VA >>18) & 0xfffc,
290   .fixup = board_fixup,			/* Opt. early setup_arch() */
291   .map_io = board_map_io,			/* Opt. from setup_arch() */
292   .init_irq = board_init_irq,			/* main.c after setup_arch() */
293   .timer  = &board_timer,			/* main.c after IRQs */
294   .init_machine = board_init,			/* Late archinitcall */
295   .boot_params = CONFIG_BOARD_PARAMS_PHYS,
296MACHINE_END
297
298#ifdef	CONFIG_MACH_BRCM_NS_QT
299MACHINE_START(BRCM_NS_QT, "Northstar Emulation Model")
300   .phys_io = 					/* UART I/O mapping */
301	IO_BASE_PA,
302   .io_pg_offst = 				/* for early debug */
303	(IO_BASE_VA >>18) & 0xfffc,
304   .fixup = board_fixup,			/* Opt. early setup_arch() */
305   .map_io = board_map_io,			/* Opt. from setup_arch() */
306   .init_irq = board_init_irq,			/* main.c after setup_arch() */
307   .timer  = &board_timer,			/* main.c after IRQs */
308   .init_machine = board_init,			/* Late archinitcall */
309   .boot_params = CONFIG_BOARD_PARAMS_PHYS,
310MACHINE_END
311#endif
312
313void arch_reset(char mode, const char *cmd)
314{
315#ifdef CONFIG_OUTER_CACHE_SYNC
316	outer_cache.sync = NULL;
317#endif
318	hnd_cpu_reset(sih);
319}
320
321#ifdef CONFIG_MTD_PARTITIONS
322
323static spinlock_t *mtd_lock = NULL;
324
325spinlock_t *partitions_lock_init(void)
326{
327	if (!mtd_lock) {
328		mtd_lock = (spinlock_t *)kzalloc(sizeof(spinlock_t), GFP_KERNEL);
329		if (!mtd_lock)
330			return NULL;
331
332		spin_lock_init( mtd_lock );
333	}
334	return mtd_lock;
335}
336EXPORT_SYMBOL(partitions_lock_init);
337
338static struct nand_hw_control *nand_hwcontrol = NULL;
339struct nand_hw_control *nand_hwcontrol_lock_init(void)
340{
341	if (!nand_hwcontrol) {
342		nand_hwcontrol = (struct nand_hw_control *)kzalloc(sizeof(struct nand_hw_control), GFP_KERNEL);
343		if (!nand_hwcontrol)
344			return NULL;
345
346		spin_lock_init(&nand_hwcontrol->lock);
347		init_waitqueue_head(&nand_hwcontrol->wq);
348	}
349	return nand_hwcontrol;
350}
351EXPORT_SYMBOL(nand_hwcontrol_lock_init);
352
353/* Find out prom size */
354static uint32 boot_partition_size(uint32 flash_phys) {
355	uint32 bootsz, *bisz;
356
357	/* Default is 256K boot partition */
358	bootsz = 256 * 1024;
359
360	/* Do we have a self-describing binary image? */
361	bisz = (uint32 *)(flash_phys + BISZ_OFFSET);
362	if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) {
363		int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX];
364
365		if (isz > (1024 * 1024))
366			bootsz = 2048 * 1024;
367		else if (isz > (512 * 1024))
368			bootsz = 1024 * 1024;
369		else if (isz > (256 * 1024))
370			bootsz = 512 * 1024;
371		else if (isz <= (128 * 1024))
372			bootsz = 128 * 1024;
373	}
374	return bootsz;
375}
376
377#if defined(BCMCONFMTD)
378#define MTD_PARTS 1
379#else
380#define MTD_PARTS 0
381#endif
382#if defined(PLC)
383#define PLC_PARTS 1
384#else
385#define PLC_PARTS 0
386#endif
387#if defined(CONFIG_FAILSAFE_UPGRADE)
388#define FAILSAFE_PARTS 2
389#else
390#define FAILSAFE_PARTS 0
391#endif
392#if defined(CONFIG_CRASHLOG)
393#define CRASHLOG_PARTS 1
394#else
395#define CRASHLOG_PARTS 0
396#endif
397/* boot;nvram;kernel;rootfs;empty */
398#define FLASH_PARTS_NUM	(5+MTD_PARTS+PLC_PARTS+FAILSAFE_PARTS+CRASHLOG_PARTS)
399
400static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
401
402static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size,
403                                       uint32 *trx_size)
404{
405	struct romfs_super_block *romfsb;
406	struct cramfs_super *cramfsb;
407#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
408	struct squashfs_super_block *squashfsb;
409#else
410	struct dummy_super_block *squashfsb;
411#endif
412	struct trx_header *trx;
413	unsigned char buf[512];
414	int off;
415	size_t len;
416
417	romfsb = (struct romfs_super_block *) buf;
418	cramfsb = (struct cramfs_super *) buf;
419	squashfsb = (void *) buf;
420	trx = (struct trx_header *) buf;
421
422	/* Look at every 64 KB boundary */
423	for (off = *trx_off; off < size; off += (64 * 1024)) {
424		memset(buf, 0xe5, sizeof(buf));
425
426		/*
427		 * Read block 0 to test for romfs and cramfs superblock
428		 */
429		if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
430		    len != sizeof(buf))
431			continue;
432
433		/* Try looking at TRX header for rootfs offset */
434		if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
435			*trx_off = off;
436			*trx_size = le32_to_cpu(trx->len);
437			if (trx->offsets[1] == 0)
438				continue;
439			/*
440			 * Read to test for romfs and cramfs superblock
441			 */
442			off += le32_to_cpu(trx->offsets[1]);
443			memset(buf, 0xe5, sizeof(buf));
444			if (mtd->read(mtd, off, sizeof(buf), &len, buf) || len != sizeof(buf))
445				continue;
446		}
447
448		/* romfs is at block zero too */
449		if (romfsb->word0 == ROMSB_WORD0 &&
450		    romfsb->word1 == ROMSB_WORD1) {
451			printk(KERN_NOTICE
452			       "%s: romfs filesystem found at block %d\n",
453			       mtd->name, off / mtd->erasesize);
454			break;
455		}
456
457		/* so is cramfs */
458		if (cramfsb->magic == CRAMFS_MAGIC) {
459			printk(KERN_NOTICE
460			       "%s: cramfs filesystem found at block %d\n",
461			       mtd->name, off / mtd->erasesize);
462			break;
463		}
464
465		if (squashfsb->s_magic == SQUASHFS_MAGIC) {
466			printk(KERN_NOTICE
467			       "%s: squash filesystem found at block %d\n",
468			       mtd->name, off / mtd->erasesize);
469			break;
470		}
471	}
472
473	return off;
474}
475
476struct mtd_partition *
477init_mtd_partitions(hndsflash_t *sfl_info, struct mtd_info *mtd, size_t size)
478{
479	int bootdev;
480	int knldev;
481	int nparts = 0;
482	uint32 offset = 0;
483	uint rfs_off = 0;
484	uint vmlz_off, knl_size;
485	uint32 top = 0;
486	uint32 bootsz;
487	uint32 trx_size;
488#ifdef CONFIG_CRASHLOG
489	char create_crash_partition = 0;
490#endif
491#ifdef CONFIG_FAILSAFE_UPGRADE
492	char *img_boot = nvram_get(BOOTPARTITION);
493	char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
494	char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
495	unsigned int image_first_offset = 0;
496	unsigned int image_second_offset = 0;
497	char dual_image_on = 0;
498
499	/* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
500	 * image
501	 */
502	dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
503
504	if (dual_image_on) {
505		image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
506		image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
507		printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
508			image_second_offset);
509
510	}
511#endif	/* CONFIG_FAILSAFE_UPGRADE */
512
513	bootdev = soc_boot_dev((void *)sih);
514	knldev = soc_knl_dev((void *)sih);
515
516	if (bootdev == SOC_BOOTDEV_NANDFLASH) {
517		/* Do not init MTD partitions on NOR flash when NAND boot */
518		return NULL;
519	}
520
521	if (knldev != SOC_KNLDEV_NANDFLASH) {
522		vmlz_off = 0;
523		rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size, &trx_size);
524
525		/* Size pmon */
526		bcm947xx_flash_parts[nparts].name = "boot";
527		bcm947xx_flash_parts[nparts].size = vmlz_off;
528		bcm947xx_flash_parts[nparts].offset = top;
529		bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
530		nparts++;
531
532		/* Setup kernel MTD partition */
533		bcm947xx_flash_parts[nparts].name = "linux";
534#ifdef CONFIG_FAILSAFE_UPGRADE
535		if (trx_size > (image_second_offset-image_first_offset)) {
536			printk("sflash size is too small to afford two images.\n");
537			dual_image_on = 0;
538			image_first_offset = 0;
539			image_second_offset = 0;
540		}
541		if (dual_image_on) {
542			bcm947xx_flash_parts[nparts].size = image_second_offset-image_first_offset;
543		} else {
544			bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
545
546			/* Reserve for NVRAM */
547			bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
548#ifdef PLC
549			/* Reserve for PLC */
550			bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
551#endif
552#ifdef BCMCONFMTD
553			bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
554#endif
555		}
556#else
557
558		bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
559
560#ifdef PLC
561		/* Reserve for PLC */
562		bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
563#endif
564		/* Reserve for NVRAM */
565		bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
566
567#ifdef BCMCONFMTD
568		bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
569#endif
570#endif	/* CONFIG_FAILSAFE_UPGRADE */
571
572#ifdef CONFIG_CRASHLOG
573		if ((bcm947xx_flash_parts[nparts].size - trx_size) >=
574		    ROUNDUP(0x4000, mtd->erasesize)) {
575			bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x4000, mtd->erasesize);
576			create_crash_partition = 1;
577		} else {
578			create_crash_partition = 0;
579		}
580#endif
581
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++;
586
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		offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
593		nparts++;
594
595#if defined(CONFIG_CRASHLOG) && defined(BCMDBG)
596		if (create_crash_partition) {
597			/* Setup crash MTD partition */
598			bcm947xx_flash_parts[nparts].name = "crash";
599			bcm947xx_flash_parts[nparts].size = ROUNDUP(0x4000, mtd->erasesize);
600			bcm947xx_flash_parts[nparts].offset = offset;
601			bcm947xx_flash_parts[nparts].mask_flags = 0;
602			nparts++;
603		}
604#endif
605#ifdef CONFIG_FAILSAFE_UPGRADE
606		if (dual_image_on) {
607			offset = image_second_offset;
608			rfs_off = lookup_flash_rootfs_offset(mtd, &offset, size, &trx_size);
609			/* When the second image doesn't exist,
610			 * set the rootfs use the same offset with the kernel
611			 */
612			if (rfs_off == size)
613				rfs_off = offset;
614
615			vmlz_off = offset;
616			/* Setup kernel2 MTD partition */
617			bcm947xx_flash_parts[nparts].name = "linux2";
618			bcm947xx_flash_parts[nparts].size = mtd->size - image_second_offset;
619			/* Reserve for NVRAM */
620			bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
621
622#ifdef BCMCONFMTD
623			bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
624#endif
625#ifdef PLC
626			/* Reserve for PLC */
627			bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
628#endif
629			bcm947xx_flash_parts[nparts].offset = image_second_offset;
630			knl_size = bcm947xx_flash_parts[nparts].size;
631			offset = bcm947xx_flash_parts[nparts].offset + knl_size;
632			nparts++;
633
634			/* Setup rootfs MTD partition */
635			bcm947xx_flash_parts[nparts].name = "rootfs2";
636			bcm947xx_flash_parts[nparts].size =
637				knl_size - (rfs_off - image_second_offset);
638			bcm947xx_flash_parts[nparts].offset = rfs_off;
639			/* forces on read only */
640			bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE;
641			nparts++;
642		}
643#endif	/* CONFIG_FAILSAFE_UPGRADE */
644
645	} else {
646		bootsz = boot_partition_size(sfl_info->base);
647		printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
648		/* Size pmon */
649		bcm947xx_flash_parts[nparts].name = "boot";
650		bcm947xx_flash_parts[nparts].size = bootsz;
651		bcm947xx_flash_parts[nparts].offset = top;
652		//bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
653		offset = bcm947xx_flash_parts[nparts].size;
654		nparts++;
655	}
656
657#ifdef BCMCONFMTD
658	/* Setup CONF MTD partition */
659	bcm947xx_flash_parts[nparts].name = "confmtd";
660	bcm947xx_flash_parts[nparts].size = mtd->erasesize * 4;
661	bcm947xx_flash_parts[nparts].offset = offset;
662	offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
663	nparts++;
664#endif	/* BCMCONFMTD */
665
666#ifdef PLC
667	/* Setup plc MTD partition */
668	bcm947xx_flash_parts[nparts].name = "plc";
669	bcm947xx_flash_parts[nparts].size = ROUNDUP(0x1000, mtd->erasesize);
670	bcm947xx_flash_parts[nparts].offset =
671		size - (ROUNDUP(nvram_space, mtd->erasesize) + ROUNDUP(0x1000, mtd->erasesize));
672	nparts++;
673#endif
674
675	/* Setup nvram MTD partition */
676	bcm947xx_flash_parts[nparts].name = "nvram";
677	bcm947xx_flash_parts[nparts].size = ROUNDUP(nvram_space, mtd->erasesize);
678	bcm947xx_flash_parts[nparts].offset = size - bcm947xx_flash_parts[nparts].size;
679	nparts++;
680
681	return bcm947xx_flash_parts;
682}
683
684EXPORT_SYMBOL(init_mtd_partitions);
685
686#endif /* CONFIG_MTD_PARTITIONS */
687
688
689#ifdef	CONFIG_MTD_NFLASH
690
691#define NFLASH_PARTS_NUM	7
692static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {{0}};
693
694static uint
695lookup_nflash_rootfs_offset(hndnand_t *nfl, struct mtd_info *mtd, int offset, size_t size)
696{
697	struct romfs_super_block *romfsb;
698	struct cramfs_super *cramfsb;
699	struct dummy_super_block *squashfsb;
700	struct trx_header *trx;
701	unsigned char *buf;
702	uint blocksize, pagesize, mask, blk_offset, off, shift = 0;
703	int ret;
704
705	pagesize = nfl->pagesize;
706	buf = (unsigned char *)kmalloc(pagesize, GFP_KERNEL);
707	if (!buf) {
708		printk("lookup_nflash_rootfs_offset: kmalloc fail\n");
709		return 0;
710	}
711
712	romfsb = (struct romfs_super_block *) buf;
713	cramfsb = (struct cramfs_super *) buf;
714	squashfsb = (void *) buf;
715	trx = (struct trx_header *) buf;
716
717	/* Look at every block boundary till 16MB; higher space is reserved for application data. */
718	blocksize = mtd->erasesize;
719	printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
720	for (off = offset; off < offset + size; off += blocksize) {
721		mask = blocksize - 1;
722		blk_offset = off & ~mask;
723		if (hndnand_checkbadb(nfl, blk_offset) != 0)
724			continue;
725		memset(buf, 0xe5, pagesize);
726		if ((ret = hndnand_read(nfl, off, pagesize, buf)) != pagesize) {
727			printk(KERN_NOTICE
728			       "%s: nflash_read return %d\n", mtd->name, ret);
729			continue;
730		}
731
732		/* Try looking at TRX header for rootfs offset */
733		if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
734			mask = pagesize - 1;
735			off = offset + (le32_to_cpu(trx->offsets[1]) & ~mask) - blocksize;
736			shift = (le32_to_cpu(trx->offsets[1]) & mask);
737			romfsb = (struct romfs_super_block *)((unsigned char *)romfsb + shift);
738			cramfsb = (struct cramfs_super *)((unsigned char *)cramfsb + shift);
739			squashfsb = (struct squashfs_super_block *)
740				((unsigned char *)squashfsb + shift);
741			continue;
742		}
743
744		/* romfs is at block zero too */
745		if (romfsb->word0 == ROMSB_WORD0 &&
746		    romfsb->word1 == ROMSB_WORD1) {
747			printk(KERN_NOTICE
748			       "%s: romfs filesystem found at block %d\n",
749			       mtd->name, off / blocksize);
750			break;
751		}
752
753		/* so is cramfs */
754		if (cramfsb->magic == CRAMFS_MAGIC) {
755			printk(KERN_NOTICE
756			       "%s: cramfs filesystem found at block %d\n",
757			       mtd->name, off / blocksize);
758			break;
759		}
760
761		if (squashfsb->s_magic == SQUASHFS_MAGIC) {
762			printk(KERN_NOTICE
763			       "%s: squash filesystem with lzma found at block %d\n",
764			       mtd->name, off / blocksize);
765			break;
766		}
767
768	}
769
770	if (buf)
771		kfree(buf);
772
773	return shift + off;
774}
775
776struct mtd_partition *
777init_nflash_mtd_partitions(hndnand_t *nfl, struct mtd_info *mtd, size_t size)
778{
779	int bootdev;
780	int knldev;
781	int nparts = 0;
782	uint32 offset = 0;
783	uint shift = 0;
784	uint32 top = 0;
785	uint32 bootsz;
786#ifdef CONFIG_FAILSAFE_UPGRADE
787	char *img_boot = nvram_get(BOOTPARTITION);
788	char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
789	char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
790	unsigned int image_first_offset = 0;
791	unsigned int image_second_offset = 0;
792	char dual_image_on = 0;
793
794	/* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
795	 * image
796	 */
797	dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
798
799	if (dual_image_on) {
800		image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
801		image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
802		printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
803			image_second_offset);
804
805	}
806#endif	/* CONFIG_FAILSAFE_UPGRADE */
807
808	bootdev = soc_boot_dev((void *)sih);
809	knldev = soc_knl_dev((void *)sih);
810
811	if (bootdev == SOC_BOOTDEV_NANDFLASH) {
812		bootsz = boot_partition_size(nfl->base);
813		if (bootsz > mtd->erasesize) {
814			/* Prepare double space in case of bad blocks */
815			bootsz = (bootsz << 1);
816		} else {
817			/* CFE occupies at least one block */
818			bootsz = mtd->erasesize;
819		}
820		printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
821
822		/* Size pmon */
823		bcm947xx_nflash_parts[nparts].name = "boot";
824		bcm947xx_nflash_parts[nparts].size = bootsz;
825		bcm947xx_nflash_parts[nparts].offset = top;
826		//bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
827		offset = bcm947xx_nflash_parts[nparts].size;
828		nparts++;
829
830		/* Setup NVRAM MTD partition */
831		bcm947xx_nflash_parts[nparts].name = "nvram";
832		bcm947xx_nflash_parts[nparts].size = nfl_boot_size(nfl) - offset;
833		bcm947xx_nflash_parts[nparts].offset = offset;
834
835		offset = nfl_boot_size(nfl);
836		nparts++;
837	}
838
839	if (knldev == SOC_KNLDEV_NANDFLASH) {
840		/* Setup kernel MTD partition */
841		bcm947xx_nflash_parts[nparts].name = "linux";
842#ifdef CONFIG_FAILSAFE_UPGRADE
843		if (dual_image_on) {
844			bcm947xx_nflash_parts[nparts].size =
845				image_second_offset - image_first_offset;
846		} else
847#endif
848		{
849			bcm947xx_nflash_parts[nparts].size = nparts ?
850				(nfl_boot_os_size(nfl) - nfl_boot_size(nfl)) :
851				nfl_boot_os_size(nfl);
852		}
853		bcm947xx_nflash_parts[nparts].offset = offset;
854
855		shift = lookup_nflash_rootfs_offset(nfl, mtd, offset,
856			bcm947xx_nflash_parts[nparts].size);
857
858#ifdef CONFIG_FAILSAFE_UPGRADE
859		if (dual_image_on)
860			offset = image_second_offset;
861		else
862#endif
863		offset = nfl_boot_os_size(nfl);
864		nparts++;
865
866		/* Setup rootfs MTD partition */
867		bcm947xx_nflash_parts[nparts].name = "rootfs";
868#ifdef CONFIG_FAILSAFE_UPGRADE
869		if (dual_image_on)
870			bcm947xx_nflash_parts[nparts].size = image_second_offset - shift;
871		else
872#endif
873		bcm947xx_nflash_parts[nparts].size = nfl_boot_os_size(nfl) - shift;
874		bcm947xx_nflash_parts[nparts].offset = shift;
875		bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
876		offset = nfl_boot_os_size(nfl);
877
878		nparts++;
879
880#ifdef CONFIG_DUAL_TRX /* ASUS Setup 2nd kernel MTD partition */
881                bcm947xx_nflash_parts[nparts].name = "linux2";
882                bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE;
883                bcm947xx_nflash_parts[nparts].offset = NFL_BOOT_OS_SIZE;
884                nparts++;
885                /* Setup rootfs MTD partition */
886                bcm947xx_nflash_parts[nparts].name = "rootfs2";
887                bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
888                bcm947xx_nflash_parts[nparts].offset = NFL_BOOT_OS_SIZE + shift;
889                bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
890                nparts++;
891#endif /* End of ASUS 2nd FW partition*/
892
893#ifdef CONFIG_FAILSAFE_UPGRADE
894		/* Setup 2nd kernel MTD partition */
895		if (dual_image_on) {
896			bcm947xx_nflash_parts[nparts].name = "linux2";
897			bcm947xx_nflash_parts[nparts].size = nfl_boot_os_size(nfl) - image_second_offset;
898			bcm947xx_nflash_parts[nparts].offset = image_second_offset;
899			shift = lookup_nflash_rootfs_offset(nfl, mtd, image_second_offset,
900			                                    bcm947xx_nflash_parts[nparts].size);
901			nparts++;
902			/* Setup rootfs MTD partition */
903			bcm947xx_nflash_parts[nparts].name = "rootfs2";
904			bcm947xx_nflash_parts[nparts].size = nfl_boot_os_size(nfl) - shift;
905			bcm947xx_nflash_parts[nparts].offset = shift;
906			bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
907			nparts++;
908		}
909#endif	/* CONFIG_FAILSAFE_UPGRADE */
910
911	}
912
913#ifdef PLAT_NAND_JFFS2
914	/* Setup the remainder of NAND Flash as FFS partition */
915	if( size > offset ) {
916		bcm947xx_nflash_parts[nparts].name = "ffs";
917		bcm947xx_nflash_parts[nparts].size = size - offset ;
918		bcm947xx_nflash_parts[nparts].offset = offset;
919		bcm947xx_nflash_parts[nparts].mask_flags = 0;
920		bcm947xx_nflash_parts[nparts].ecclayout = mtd->ecclayout;
921		nparts++;
922	}
923#endif
924
925	return bcm947xx_nflash_parts;
926}
927
928/* LR: Calling this function directly violates Linux API conventions */
929EXPORT_SYMBOL(init_nflash_mtd_partitions);
930#endif /* CONFIG_MTD_NFLASH */
931
932#ifdef CONFIG_CRASHLOG
933extern char *get_logbuf(void);
934extern char *get_logsize(void);
935
936void nvram_store_crash(void)
937{
938	struct mtd_info *mtd = NULL;
939	int i;
940	char *buffer;
941	unsigned char buf[16];
942	int buf_len;
943	int len;
944
945	printk("Trying to store crash\n");
946
947	mtd = get_mtd_device_nm("crash");
948
949	if (!IS_ERR(mtd)) {
950
951		buf_len = get_logsize();
952		buffer = get_logbuf();
953		if (buf_len > mtd->size)
954			buf_len = mtd->size;
955
956		memset(buf,0,sizeof(buf));
957		mtd->read(mtd, 0, sizeof(buf), &len, buf);
958		for (len=0;len<sizeof(buf);len++)
959			if (buf[len]!=0xff) {
960				printk("Could not save crash, partition not clean\n");
961				break;
962			}
963		if (len == sizeof(buf)) {
964			mtd->write(mtd, 0, buf_len, &len, buffer);
965			if (buf_len == len)
966				printk("Crash Saved\n");
967		}
968	} else {
969		printk("Could not find NVRAM partition\n");
970	}
971}
972#endif /* CONFIG_CRASHLOG */
973