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