Netgear R6400 support
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / arm / mach-brcm-hnd / board_ns.c
blob9ab757e6127db3f8b50afa731228ba19a9e2e475
2 #include <linux/types.h>
3 #include <linux/version.h>
4 #include <linux/init.h>
5 #include <linux/platform_device.h>
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>
13 #include <mach/clkdev.h>
14 #include <mach/hardware.h>
15 #include <mach/memory.h>
16 #include <mach/io_map.h>
18 #include <plat/bsp.h>
19 #include <plat/mpcore.h>
20 #include <plat/plat-bcm5301x.h>
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
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
55 extern char __initdata saved_root_name[];
57 /* Global SB handle */
58 si_t *bcm947xx_sih = NULL;
59 spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
60 EXPORT_SYMBOL(bcm947xx_sih);
61 EXPORT_SYMBOL(bcm947xx_sih_lock);
63 /* Convenience */
64 #define sih bcm947xx_sih
65 #define sih_lock bcm947xx_sih_lock
67 #define WATCHDOG_MIN 3000 /* milliseconds */
68 extern int panic_timeout;
69 extern int panic_on_oops;
70 static int watchdog = 0;
72 #ifdef HNDCTF
73 ctf_t *kcih = NULL;
74 EXPORT_SYMBOL(kcih);
75 ctf_attach_t ctf_attach_fn = NULL;
76 EXPORT_SYMBOL(ctf_attach_fn);
77 #endif /* HNDCTF */
80 struct dummy_super_block {
81 u32 s_magic ;
84 /* This is the main reference clock 25MHz from external crystal */
85 static struct clk clk_ref = {
86 .name = "Refclk",
87 .rate = 25 * 1000000, /* run-time override */
88 .fixed = 1,
89 .type = CLK_XTAL,
93 static struct clk_lookup board_clk_lookups[] = {
95 .con_id = "refclk",
96 .clk = &clk_ref,
100 extern int _memsize;
102 void __init board_map_io(void)
104 early_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));
109 /* Map SoC specific I/O */
110 soc_map_io( &clk_ref );
114 void __init board_init_irq(void)
116 early_printk("board_init_irq\n");
117 soc_init_irq();
119 /* serial_setup(sih); */
122 void board_init_timer(void)
124 early_printk("board_init_timer\n");
125 soc_init_timer();
128 static int __init rootfs_mtdblock(void)
130 int bootdev;
131 int knldev;
132 int block = 0;
133 #ifdef CONFIG_FAILSAFE_UPGRADE
134 char *img_boot = nvram_get(BOOTPARTITION);
135 #endif
137 bootdev = soc_boot_dev((void *)sih);
138 knldev = soc_knl_dev((void *)sih);
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
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
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;
177 static void __init brcm_setup(void)
179 /* Get global SB handle */
180 sih = si_kattach(SI_OSH);
182 if (strncmp(boot_command_line, "root=/dev/mtdblock", strlen("root=/dev/mtdblock")) == 0)
183 sprintf(saved_root_name, "/dev/mtdblock%d", rootfs_mtdblock());
185 /* Set watchdog interval in ms */
186 watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);
188 /* Ensure at least WATCHDOG_MIN */
189 if ((watchdog > 0) && (watchdog < WATCHDOG_MIN))
190 watchdog = WATCHDOG_MIN;
192 /* Set panic timeout in seconds */
193 panic_timeout = watchdog / 1000;
194 panic_on_oops = watchdog / 1000;
197 void soc_watchdog(void)
199 if (watchdog > 0)
200 si_watchdog_ms(sih, watchdog);
203 #define CFE_UPDATE 1 // added by Chen-I for mac/regulation update
205 #ifdef CFE_UPDATE
206 void bcm947xx_watchdog_disable(void)
208 watchdog=0;
209 si_watchdog_ms(sih, 0);
211 #endif
213 void __init board_init(void)
215 early_printk("board_init\n");
216 brcm_setup();
218 * Add common platform devices that do not have board dependent HW
219 * configurations
221 soc_add_devices();
223 return;
226 static void __init board_fixup(
227 struct machine_desc *desc,
228 struct tag *t,
229 char **cmdline,
230 struct meminfo *mi
233 u32 mem_size, lo_size ;
234 early_printk("board_fixup\n" );
236 /* Fuxup reference clock rate */
237 if (desc->nr == MACH_TYPE_BRCM_NS_QT )
238 clk_ref.rate = 17594; /* Emulator ref clock rate */
241 mem_size = _memsize;
243 early_printk("board_fixup: mem=%uMiB\n", mem_size >> 20);
245 lo_size = min(mem_size, DRAM_MEMORY_REGION_SIZE);
247 mi->bank[0].start = PHYS_OFFSET;
248 mi->bank[0].size = lo_size;
249 mi->nr_banks++;
251 if (lo_size == mem_size)
252 return;
254 mi->bank[1].start = PHYS_OFFSET2;
255 mi->bank[1].size = mem_size - lo_size;
256 mi->nr_banks++;
259 #ifdef CONFIG_ZONE_DMA
261 * Adjust the zones if there are restrictions for DMA access.
263 void __init bcm47xx_adjust_zones(unsigned long *size, unsigned long *hole)
265 unsigned long dma_size = SZ_128M >> PAGE_SHIFT;
267 if (size[0] <= dma_size)
268 return;
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;
275 #endif /* CONFIG_ZONE_DMA */
277 static struct sys_timer board_timer = {
278 .init = board_init_timer,
281 #if (( (IO_BASE_VA >>18) & 0xfffc) != 0x3c40)
282 #error IO_BASE_VA
283 #endif
285 MACHINE_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,
296 MACHINE_END
298 #ifdef CONFIG_MACH_BRCM_NS_QT
299 MACHINE_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,
310 MACHINE_END
311 #endif
313 void arch_reset(char mode, const char *cmd)
315 #ifdef CONFIG_OUTER_CACHE_SYNC
316 outer_cache.sync = NULL;
317 #endif
318 hnd_cpu_reset(sih);
321 #ifdef CONFIG_MTD_PARTITIONS
323 static spinlock_t *mtd_lock = NULL;
325 spinlock_t *partitions_lock_init(void)
327 if (!mtd_lock) {
328 mtd_lock = (spinlock_t *)kzalloc(sizeof(spinlock_t), GFP_KERNEL);
329 if (!mtd_lock)
330 return NULL;
332 spin_lock_init( mtd_lock );
334 return mtd_lock;
336 EXPORT_SYMBOL(partitions_lock_init);
338 static struct nand_hw_control *nand_hwcontrol = NULL;
339 struct nand_hw_control *nand_hwcontrol_lock_init(void)
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;
346 spin_lock_init(&nand_hwcontrol->lock);
347 init_waitqueue_head(&nand_hwcontrol->wq);
349 return nand_hwcontrol;
351 EXPORT_SYMBOL(nand_hwcontrol_lock_init);
353 /* Find out prom size */
354 static uint32 boot_partition_size(uint32 flash_phys) {
355 uint32 bootsz, *bisz;
357 /* Default is 256K boot partition */
358 bootsz = 256 * 1024;
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];
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;
374 return bootsz;
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)
400 static struct mtd_partition bcm947xx_flash_parts[FLASH_PARTS_NUM] = {{0}};
402 static uint lookup_flash_rootfs_offset(struct mtd_info *mtd, int *trx_off, size_t size,
403 uint32 *trx_size)
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;
417 romfsb = (struct romfs_super_block *) buf;
418 cramfsb = (struct cramfs_super *) buf;
419 squashfsb = (void *) buf;
420 trx = (struct trx_header *) buf;
422 /* Look at every 64 KB boundary */
423 for (off = *trx_off; off < size; off += (64 * 1024)) {
424 memset(buf, 0xe5, sizeof(buf));
427 * Read block 0 to test for romfs and cramfs superblock
429 if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
430 len != sizeof(buf))
431 continue;
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;
440 * Read to test for romfs and cramfs superblock
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;
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;
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;
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;
473 return off;
476 struct mtd_partition *
477 init_mtd_partitions(hndsflash_t *sfl_info, struct mtd_info *mtd, size_t size)
479 int bootdev;
480 int knldev;
481 int nparts = 0;
482 uint32 offset = 0;
483 uint32 maxsize = 0;
484 uint rfs_off = 0;
485 uint vmlz_off, knl_size;
486 uint32 top = 0;
487 uint32 bootsz;
488 uint32 trx_size;
489 #ifdef CONFIG_CRASHLOG
490 char create_crash_partition = 0;
491 #endif
492 #ifdef CONFIG_FAILSAFE_UPGRADE
493 char *img_boot = nvram_get(BOOTPARTITION);
494 char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
495 char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
496 unsigned int image_first_offset = 0;
497 unsigned int image_second_offset = 0;
498 char dual_image_on = 0;
500 /* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
501 * image
503 dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
505 if (dual_image_on) {
506 image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
507 image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
508 printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
509 image_second_offset);
512 #endif /* CONFIG_FAILSAFE_UPGRADE */
514 /* limit size for R6300V2/R6250 */
515 if (nvram_match("boardnum", "679") && nvram_match("boardtype", "0x0646")
516 && nvram_match("boardrev", "0x1110")) {
517 maxsize = 0x200000;
518 size = maxsize;
520 /* R7000 */
521 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665")
522 && nvram_match("boardrev", "0x1301")) {
523 maxsize = 0x200000;
524 size = maxsize;
526 /* R6400 */
527 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0646")
528 && nvram_match("boardrev", "0x1601")) {
529 maxsize = 0x200000;
530 size = maxsize;
533 bootdev = soc_boot_dev((void *)sih);
534 knldev = soc_knl_dev((void *)sih);
536 if (bootdev == SOC_BOOTDEV_NANDFLASH) {
537 /* Do not init MTD partitions on NOR flash when NAND boot */
538 return NULL;
541 if (knldev != SOC_KNLDEV_NANDFLASH) {
542 vmlz_off = 0;
543 rfs_off = lookup_flash_rootfs_offset(mtd, &vmlz_off, size, &trx_size);
545 /* Size pmon */
546 bcm947xx_flash_parts[nparts].name = "boot";
547 bcm947xx_flash_parts[nparts].size = vmlz_off;
548 bcm947xx_flash_parts[nparts].offset = top;
549 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
550 nparts++;
552 /* Setup kernel MTD partition */
553 bcm947xx_flash_parts[nparts].name = "linux";
554 #ifdef CONFIG_FAILSAFE_UPGRADE
555 if (trx_size > (image_second_offset-image_first_offset)) {
556 printk("sflash size is too small to afford two images.\n");
557 dual_image_on = 0;
558 image_first_offset = 0;
559 image_second_offset = 0;
561 if (dual_image_on) {
562 bcm947xx_flash_parts[nparts].size = image_second_offset-image_first_offset;
563 } else {
564 bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
566 /* Reserve for NVRAM */
567 bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
568 #ifdef PLC
569 /* Reserve for PLC */
570 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
571 #endif
572 #ifdef BCMCONFMTD
573 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
574 #endif
576 #else
578 bcm947xx_flash_parts[nparts].size = mtd->size - vmlz_off;
580 #ifdef PLC
581 /* Reserve for PLC */
582 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
583 #endif
584 /* Reserve for NVRAM */
585 bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
587 #ifdef BCMCONFMTD
588 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
589 #endif
590 #endif /* CONFIG_FAILSAFE_UPGRADE */
592 /* Reserve for board_data */
593 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665")
594 && nvram_match("boardrev", "0x1301") && nvram_match("model", "R1D")) {
595 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x10000, mtd->erasesize);
599 #ifdef CONFIG_CRASHLOG
600 if ((bcm947xx_flash_parts[nparts].size - trx_size) >=
601 ROUNDUP(0x4000, mtd->erasesize)) {
602 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x4000, mtd->erasesize);
603 create_crash_partition = 1;
604 } else {
605 create_crash_partition = 0;
607 #endif
609 bcm947xx_flash_parts[nparts].offset = vmlz_off;
610 knl_size = bcm947xx_flash_parts[nparts].size;
611 offset = bcm947xx_flash_parts[nparts].offset + knl_size;
612 nparts++;
614 /* Setup rootfs MTD partition */
615 bcm947xx_flash_parts[nparts].name = "rootfs";
616 bcm947xx_flash_parts[nparts].size = knl_size - (rfs_off - vmlz_off);
617 bcm947xx_flash_parts[nparts].offset = rfs_off;
618 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
619 offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
620 nparts++;
622 #if defined(CONFIG_CRASHLOG) && defined(BCMDBG)
623 if (create_crash_partition) {
624 /* Setup crash MTD partition */
625 bcm947xx_flash_parts[nparts].name = "crash";
626 bcm947xx_flash_parts[nparts].size = ROUNDUP(0x4000, mtd->erasesize);
627 bcm947xx_flash_parts[nparts].offset = offset;
628 bcm947xx_flash_parts[nparts].mask_flags = 0;
629 nparts++;
631 #endif
632 #ifdef CONFIG_FAILSAFE_UPGRADE
633 if (dual_image_on) {
634 offset = image_second_offset;
635 rfs_off = lookup_flash_rootfs_offset(mtd, &offset, size, &trx_size);
636 /* When the second image doesn't exist,
637 * set the rootfs use the same offset with the kernel
639 if (rfs_off == size)
640 rfs_off = offset;
642 vmlz_off = offset;
643 /* Setup kernel2 MTD partition */
644 bcm947xx_flash_parts[nparts].name = "linux2";
645 bcm947xx_flash_parts[nparts].size = mtd->size - image_second_offset;
646 /* Reserve for NVRAM */
647 bcm947xx_flash_parts[nparts].size -= ROUNDUP(nvram_space, mtd->erasesize);
649 #ifdef BCMCONFMTD
650 bcm947xx_flash_parts[nparts].size -= (mtd->erasesize *4);
651 #endif
652 #ifdef PLC
653 /* Reserve for PLC */
654 bcm947xx_flash_parts[nparts].size -= ROUNDUP(0x1000, mtd->erasesize);
655 #endif
656 bcm947xx_flash_parts[nparts].offset = image_second_offset;
657 knl_size = bcm947xx_flash_parts[nparts].size;
658 offset = bcm947xx_flash_parts[nparts].offset + knl_size;
659 nparts++;
661 /* Setup rootfs MTD partition */
662 bcm947xx_flash_parts[nparts].name = "rootfs2";
663 bcm947xx_flash_parts[nparts].size =
664 knl_size - (rfs_off - image_second_offset);
665 bcm947xx_flash_parts[nparts].offset = rfs_off;
666 /* forces on read only */
667 bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE;
668 nparts++;
670 #endif /* CONFIG_FAILSAFE_UPGRADE */
672 } else {
673 bootsz = boot_partition_size(sfl_info->base);
674 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
675 /* Size pmon */
676 if (maxsize)
677 bootsz = maxsize;
678 bcm947xx_flash_parts[nparts].name = "boot";
679 bcm947xx_flash_parts[nparts].size = bootsz;
680 bcm947xx_flash_parts[nparts].offset = top;
681 //bcm947xx_flash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
682 offset = bcm947xx_flash_parts[nparts].size;
683 nparts++;
686 #ifdef BCMCONFMTD
687 /* Setup CONF MTD partition */
688 bcm947xx_flash_parts[nparts].name = "confmtd";
689 bcm947xx_flash_parts[nparts].size = mtd->erasesize * 4;
690 bcm947xx_flash_parts[nparts].offset = offset;
691 offset = bcm947xx_flash_parts[nparts].offset + bcm947xx_flash_parts[nparts].size;
692 nparts++;
693 #endif /* BCMCONFMTD */
695 #ifdef PLC
696 /* Setup plc MTD partition */
697 bcm947xx_flash_parts[nparts].name = "plc";
698 bcm947xx_flash_parts[nparts].size = ROUNDUP(0x1000, mtd->erasesize);
699 bcm947xx_flash_parts[nparts].offset =
700 size - (ROUNDUP(nvram_space, mtd->erasesize) + ROUNDUP(0x1000, mtd->erasesize));
701 nparts++;
702 #endif
704 /* Setup board_data partition */
705 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665")
706 && nvram_match("boardrev", "0x1301") && nvram_match("model", "R1D")) {
707 bcm947xx_flash_parts[nparts].name = "board_data";
708 bcm947xx_flash_parts[nparts].size = ROUNDUP(0x10000, mtd->erasesize);
709 bcm947xx_flash_parts[nparts].offset = 0xFE0000;
710 nparts++;
713 /* Setup nvram MTD partition */
714 bcm947xx_flash_parts[nparts].name = "nvram";
715 bcm947xx_flash_parts[nparts].size = ROUNDUP(nvram_space, mtd->erasesize);
717 /* R1D */
718 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665")
719 && nvram_match("boardrev", "0x1301") && nvram_match("model", "R1D")) {
720 bcm947xx_flash_parts[nparts].offset = 0xFF0000;
721 } else {
722 if (maxsize)
723 bcm947xx_flash_parts[nparts].offset = (size - 0x10000) - bcm947xx_flash_parts[nparts].size;
724 else
725 bcm947xx_flash_parts[nparts].offset = size - bcm947xx_flash_parts[nparts].size;
728 nparts++;
730 return bcm947xx_flash_parts;
733 EXPORT_SYMBOL(init_mtd_partitions);
735 #endif /* CONFIG_MTD_PARTITIONS */
738 #ifdef CONFIG_MTD_NFLASH
740 #define NFLASH_PARTS_NUM 7
741 static struct mtd_partition bcm947xx_nflash_parts[NFLASH_PARTS_NUM] = {{0}};
743 static uint
744 lookup_nflash_rootfs_offset(hndnand_t *nfl, struct mtd_info *mtd, int offset, size_t size)
746 struct romfs_super_block *romfsb;
747 struct cramfs_super *cramfsb;
748 struct dummy_super_block *squashfsb;
749 struct trx_header *trx;
750 unsigned char *buf;
751 uint blocksize, pagesize, mask, blk_offset, off, shift = 0;
752 int ret;
754 pagesize = nfl->pagesize;
755 buf = (unsigned char *)kmalloc(pagesize, GFP_KERNEL);
756 if (!buf) {
757 printk("lookup_nflash_rootfs_offset: kmalloc fail\n");
758 return 0;
761 romfsb = (struct romfs_super_block *) buf;
762 cramfsb = (struct cramfs_super *) buf;
763 squashfsb = (void *) buf;
764 trx = (struct trx_header *) buf;
766 /* Look at every block boundary till 16MB; higher space is reserved for application data. */
767 blocksize = mtd->erasesize;
768 printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
769 for (off = offset; off < offset + size; off += blocksize) {
770 mask = blocksize - 1;
771 blk_offset = off & ~mask;
772 if (hndnand_checkbadb(nfl, blk_offset) != 0)
773 continue;
774 memset(buf, 0xe5, pagesize);
775 if ((ret = hndnand_read(nfl, off, pagesize, buf)) != pagesize) {
776 printk(KERN_NOTICE
777 "%s: nflash_read return %d\n", mtd->name, ret);
778 continue;
781 /* Try looking at TRX header for rootfs offset */
782 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
783 mask = pagesize - 1;
784 off = offset + (le32_to_cpu(trx->offsets[1]) & ~mask) - blocksize;
785 shift = (le32_to_cpu(trx->offsets[1]) & mask);
786 romfsb = (struct romfs_super_block *)((unsigned char *)romfsb + shift);
787 cramfsb = (struct cramfs_super *)((unsigned char *)cramfsb + shift);
788 squashfsb = (struct squashfs_super_block *)
789 ((unsigned char *)squashfsb + shift);
790 continue;
793 /* romfs is at block zero too */
794 if (romfsb->word0 == ROMSB_WORD0 &&
795 romfsb->word1 == ROMSB_WORD1) {
796 printk(KERN_NOTICE
797 "%s: romfs filesystem found at block %d\n",
798 mtd->name, off / blocksize);
799 break;
802 /* so is cramfs */
803 if (cramfsb->magic == CRAMFS_MAGIC) {
804 printk(KERN_NOTICE
805 "%s: cramfs filesystem found at block %d\n",
806 mtd->name, off / blocksize);
807 break;
810 if (squashfsb->s_magic == SQUASHFS_MAGIC) {
811 printk(KERN_NOTICE
812 "%s: squash filesystem with lzma found at block %d\n",
813 mtd->name, off / blocksize);
814 break;
819 if (buf)
820 kfree(buf);
822 return shift + off;
825 struct mtd_partition *
826 init_nflash_mtd_partitions(hndnand_t *nfl, struct mtd_info *mtd, size_t size)
828 int bootdev;
829 int knldev;
830 int nparts = 0;
831 uint32 offset = 0;
832 uint shift = 0;
833 uint32 top = 0;
834 uint32 bootsz;
835 uint32 nvsz = 0;
836 uint32 bootossz = nfl_boot_os_size(nfl);
837 uint boardnum = bcm_strtoul(nvram_safe_get("boardnum"), NULL, 0);
838 //EA6700 EA6900
839 if (((boardnum == 1) || (nvram_get("boardnum") == NULL)) && nvram_match("boardtype", "0xF646") && nvram_match("boardrev", "0x1100")) {
840 bootossz = 0x4000000;
841 nvsz = 0x100000;
843 else if (((boardnum == 1) || (nvram_get("boardnum") == NULL)) && nvram_match("boardtype","0xD646") && nvram_match("boardrev","0x1100")) {
844 bootossz = 0x4000000;
845 nvsz = 0x100000;
847 #ifdef CONFIG_FAILSAFE_UPGRADE
848 char *img_boot = nvram_get(BOOTPARTITION);
849 char *imag_1st_offset = nvram_get(IMAGE_FIRST_OFFSET);
850 char *imag_2nd_offset = nvram_get(IMAGE_SECOND_OFFSET);
851 unsigned int image_first_offset = 0;
852 unsigned int image_second_offset = 0;
853 char dual_image_on = 0;
855 /* The image_1st_size and image_2nd_size are necessary if the Flash does not have any
856 * image
858 dual_image_on = (img_boot != NULL && imag_1st_offset != NULL && imag_2nd_offset != NULL);
860 if (dual_image_on) {
861 image_first_offset = simple_strtol(imag_1st_offset, NULL, 10);
862 image_second_offset = simple_strtol(imag_2nd_offset, NULL, 10);
863 printk("The first offset=%x, 2nd offset=%x\n", image_first_offset,
864 image_second_offset);
867 #endif /* CONFIG_FAILSAFE_UPGRADE */
869 bootdev = soc_boot_dev((void *)sih);
870 knldev = soc_knl_dev((void *)sih);
872 if (bootdev == SOC_BOOTDEV_NANDFLASH) {
873 bootsz = boot_partition_size(nfl->base);
874 if (bootsz > mtd->erasesize) {
875 /* Prepare double space in case of bad blocks */
876 bootsz = (bootsz << 1);
877 } else {
878 /* CFE occupies at least one block */
879 bootsz = mtd->erasesize;
881 printk("Boot partition size = %d(0x%x)\n", bootsz, bootsz);
883 /* Size pmon */
884 bcm947xx_nflash_parts[nparts].name = "boot";
885 bcm947xx_nflash_parts[nparts].size = bootsz;
886 bcm947xx_nflash_parts[nparts].offset = top;
887 //bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE; /* forces on read only */
888 offset = bcm947xx_nflash_parts[nparts].size;
889 nparts++;
891 /* Setup NVRAM MTD partition */
892 bcm947xx_nflash_parts[nparts].name = "nvram";
893 if (nvsz)
894 bcm947xx_nflash_parts[nparts].size = nvsz;
895 else
896 bcm947xx_nflash_parts[nparts].size = nfl_boot_size(nfl) - offset;
897 bcm947xx_nflash_parts[nparts].offset = offset;
899 offset = nfl_boot_size(nfl);
900 nparts++;
903 if (knldev == SOC_KNLDEV_NANDFLASH) {
904 /* Setup kernel MTD partition */
905 bcm947xx_nflash_parts[nparts].name = "linux";
906 #ifdef CONFIG_FAILSAFE_UPGRADE
907 if (dual_image_on) {
908 bcm947xx_nflash_parts[nparts].size =
909 image_second_offset - image_first_offset;
910 } else
911 #endif
913 bcm947xx_nflash_parts[nparts].size = nparts ?
914 (bootossz - nfl_boot_size(nfl)) :
915 nfl_boot_os_size(nfl);
917 /* fix linux offset for the R6300V2/R6250 units */
918 if (nvram_match("boardnum","679") && nvram_match("boardtype", "0x0646") && nvram_match("boardrev", "0x1110")) {
919 offset += 0x180000;
920 bcm947xx_nflash_parts[nparts].size -= 0x180000;
922 /* R7000 */
923 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665") && nvram_match("boardrev", "0x1301")) {
924 bcm947xx_nflash_parts[nparts].size += 0x200000;
926 /* R7000 */
927 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0646") && nvram_match("boardrev", "0x1601")) {
928 bcm947xx_nflash_parts[nparts].size += 0x200000;
931 bcm947xx_nflash_parts[nparts].offset = offset;
933 shift = lookup_nflash_rootfs_offset(nfl, mtd, offset,
934 bcm947xx_nflash_parts[nparts].size);
936 #ifdef CONFIG_FAILSAFE_UPGRADE
937 if (dual_image_on)
938 offset = image_second_offset;
939 else
940 #endif
941 offset = bootossz;
942 nparts++;
944 /* Setup rootfs MTD partition */
945 bcm947xx_nflash_parts[nparts].name = "rootfs";
946 #ifdef CONFIG_FAILSAFE_UPGRADE
947 if (dual_image_on)
948 bcm947xx_nflash_parts[nparts].size = image_second_offset - shift;
949 else
950 #endif
951 bcm947xx_nflash_parts[nparts].size = bootossz - shift;
952 bcm947xx_nflash_parts[nparts].offset = shift;
953 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
954 offset = nfl_boot_os_size(nfl);
956 nparts++;
958 #ifdef CONFIG_DUAL_TRX /* ASUS Setup 2nd kernel MTD partition */
959 bcm947xx_nflash_parts[nparts].name = "linux2";
960 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE;
961 bcm947xx_nflash_parts[nparts].offset = NFL_BOOT_OS_SIZE;
962 nparts++;
963 /* Setup rootfs MTD partition */
964 bcm947xx_nflash_parts[nparts].name = "rootfs2";
965 bcm947xx_nflash_parts[nparts].size = NFL_BOOT_OS_SIZE - shift;
966 bcm947xx_nflash_parts[nparts].offset = NFL_BOOT_OS_SIZE + shift;
967 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
968 nparts++;
969 #endif /* End of ASUS 2nd FW partition*/
971 /* again, to fix R6300V2, 6400 and R7000 */
972 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0665") && nvram_match("boardrev", "0x1301")) {
974 bcm947xx_nflash_parts[nparts].name = "board_data";
975 bcm947xx_nflash_parts[nparts].size = 0x40000;
976 bcm947xx_nflash_parts[nparts].offset = 0x2200000;
977 nparts++;
980 if (nvram_match("boardnum", "32") && nvram_match("boardtype", "0x0646") && nvram_match("boardrev", "0x1601")) {
982 bcm947xx_nflash_parts[nparts].name = "board_data";
983 bcm947xx_nflash_parts[nparts].size = 0x40000;
984 bcm947xx_nflash_parts[nparts].offset = 0x2200000;
985 nparts++;
988 if ( nvram_match("boardnum","679") && nvram_match("boardtype", "0x0646") && (nvram_match("boardrev", "0x1110")) ) {
989 bcm947xx_nflash_parts[nparts].name = "board_data";
990 bcm947xx_nflash_parts[nparts].size = 0x20000;
991 bcm947xx_nflash_parts[nparts].offset = 0x200000;
992 nparts++;
994 #ifdef CONFIG_FAILSAFE_UPGRADE
995 /* Setup 2nd kernel MTD partition */
996 if (dual_image_on) {
997 bcm947xx_nflash_parts[nparts].name = "linux2";
998 bcm947xx_nflash_parts[nparts].size = bootossz - image_second_offset;
999 bcm947xx_nflash_parts[nparts].offset = image_second_offset;
1000 shift = lookup_nflash_rootfs_offset(nfl, mtd, image_second_offset,
1001 bcm947xx_nflash_parts[nparts].size);
1002 nparts++;
1003 /* Setup rootfs MTD partition */
1004 bcm947xx_nflash_parts[nparts].name = "rootfs2";
1005 bcm947xx_nflash_parts[nparts].size = bootossz - shift;
1006 bcm947xx_nflash_parts[nparts].offset = shift;
1007 bcm947xx_nflash_parts[nparts].mask_flags = MTD_WRITEABLE;
1008 nparts++;
1010 #endif /* CONFIG_FAILSAFE_UPGRADE */
1014 #ifdef PLAT_NAND_JFFS2
1015 /* Setup the remainder of NAND Flash as FFS partition */
1016 if( size > offset ) {
1017 bcm947xx_nflash_parts[nparts].name = "ffs";
1018 bcm947xx_nflash_parts[nparts].size = size - offset ;
1019 bcm947xx_nflash_parts[nparts].offset = offset;
1020 bcm947xx_nflash_parts[nparts].mask_flags = 0;
1021 bcm947xx_nflash_parts[nparts].ecclayout = mtd->ecclayout;
1022 nparts++;
1024 #endif
1026 return bcm947xx_nflash_parts;
1029 /* LR: Calling this function directly violates Linux API conventions */
1030 EXPORT_SYMBOL(init_nflash_mtd_partitions);
1031 #endif /* CONFIG_MTD_NFLASH */
1033 #ifdef CONFIG_CRASHLOG
1034 extern char *get_logbuf(void);
1035 extern char *get_logsize(void);
1037 void nvram_store_crash(void)
1039 struct mtd_info *mtd = NULL;
1040 int i;
1041 char *buffer;
1042 unsigned char buf[16];
1043 int buf_len;
1044 int len;
1046 printk("Trying to store crash\n");
1048 mtd = get_mtd_device_nm("crash");
1050 if (!IS_ERR(mtd)) {
1052 buf_len = get_logsize();
1053 buffer = get_logbuf();
1054 if (buf_len > mtd->size)
1055 buf_len = mtd->size;
1057 memset(buf,0,sizeof(buf));
1058 mtd->read(mtd, 0, sizeof(buf), &len, buf);
1059 for (len=0;len<sizeof(buf);len++)
1060 if (buf[len]!=0xff) {
1061 printk("Could not save crash, partition not clean\n");
1062 break;
1064 if (len == sizeof(buf)) {
1065 mtd->write(mtd, 0, buf_len, &len, buffer);
1066 if (buf_len == len)
1067 printk("Crash Saved\n");
1069 } else {
1070 printk("Could not find NVRAM partition\n");
1073 #endif /* CONFIG_CRASHLOG */