• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/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/* To store real PHYS_OFFSET value */
80unsigned int ddr_phys_offset_va = -1;
81EXPORT_SYMBOL(ddr_phys_offset_va);
82
83/* For NS-Ax ACP only */
84unsigned int ns_acp_win_size = SZ_256M;
85EXPORT_SYMBOL(ns_acp_win_size);
86
87struct dummy_super_block {
88	u32	s_magic ;
89};
90
91/* This is the main reference clock 25MHz from external crystal */
92static struct clk clk_ref = {
93	.name = "Refclk",
94	.rate = 25 * 1000000,	/* run-time override */
95	.fixed = 1,
96	.type	= CLK_XTAL,
97};
98
99
100static struct clk_lookup board_clk_lookups[] = {
101	{
102	.con_id		= "refclk",
103	.clk		= &clk_ref,
104	}
105};
106
107static struct mtd_partition bcm947xx_parts[] =
108{
109	{
110		.name = "boot",
111		.size = 0,
112		.offset = 0,
113		.mask_flags = MTD_WRITEABLE
114	},
115	{
116		.name = "linux",
117		.size = 0,
118		.offset = 0
119	},
120	{
121		.name = "rootfs",
122		.size = 0,
123		.offset = 0,
124		.mask_flags = MTD_WRITEABLE
125	},
126	/* reserve sectors for multi-language implementation */
127	/* Foxconn add start, Tony W.Y. Wang, 01/12/2010 */
128	{
129		.name = "ML1",
130		.offset = 0,
131		.size = 0,
132	},
133	{
134		.name = "ML2",
135		.offset = 0,
136		.size = 0,
137	},
138	{
139		.name = "ML3",
140		.offset = 0,
141		.size = 0,
142	},
143	{
144		.name = "ML4",
145		.offset = 0,
146		.size = 0,
147	},
148	{
149		.name = "ML5",
150		.offset = 0,
151		.size = 0,
152	},
153	{
154		.name = "ML6",
155		.offset = 0,
156		.size = 0,
157	},
158	{
159		.name = "ML7",
160		.offset = 0,
161		.size = 0,
162	},
163	/* Foxconn add end, Tony W.Y. Wang, 01/12/2010 */
164	/* Foxconn added start pling 06/30/2006 */
165	{
166		.name = "T_Meter1",
167		.offset = 0,
168		.size = 0,
169	},
170	{
171		.name = "T_Meter2",
172		.offset = 0,
173		.size = 0,
174	},
175	{
176		.name = "POT",
177		.offset = 0,
178		.size = 0,
179	},
180	{
181		.name = "board_data",
182		.offset = 0,
183		.size = 0,
184	},
185	/* Foxconn added end pling 06/30/2006 */
186	{
187		.name = "nvram",
188		.size = 0,
189		.offset = 0
190	},
191	{
192		.name = 0,
193		.size = 0,
194		.offset = 0
195	}
196};
197
198extern int _memsize;
199
200void __init board_map_io(void)
201{
202early_printk("board_map_io\n");
203	/* Install clock sources into the lookup table */
204	clkdev_add_table(board_clk_lookups,
205			ARRAY_SIZE(board_clk_lookups));
206
207	/* Map SoC specific I/O */
208	soc_map_io( &clk_ref );
209}
210
211#if defined(CONFIG_SPI_SPIDEV) && defined(CONFIG_SPI_BCM5301X)
212
213#include <linux/spi/spi.h>
214
215static struct spi_board_info spidev_board_info[] __initdata = {
216	{
217		.modalias	= "spidev",
218		.mode		= SPI_MODE_0,
219		.max_speed_hz	= (1 << 20 ), /* 1Mhz */
220		.bus_num	= 1,
221	},
222};
223
224static void __init board_init_spi(void)
225{
226	spi_register_board_info(spidev_board_info, ARRAY_SIZE(spidev_board_info));
227}
228#else
229inline void board_init_spi(void)
230{
231}
232#endif
233
234
235void __init board_init_irq(void)
236{
237early_printk("board_init_irq\n");
238	soc_init_irq();
239
240	/* serial_setup(sih); */
241}
242
243void board_init_timer(void)
244{
245early_printk("board_init_timer\n");
246	soc_init_timer();
247}
248
249static int __init rootfs_mtdblock(void)
250{
251	int bootdev;
252	int knldev;
253	int block = 0;
254#ifdef CONFIG_FAILSAFE_UPGRADE
255	char *img_boot = nvram_get(BOOTPARTITION);
256#endif
257
258	bootdev = soc_boot_dev((void *)sih);
259	knldev = soc_knl_dev((void *)sih);
260
261	/* NANDBOOT */
262	if (bootdev == SOC_BOOTDEV_NANDFLASH &&
263	    knldev == SOC_KNLDEV_NANDFLASH) {
264#ifdef CONFIG_FAILSAFE_UPGRADE
265		if (img_boot && simple_strtol(img_boot, NULL, 10))
266			return 5;
267		else
268			return 3;
269#else
270		/*Foxconn modify by Hank 10/24/2012*/
271		/*change linux partition when using nandflash boot up*/
272
273#if defined(R6200v2)
274        return 3;
275#elif defined(R7000)
276		return 3;
277#else
278		return 15;
279#endif
280#endif
281	}
282
283	/* SFLASH/PFLASH only */
284	if (bootdev != SOC_BOOTDEV_NANDFLASH &&
285	    knldev != SOC_KNLDEV_NANDFLASH) {
286#ifdef CONFIG_FAILSAFE_UPGRADE
287		if (img_boot && simple_strtol(img_boot, NULL, 10))
288			return 4;
289		else
290			return 2;
291#else
292		return 2;
293#endif
294	}
295
296#ifdef BCMCONFMTD
297	block++;
298#endif
299#ifdef CONFIG_FAILSAFE_UPGRADE
300	if (img_boot && simple_strtol(img_boot, NULL, 10))
301		block += 2;
302#endif
303	/* Boot from norflash and kernel in nandflash */
304
305	return (sizeof(bcm947xx_parts)/sizeof(struct mtd_partition));	/* Bob modified */
306}
307
308static void __init brcm_setup(void)
309{
310	/* Get global SB handle */
311	sih = si_kattach(SI_OSH);
312
313	if (ACP_WAR_ENAB() && BCM4707_CHIP(CHIPID(sih->chip))) {
314		if (sih->chippkg == BCM4708_PKG_ID)
315			ns_acp_win_size = SZ_128M;
316		else if (sih->chippkg == BCM4707_PKG_ID)
317			ns_acp_win_size = SZ_32M;
318		else
319			ns_acp_win_size = SZ_256M;
320	} else if (BCM4707_CHIP(CHIPID(sih->chip)) &&
321		(CHIPREV(sih->chiprev) == 4 || CHIPREV(sih->chiprev) == 6)) {
322		/* Chiprev 4 for NS-B0 and chiprev 6 for NS-B1 */
323		ns_acp_win_size = SZ_1G;
324	}
325
326	if (strncmp(boot_command_line, "root=/dev/mtdblock", strlen("root=/dev/mtdblock")) == 0)
327		sprintf(saved_root_name, "/dev/mtdblock%d", rootfs_mtdblock());
328
329	/* Set watchdog interval in ms */
330        watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);
331
332	/* Ensure at least WATCHDOG_MIN */
333	if ((watchdog > 0) && (watchdog < WATCHDOG_MIN))
334		watchdog = WATCHDOG_MIN;
335
336	/* Set panic timeout in seconds */
337	panic_timeout = watchdog / 1000;
338	panic_on_oops = watchdog / 1000;
339}
340
341void soc_watchdog(void)
342{
343	if (watchdog > 0)
344		si_watchdog_ms(sih, watchdog);
345}
346
347void __init board_init(void)
348{
349early_printk("board_init\n");
350	brcm_setup();
351	/*
352	 * Add common platform devices that do not have board dependent HW
353	 * configurations
354	 */
355	soc_add_devices();
356
357	board_init_spi();
358
359	printk(KERN_NOTICE "ACP (Accelerator Coherence Port) %s\n",
360		(ACP_WAR_ENAB() || arch_is_coherent()) ? "enabled" : "disabled");
361
362	return;
363}
364
365static void __init board_fixup(
366	struct machine_desc *desc,
367	struct tag *t,
368	char **cmdline,
369	struct meminfo *mi
370	)
371{
372	u32 mem_size, lo_size ;
373        early_printk("board_fixup\n" );
374
375	/* Fuxup reference clock rate */
376	if (desc->nr == MACH_TYPE_BRCM_NS_QT )
377		clk_ref.rate = 17594;	/* Emulator ref clock rate */
378
379
380#if defined(BCM_GMAC3)
381	/* In ATLAS builds, cap the total memory to 256M (for both Ax and Bx). */
382	if (_memsize > SZ_256M) {
383		_memsize = SZ_256M;
384		early_printk("ATLAS board_fixup: cap memory to 256M\n");
385	}
386#endif /* BCM_GMAC3 */
387	mem_size = _memsize;
388
389	early_printk("board_fixup: mem=%uMiB\n", mem_size >> 20);
390
391	/* for NS-B0-ACP */
392	if (ACP_WAR_ENAB() || arch_is_coherent()) {
393		mi->bank[0].start = PHYS_OFFSET;
394		mi->bank[0].size = mem_size;
395		mi->nr_banks++;
396		return;
397	}
398
399	lo_size = min(mem_size, DRAM_MEMORY_REGION_SIZE);
400
401	mi->bank[0].start = PHYS_OFFSET;
402	mi->bank[0].size = lo_size;
403	mi->nr_banks++;
404
405	if (lo_size == mem_size)
406		return;
407
408	mi->bank[1].start = PHYS_OFFSET2;
409	mi->bank[1].size = mem_size - lo_size;
410	mi->nr_banks++;
411}
412
413#ifdef CONFIG_ZONE_DMA
414/*
415 * Adjust the zones if there are restrictions for DMA access.
416 */
417void __init bcm47xx_adjust_zones(unsigned long *size, unsigned long *hole)
418{
419	unsigned long dma_size = SZ_128M >> PAGE_SHIFT;
420
421	if (size[0] <= dma_size)
422		return;
423
424	if (ACP_WAR_ENAB() || arch_is_coherent())
425		return;
426
427	size[ZONE_NORMAL] = size[0] - dma_size;
428	size[ZONE_DMA] = dma_size;
429	hole[ZONE_NORMAL] = hole[0];
430	hole[ZONE_DMA] = 0;
431}
432#endif
433
434
435
436static struct sys_timer board_timer = {
437   .init = board_init_timer,
438};
439
440#if (( (IO_BASE_VA >>18) & 0xfffc) != 0x3c40)
441#error IO_BASE_VA
442#endif
443
444MACHINE_START(BRCM_NS, "Northstar Prototype")
445   .phys_io = 					/* UART I/O mapping */
446	IO_BASE_PA,
447   .io_pg_offst = 				/* for early debug */
448	(IO_BASE_VA >>18) & 0xfffc,
449   .fixup = board_fixup,			/* Opt. early setup_arch() */
450   .map_io = board_map_io,			/* Opt. from setup_arch() */
451   .init_irq = board_init_irq,			/* main.c after setup_arch() */
452   .timer  = &board_timer,			/* main.c after IRQs */
453   .init_machine = board_init,			/* Late archinitcall */
454   .boot_params = CONFIG_BOARD_PARAMS_PHYS,
455MACHINE_END
456
457#ifdef	CONFIG_MACH_BRCM_NS_QT
458MACHINE_START(BRCM_NS_QT, "Northstar Emulation Model")
459   .phys_io = 					/* UART I/O mapping */
460	IO_BASE_PA,
461   .io_pg_offst = 				/* for early debug */
462	(IO_BASE_VA >>18) & 0xfffc,
463   .fixup = board_fixup,			/* Opt. early setup_arch() */
464   .map_io = board_map_io,			/* Opt. from setup_arch() */
465   .init_irq = board_init_irq,			/* main.c after setup_arch() */
466   .timer  = &board_timer,			/* main.c after IRQs */
467   .init_machine = board_init,			/* Late archinitcall */
468   .boot_params = CONFIG_BOARD_PARAMS_PHYS,
469MACHINE_END
470#endif
471
472void arch_reset(char mode, const char *cmd)
473{
474#ifdef CONFIG_OUTER_CACHE_SYNC
475	outer_cache.sync = NULL;
476#endif
477	hnd_cpu_reset(sih);
478}
479
480#ifdef CONFIG_MTD_PARTITIONS
481
482static spinlock_t *mtd_lock = NULL;
483
484spinlock_t *partitions_lock_init(void)
485{
486	if (!mtd_lock) {
487		mtd_lock = (spinlock_t *)kzalloc(sizeof(spinlock_t), GFP_KERNEL);
488		if (!mtd_lock)
489			return NULL;
490
491		spin_lock_init( mtd_lock );
492	}
493	return mtd_lock;
494}
495EXPORT_SYMBOL(partitions_lock_init);
496
497static struct nand_hw_control *nand_hwcontrol = NULL;
498struct nand_hw_control *nand_hwcontrol_lock_init(void)
499{
500	if (!nand_hwcontrol) {
501		nand_hwcontrol = (struct nand_hw_control *)kzalloc(sizeof(struct nand_hw_control), GFP_KERNEL);
502		if (!nand_hwcontrol)
503			return NULL;
504
505		spin_lock_init(&nand_hwcontrol->lock);
506		init_waitqueue_head(&nand_hwcontrol->wq);
507	}
508	return nand_hwcontrol;
509}
510EXPORT_SYMBOL(nand_hwcontrol_lock_init);
511
512/* Find out prom size */
513static uint32 boot_partition_size(uint32 flash_phys) {
514	uint32 bootsz, *bisz;
515
516	/* Default is 256K boot partition */
517	bootsz = 256 * 1024;
518
519	/* Do we have a self-describing binary image? */
520	bisz = (uint32 *)(flash_phys + BISZ_OFFSET);
521	if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) {
522		int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX];
523
524		if (isz > (1024 * 1024))
525			bootsz = 2048 * 1024;
526		else if (isz > (512 * 1024))
527			bootsz = 1024 * 1024;
528		else if (isz > (256 * 1024))
529			bootsz = 512 * 1024;
530		else if (isz <= (128 * 1024))
531			bootsz = 128 * 1024;
532	}
533	return bootsz;
534}
535
536#if defined(BCMCONFMTD)
537#define MTD_PARTS 1
538#else
539#define MTD_PARTS 0
540#endif
541#if defined(CONFIG_FAILSAFE_UPGRADE)
542#define FAILSAFE_PARTS 2
543#else
544#define FAILSAFE_PARTS 0
545#endif
546#if defined(CONFIG_CRASHLOG)
547#define CRASHLOG_PARTS 1
548#else
549#define CRASHLOG_PARTS 0
550#endif
551/* boot;nvram;kernel;rootfs;empty */
552#define FLASH_PARTS_NUM	(15+MTD_PARTS+FAILSAFE_PARTS+CRASHLOG_PARTS)
553
554//static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
555
556static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size,
557                                       uint32 *trx_size)
558{
559	struct romfs_super_block *romfsb;
560	struct cramfs_super *cramfsb;
561#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
562	struct squashfs_super_block *squashfsb;
563#else
564	struct dummy_super_block *squashfsb;
565#endif
566	struct trx_header *trx;
567	unsigned char buf[512];
568	int off;
569	size_t len;
570
571	romfsb = (struct romfs_super_block *) buf;
572	cramfsb = (struct cramfs_super *) buf;
573	squashfsb = (void *) buf;
574	trx = (struct trx_header *) buf;
575
576	/* Look at every 64 KB boundary */
577	for (off = *trx_off; off < size; off += (64 * 1024)) {
578		memset(buf, 0xe5, sizeof(buf));
579
580		/*
581		 * Read block 0 to test for romfs and cramfs superblock
582		 */
583		if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
584		    len != sizeof(buf))
585			continue;
586
587		/* Try looking at TRX header for rootfs offset */
588		if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
589			*trx_off = off;
590			*trx_size = le32_to_cpu(trx->len);
591			if (trx->offsets[1] == 0)
592				continue;
593			/*
594			 * Read to test for romfs and cramfs superblock
595			 */
596			off += le32_to_cpu(trx->offsets[1]);
597			memset(buf, 0xe5, sizeof(buf));
598			if (mtd->read(mtd, off, sizeof(buf), &len, buf) || len != sizeof(buf))
599				continue;
600		}
601
602		/* romfs is at block zero too */
603		if (romfsb->word0 == ROMSB_WORD0 &&
604		    romfsb->word1 == ROMSB_WORD1) {
605			printk(KERN_NOTICE
606			       "%s: romfs filesystem found at block %d\n",
607			       mtd->name, off / mtd->erasesize);
608			break;
609		}
610
611		/* so is cramfs */
612		if (cramfsb->magic == CRAMFS_MAGIC) {
613			printk(KERN_NOTICE
614			       "%s: cramfs filesystem found at block %d\n",
615			       mtd->name, off / mtd->erasesize);
616			break;
617		}
618
619		if (squashfsb->s_magic == SQUASHFS_MAGIC) {
620			printk(KERN_NOTICE
621			       "%s: squash filesystem found at block %d\n",
622			       mtd->name, off / mtd->erasesize);
623			break;
624		}
625	}
626
627	return off;
628}
629
630struct mtd_partition *
631init_mtd_partitions(hndsflash_t *sfl_info, struct mtd_info *mtd, size_t size)
632{
633	struct romfs_super_block *romfsb;
634	struct cramfs_super *cramfsb;
635	struct squashfs_super_block *squashfsb;
636	struct trx_header *trx;
637	unsigned char buf[512];
638	int off;
639	size_t len;
640	int i;
641	uint32 offset = 0;
642	uint rfs_off = 0;
643	uint vmlz_off=0, knl_size;
644	uint32 trx_size;
645#ifdef CONFIG_CRASHLOG
646	char create_crash_partition = 0;
647#endif
648
649#if 0
650	romfsb = (struct romfs_super_block *) buf;
651	cramfsb = (struct cramfs_super *) buf;
652	squashfsb = (struct squashfs_super_block *) buf;
653	trx = (struct trx_header *) buf;
654#endif
655
656	/* Setup NVRAM MTD partition */
657	i = (sizeof(bcm947xx_parts)/sizeof(struct mtd_partition)) - 2;
658
659	bcm947xx_parts[i].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
660	bcm947xx_parts[i].offset = size - bcm947xx_parts[i].size;
661
662	/* foxconn added start, zacker, 08/19/2010 */
663	for (i = i - 1; i > 2; i--)
664	{
665		if (strncmp(bcm947xx_parts[i].name, "board_data", 10) == 0)
666			bcm947xx_parts[i].size = (mtd->erasesize) * 1; /* 64K */
667		else if (strncmp(bcm947xx_parts[i].name, "POT", 3) == 0)
668			bcm947xx_parts[i].size = (mtd->erasesize) * 1; /* 64K */
669		else if (strncmp(bcm947xx_parts[i].name, "T_Meter", 7) == 0)
670			bcm947xx_parts[i].size = (mtd->erasesize) * 1; /* 64K */
671		else if (strncmp(bcm947xx_parts[i].name, "ML", 2) == 0)
672			bcm947xx_parts[i].size = (mtd->erasesize) * 1; /* 64K */
673		else
674		{
675			printk(KERN_ERR "%s: Unknow MTD name %s\n",
676			__FUNCTION__, bcm947xx_parts[i].name);
677			break;
678		}
679
680		bcm947xx_parts[i].offset = bcm947xx_parts[i + 1].offset
681									- bcm947xx_parts[i].size;
682	}
683	/* foxconn added end, zacker, 08/19/2010 */
684	/* Size of boot */
685
686		rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size, &trx_size);
687//	bcm947xx_parts[0].size = 256 * 1024;
688	bcm947xx_parts[0].size = vmlz_off;
689	/* Size of linux */
690//	bcm947xx_parts[1].offset = 0;
691	bcm947xx_parts[1].offset = vmlz_off;
692
693//	bcm947xx_parts[1].size = 0;
694	bcm947xx_parts[1].size = mtd->size - vmlz_off;
695	/* size of rootfs */
696    knl_size = bcm947xx_parts[1].size;
697//	bcm947xx_parts[2].offset = 0;
698//	bcm947xx_parts[2].size = 0;
699	bcm947xx_parts[2].size = knl_size - (rfs_off - vmlz_off);
700	bcm947xx_parts[2].offset = rfs_off;
701	bcm947xx_parts[1].size -= (12*0X10000);
702	bcm947xx_parts[2].size -= (12*0X10000);
703#ifdef CONFIG_CRASHLOG
704		if ((bcm947xx_flash_parts[nparts].size - trx_size) >=
705		    ROUNDUP(0x4000, mtd->erasesize)) {
706			bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x4000, mtd->erasesize);
707			create_crash_partition = 1;
708		} else {
709			create_crash_partition = 0;
710
711  }
712#endif
713
714	return bcm947xx_parts;
715}
716
717EXPORT_SYMBOL(init_mtd_partitions);
718
719#endif /* CONFIG_MTD_PARTITIONS */
720
721
722#ifdef	CONFIG_MTD_NFLASH
723/*Foxconn modify start by Hank 10/24/2012*/
724/*add full partition on nandflash for using nandflash boot up*/
725#if defined(R6200v2)
726#define NFLASH_PARTS_NUM	19
727static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {
728	{
729		.name = "boot",
730		.size = 0,
731		.offset = 0,
732		.mask_flags = MTD_WRITEABLE
733	},
734	{
735		.name = "nvram",
736		.size = 0,
737		.offset = 0
738	},
739	{
740		.name = "linux",
741		.size = 0,
742		.offset = 0
743	},
744	{
745		.name = "rootfs",
746		.size = 0,
747		.offset = 0,
748		.mask_flags = MTD_WRITEABLE
749	},
750	{
751		.name = "board_data",
752		.offset = 0,
753		.size = 0,
754	},
755	{
756		.name = "POT1",
757		.offset = 0,
758		.size = 0,
759	},
760	{
761		.name = "POT2",
762		.offset = 0,
763		.size = 0,
764	},
765	{
766		.name = "T_Meter1",
767		.offset = 0,
768		.size = 0,
769	},
770	{
771		.name = "T_Meter2",
772		.offset = 0,
773		.size = 0,
774	},
775	{
776		.name = "ML1",
777		.offset = 0,
778		.size = 0,
779	},
780	{
781		.name = "ML2",
782		.offset = 0,
783		.size = 0,
784	},
785	{
786		.name = "ML3",
787		.offset = 0,
788		.size = 0,
789	},
790	{
791		.name = "ML4",
792		.offset = 0,
793		.size = 0,
794	},
795	{
796		.name = "ML5",
797		.offset = 0,
798		.size = 0,
799	},
800	{
801		.name = "ML6",
802		.offset = 0,
803		.size = 0,
804	},
805	{
806		.name = "ML7",
807		.offset = 0,
808		.size = 0,
809	},
810	{
811		.name = "R1",
812		.offset = 0,
813		.size = 0,
814	},
815	{
816		.name = "R2",
817		.offset = 0,
818		.size = 0,
819	},
820	{
821		.name = 0,
822		.size = 0,
823		.offset = 0
824	}
825};
826#else
827#if defined(R7000)
828#define NFLASH_PARTS_NUM	18
829#else
830#define NFLASH_PARTS_NUM	17
831#endif
832static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {
833	{
834		.name = "boot",
835		.size = 0,
836		.offset = 0,
837		.mask_flags = MTD_WRITEABLE
838	},
839	{
840		.name = "nvram",
841		.size = 0,
842		.offset = 0
843	},
844#if defined(R7000)
845	{
846		.name = "linux",
847		.size = 0,
848		.offset = 0
849	},
850	{
851		.name = "rootfs",
852		.size = 0,
853		.offset = 0,
854		.mask_flags = MTD_WRITEABLE
855	},
856#endif
857	{
858		.name = "board_data",
859		.offset = 0,
860		.size = 0,
861	},
862	{
863		.name = "POT1",
864		.offset = 0,
865		.size = 0,
866	},
867	{
868		.name = "POT2",
869		.offset = 0,
870		.size = 0,
871	},
872	{
873		.name = "T_Meter1",
874		.offset = 0,
875		.size = 0,
876	},
877	{
878		.name = "T_Meter2",
879		.offset = 0,
880		.size = 0,
881	},
882	{
883		.name = "ML1",
884		.offset = 0,
885		.size = 0,
886	},
887	{
888		.name = "ML2",
889		.offset = 0,
890		.size = 0,
891	},
892	{
893		.name = "ML3",
894		.offset = 0,
895		.size = 0,
896	},
897	{
898		.name = "ML4",
899		.offset = 0,
900		.size = 0,
901	},
902	{
903		.name = "ML5",
904		.offset = 0,
905		.size = 0,
906	},
907	{
908		.name = "ML6",
909		.offset = 0,
910		.size = 0,
911	},
912	{
913		.name = "ML7",
914		.offset = 0,
915		.size = 0,
916	},
917#if defined(R7000)
918	{
919		.name = "QoSRule",
920		.offset = 0,
921		.size = 0,
922	},
923#endif
924#if !defined(R7000)
925	{
926		.name = "linux",
927		.size = 0,
928		.offset = 0
929	},
930	{
931		.name = "rootfs",
932		.size = 0,
933		.offset = 0,
934		.mask_flags = MTD_WRITEABLE
935	},
936#endif
937	{
938		.name = 0,
939		.size = 0,
940		.offset = 0
941	}
942};
943#endif
944/*Foxconn modify end by Hank 10/24/2012*/
945
946static uint
947lookup_nflash_rootfs_offset(hndnand_t *nfl, struct mtd_info *mtd, int offset, size_t size)
948{
949	struct romfs_super_block *romfsb;
950	struct cramfs_super *cramfsb;
951	struct dummy_super_block *squashfsb;
952	struct trx_header *trx;
953	unsigned char *buf;
954	uint blocksize, pagesize, mask, blk_offset, off, shift = 0;
955	int ret;
956
957	pagesize = nfl->pagesize;
958	buf = (unsigned char *)kmalloc(pagesize, GFP_KERNEL);
959	if (!buf) {
960		printk("lookup_nflash_rootfs_offset: kmalloc fail\n");
961		return 0;
962	}
963
964	romfsb = (struct romfs_super_block *) buf;
965	cramfsb = (struct cramfs_super *) buf;
966	squashfsb = (void *) buf;
967	trx = (struct trx_header *) buf;
968
969	/* Look at every block boundary till 16MB; higher space is reserved for application data. */
970	blocksize = mtd->erasesize;
971	printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
972	for (off = offset; off < offset + size; off += blocksize) {
973		mask = blocksize - 1;
974		blk_offset = off & ~mask;
975		if (hndnand_checkbadb(nfl, blk_offset) != 0)
976			continue;
977		memset(buf, 0xe5, pagesize);
978		if ((ret = hndnand_read(nfl, off, pagesize, buf)) != pagesize) {
979			printk(KERN_NOTICE
980			       "%s: nflash_read return %d\n", mtd->name, ret);
981			continue;
982		}
983
984		/* Try looking at TRX header for rootfs offset */
985		if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
986			mask = pagesize - 1;
987			off = offset + (le32_to_cpu(trx->offsets[1]) & ~mask) - blocksize;
988			shift = (le32_to_cpu(trx->offsets[1]) & mask);
989			romfsb = (struct romfs_super_block *)((unsigned char *)romfsb + shift);
990			cramfsb = (struct cramfs_super *)((unsigned char *)cramfsb + shift);
991			squashfsb = (struct squashfs_super_block *)
992				((unsigned char *)squashfsb + shift);
993			continue;
994		}
995
996		/* romfs is at block zero too */
997		if (romfsb->word0 == ROMSB_WORD0 &&
998		    romfsb->word1 == ROMSB_WORD1) {
999			printk(KERN_NOTICE
1000			       "%s: romfs filesystem found at block %d\n",
1001			       mtd->name, off / blocksize);
1002			break;
1003		}
1004
1005		/* so is cramfs */
1006		if (cramfsb->magic == CRAMFS_MAGIC) {
1007			printk(KERN_NOTICE
1008			       "%s: cramfs filesystem found at block %d\n",
1009			       mtd->name, off / blocksize);
1010			break;
1011		}
1012
1013		if (squashfsb->s_magic == SQUASHFS_MAGIC) {
1014			printk(KERN_NOTICE
1015			       "%s: squash filesystem with lzma found at block %d\n",
1016			       mtd->name, off / blocksize);
1017			break;
1018		}
1019
1020	}
1021
1022	if (buf)
1023		kfree(buf);
1024
1025	return shift + off;
1026}
1027
1028struct mtd_partition *
1029init_nflash_mtd_partitions(hndnand_t *nfl, struct mtd_info *mtd, size_t size)
1030{
1031	int bootdev;
1032	int knldev;
1033	int nparts = 0;
1034	uint32 offset = 0;
1035	uint shift = 0;
1036	uint32 top = 0;
1037	uint32 bootsz;
1038	/*Foxconn modify start by Hank 10/24/2012*/
1039	uint32 partition_size;
1040	int i=0;
1041	/*Foxconn modify end by Hank 10/24/2012*/
1042#ifdef CONFIG_FAILSAFE_UPGRADE
1043	char *img_boot = nvram_get(BOOTPARTITION);
1044	char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
1045	char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
1046	unsigned int image_first_offset = 0;
1047	unsigned int image_second_offset = 0;
1048	char dual_image_on = 0;
1049
1050	/* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
1051	 * image
1052	 */
1053	dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
1054
1055	if (dual_image_on) {
1056		image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
1057		image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
1058		printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
1059			image_second_offset);
1060
1061	}
1062#endif	/* CONFIG_FAILSAFE_UPGRADE */
1063
1064	bootdev = soc_boot_dev((void *)sih);
1065	knldev = soc_knl_dev((void *)sih);
1066	/*Foxconn modify end by Hank 10/24/2012*/
1067	/*Get erase size of nandflash*/
1068	partition_size = mtd->erasesize;
1069	/*Foxconn modify end by Hank 10/24/2012*/
1070
1071	if (bootdev == SOC_BOOTDEV_NANDFLASH) {
1072		bootsz = boot_partition_size(nfl->base);
1073		if (bootsz > mtd->erasesize) {
1074			/* Prepare double space in case of bad blocks */
1075			/*Foxconn modify start by Hank 10/26/2012*/
1076			/*change bootcode size*/
1077			bootsz = (bootsz << 1);
1078			/*Foxconn modify end by Hank 10/26/2012*/
1079		} else {
1080			/* CFE occupies at least one block */
1081			bootsz = mtd->erasesize;
1082		}
1083		printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
1084
1085		/* Size pmon */
1086		/*Foxconn modify start by Hank 10/24/2012*/
1087		/*set bootcode and nvram size and offset*/
1088		bcm947xx_nflash_parts[0].name = "boot";
1089		/*Foxconn modify start by Hank 10/24/2012*/
1090		/*change to dynamic size of bootcode*/
1091		bcm947xx_nflash_parts[0].size = bootsz;
1092		/*Foxconn modify end by Hank 10/24/2012*/
1093		bcm947xx_nflash_parts[0].offset = top;
1094		bcm947xx_nflash_parts[0].mask_flags = MTD_WRITEABLE; /* forces on read only */
1095		offset = bcm947xx_nflash_parts[0].size;
1096
1097		/*Foxconn modify start by Hank 10/24/2012*/
1098		/*change to dynamic size of nvram*/
1099		bcm947xx_nflash_parts[1].size = NFL_BOOT_SIZE - bootsz;
1100		bcm947xx_nflash_parts[1].offset = bcm947xx_nflash_parts[0].size;
1101		/*Foxconn modify end by Hank 10/24/2012*/
1102		/*remove older partition setting*/
1103#if 0
1104		bcm947xx_nflash_parts[nparts].name = "boot";
1105		bcm947xx_nflash_parts[nparts].size = bootsz;
1106		bcm947xx_nflash_parts[nparts].offset = top;
1107		bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
1108		offset = bcm947xx_nflash_parts[nparts].size;
1109		nparts++;
1110
1111		/* Setup NVRAM MTD partition */
1112		bcm947xx_nflash_parts[nparts].name = "nvram";
1113		bcm947xx_nflash_parts[nparts].size = NFL_BOOT_SIZE - offset;
1114		bcm947xx_nflash_parts[nparts].offset = offset;
1115
1116		offset = NFL_BOOT_SIZE;
1117		nparts++;
1118#endif
1119		/*Foxconn modify end by Hank 10/24/2012*/
1120	}
1121
1122	/*Foxconn modify start by Hank 10/24/2012*/
1123	if (knldev == SOC_KNLDEV_NANDFLASH) {
1124
1125#if defined(R6200v2)
1126		/* Size of linux */
1127		bcm947xx_nflash_parts[2].offset = bcm947xx_nflash_parts[1].offset + bcm947xx_nflash_parts[1].size;
1128		bcm947xx_nflash_parts[2].size = NFL_BOOT_OS_SIZE; /* reserved 32 MB for firmware */ //NFL_BOOT_OS_SIZE - bcm947xx_nflash_parts[2].offset ;
1129
1130		shift = lookup_nflash_rootfs_offset(nfl, mtd, bcm947xx_nflash_parts[2].offset,
1131				bcm947xx_nflash_parts[2].size );
1132
1133		/* size of rootfs */
1134		bcm947xx_nflash_parts[3].offset = shift;
1135		bcm947xx_nflash_parts[3].size = (bcm947xx_nflash_parts[2].offset + bcm947xx_nflash_parts[2].size) - shift;
1136
1137		/* Setup other MTD partition */
1138		for (i = 4; i < 18; i++){
1139			bcm947xx_nflash_parts[i].size = partition_size*2; /* reserved 2 block for each partition */
1140			bcm947xx_nflash_parts[i].offset = bcm947xx_nflash_parts[i-1].offset + bcm947xx_nflash_parts[i-1].size;
1141		}
1142#elif defined(R7000)
1143		bcm947xx_nflash_parts[2].offset = NFL_BOOT_SIZE;
1144		bcm947xx_nflash_parts[2].size = NFL_BOOT_OS_SIZE;
1145
1146		shift = lookup_nflash_rootfs_offset(nfl, mtd, bcm947xx_nflash_parts[2].offset,	bcm947xx_nflash_parts[2].size );
1147
1148		bcm947xx_nflash_parts[3].offset = shift;
1149		bcm947xx_nflash_parts[3].size = (bcm947xx_nflash_parts[2].offset + bcm947xx_nflash_parts[2].size) - shift;
1150
1151		/* size of rootfs */
1152		/* Setup other MTD partition */
1153		for (i = 4; i < 17; i++){
1154                     if(i==7 ||i==8)
1155			bcm947xx_nflash_parts[i].size = (partition_size <<2 );
1156                     else
1157			bcm947xx_nflash_parts[i].size = (partition_size <<1 );
1158		     bcm947xx_nflash_parts[i].offset = bcm947xx_nflash_parts[i-1].offset + bcm947xx_nflash_parts[i-1].size;
1159		}
1160
1161		/* Size of linux */
1162
1163#else
1164		/* Setup other MTD partition */
1165		for (i = 2; i < 14; i++){
1166			bcm947xx_nflash_parts[i].size = partition_size;
1167			bcm947xx_nflash_parts[i].offset = bcm947xx_nflash_parts[i-1].offset + bcm947xx_nflash_parts[i-1].size;
1168		}
1169
1170		/* Size of linux */
1171		bcm947xx_nflash_parts[14].offset = bcm947xx_nflash_parts[i-1].offset + bcm947xx_nflash_parts[i-1].size;
1172		bcm947xx_nflash_parts[14].size = NFL_BOOT_OS_SIZE - bcm947xx_nflash_parts[2].offset ;
1173
1174		shift = lookup_nflash_rootfs_offset(nfl, mtd, bcm947xx_nflash_parts[14].offset,
1175				bcm947xx_nflash_parts[14].size );
1176
1177		/* size of rootfs */
1178		bcm947xx_nflash_parts[15].offset = shift;
1179		bcm947xx_nflash_parts[15].size = (bcm947xx_nflash_parts[14].offset + bcm947xx_nflash_parts[14].size) - shift;
1180#endif /* defined(R6200v2) */
1181		/*remove older partition setting*/
1182#if 0
1183		/* Setup kernel MTD partition */
1184		bcm947xx_nflash_parts[nparts].name = "linux";
1185#ifdef CONFIG_FAILSAFE_UPGRADE
1186		if (dual_image_on) {
1187			bcm947xx_nflash_parts[nparts].size =
1188				image_second_offset - image_first_offset;
1189		} else
1190#endif
1191		{
1192			bcm947xx_nflash_parts[nparts].size =
1193				nparts ? (NFL_BOOT_OS_SIZE - NFL_BOOT_SIZE) : NFL_BOOT_OS_SIZE;
1194		}
1195		bcm947xx_nflash_parts[nparts].offset = offset;
1196
1197		shift = lookup_nflash_rootfs_offset(nfl, mtd, offset,
1198			bcm947xx_nflash_parts[nparts].size);
1199
1200#ifdef CONFIG_FAILSAFE_UPGRADE
1201		if (dual_image_on)
1202			offset = image_second_offset;
1203		else
1204#endif
1205		offset = NFL_BOOT_OS_SIZE;
1206		nparts++;
1207
1208		/* Setup rootfs MTD partition */
1209		bcm947xx_nflash_parts[nparts].name = "rootfs";
1210#ifdef CONFIG_FAILSAFE_UPGRADE
1211		if (dual_image_on)
1212			bcm947xx_nflash_parts[nparts].size = image_second_offset - shift;
1213		else
1214#endif
1215		bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
1216		bcm947xx_nflash_parts[nparts].offset = shift;
1217		bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
1218		offset = NFL_BOOT_OS_SIZE;
1219
1220		nparts++;
1221
1222#ifdef CONFIG_FAILSAFE_UPGRADE
1223		/* Setup 2nd kernel MTD partition */
1224		if (dual_image_on) {
1225			bcm947xx_nflash_parts[nparts].name = "linux2";
1226			bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - image_second_offset;
1227			bcm947xx_nflash_parts[nparts].offset = image_second_offset;
1228			shift = lookup_nflash_rootfs_offset(nfl, mtd, image_second_offset,
1229			                                    bcm947xx_nflash_parts[nparts].size);
1230			nparts++;
1231			/* Setup rootfs MTD partition */
1232			bcm947xx_nflash_parts[nparts].name = "rootfs2";
1233			bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
1234			bcm947xx_nflash_parts[nparts].offset = shift;
1235			bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
1236			nparts++;
1237		}
1238#endif	/* CONFIG_FAILSAFE_UPGRADE */
1239#endif
1240	/*Foxconn modify end by Hank 10/24/2012*/
1241	}
1242
1243#ifdef PLAT_NAND_JFFS2
1244	/* Setup the remainder of NAND Flash as FFS partition */
1245	if( size > offset ) {
1246		bcm947xx_nflash_parts[nparts].name = "ffs";
1247		bcm947xx_nflash_parts[nparts].size = size - offset ;
1248		bcm947xx_nflash_parts[nparts].offset = offset;
1249		bcm947xx_nflash_parts[nparts].mask_flags = 0;
1250		bcm947xx_nflash_parts[nparts].ecclayout = mtd->ecclayout;
1251		nparts++;
1252	}
1253#endif
1254
1255	return bcm947xx_nflash_parts;
1256}
1257
1258/* LR: Calling this function directly violates Linux API conventions */
1259EXPORT_SYMBOL(init_nflash_mtd_partitions);
1260#else
1261
1262/* Note: NFL_BOOT_OS_SIZE is now set to 32M for FAILSAFE issue */
1263#ifndef	NFL_BOOT_OS_SIZE
1264#define	NFL_BOOT_OS_SIZE	SZ_32M
1265#endif
1266
1267/* LR: Here is how partition managers are intended to be */
1268static int parse_cfenand_partitions(struct mtd_info *mtd,
1269                             struct mtd_partition **pparts,
1270                             unsigned long origin)
1271{
1272	unsigned size, offset, nparts ;
1273	static struct mtd_partition cfenand_parts[2] = {{0}};
1274
1275	if ( pparts == NULL )
1276		return -EINVAL;
1277
1278	/*
1279	NOTE:
1280	Can not call init_nflash_mtd_partitions)_ because it depends
1281	on the "other" conflicting driver for its operation,
1282	so instead this will just create two partitions
1283	so that jffs2 does not overwrite bootable areas.
1284	*/
1285
1286	size = mtd->size ;
1287	nparts = 0;
1288	offset = origin ;
1289
1290	printk("%s: slicing up %uMiB provisionally\n", __func__, size >> 20 );
1291
1292	cfenand_parts[nparts].name = "cfenand";
1293	cfenand_parts[nparts].size = NFL_BOOT_OS_SIZE ;
1294	cfenand_parts[nparts].offset = offset ;
1295	cfenand_parts[nparts].mask_flags = MTD_WRITEABLE;
1296	cfenand_parts[nparts].ecclayout = mtd->ecclayout;
1297	nparts++;
1298	offset += NFL_BOOT_OS_SIZE ;
1299
1300	cfenand_parts[nparts].name = "jffs2";
1301	cfenand_parts[nparts].size = size - offset ;
1302	cfenand_parts[nparts].offset = offset;
1303	cfenand_parts[nparts].mask_flags = 0;
1304	cfenand_parts[nparts].ecclayout = mtd->ecclayout;
1305	nparts++;
1306
1307	*pparts = cfenand_parts;
1308	return nparts;
1309}
1310
1311static struct mtd_part_parser cfenand_parser = {
1312        .owner = THIS_MODULE,
1313        .parse_fn = parse_cfenand_partitions,
1314        .name = "cfenandpart",
1315};
1316
1317static int __init cfenenad_parser_init(void)
1318{
1319        return register_mtd_parser(&cfenand_parser);
1320}
1321
1322module_init(cfenenad_parser_init);
1323
1324#endif /* CONFIG_MTD_NFLASH */
1325
1326#ifdef CONFIG_CRASHLOG
1327extern char *get_logbuf(void);
1328extern char *get_logsize(void);
1329
1330void nvram_store_crash(void)
1331{
1332	struct mtd_info *mtd = NULL;
1333	int i;
1334	char *buffer;
1335	unsigned char buf[16];
1336	int buf_len;
1337	int len;
1338
1339	printk("Trying to store crash\n");
1340
1341	mtd = get_mtd_device_nm("crash");
1342
1343	if (!IS_ERR(mtd)) {
1344
1345		buf_len = get_logsize();
1346		buffer = get_logbuf();
1347		if (buf_len > mtd->size)
1348			buf_len = mtd->size;
1349
1350		memset(buf,0,sizeof(buf));
1351		mtd->read(mtd, 0, sizeof(buf), &len, buf);
1352		for (len=0;len<sizeof(buf);len++)
1353			if (buf[len]!=0xff) {
1354				printk("Could not save crash, partition not clean\n");
1355				break;
1356			}
1357		if (len == sizeof(buf)) {
1358			mtd->write(mtd, 0, buf_len, &len, buffer);
1359			if (buf_len == len)
1360				printk("Crash Saved\n");
1361		}
1362	} else {
1363		printk("Could not find NVRAM partition\n");
1364	}
1365}
1366#endif /* CONFIG_CRASHLOG */
1367