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