Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (67 commits)
[MTD] [MAPS] Fix printk format warning in nettel.c
[MTD] [NAND] add cmdline parsing (mtdparts=) support to cafe_nand
[MTD] CFI: remove major/minor version check for command set 0x0002
[MTD] [NAND] ndfc driver
[MTD] [TESTS] Fix some size_t printk format warnings
[MTD] LPDDR Makefile and KConfig
[MTD] LPDDR extended physmap driver to support LPDDR flash
[MTD] LPDDR added new pfow_base parameter
[MTD] LPDDR Command set driver
[MTD] LPDDR PFOW definition
[MTD] LPDDR QINFO records definitions
[MTD] LPDDR qinfo probing.
[MTD] [NAND] pxa3xx: convert from ns to clock ticks more accurately
[MTD] [NAND] pxa3xx: fix non-page-aligned reads
[MTD] [NAND] fix nandsim sched.h references
[MTD] [NAND] alauda: use USB API functions rather than constants
[MTD] struct device - replace bus_id with dev_name(), dev_set_name()
[MTD] fix m25p80 64-bit divisions
[MTD] fix dataflash 64-bit divisions
[MTD] [NAND] Set the fsl elbc ECCM according the settings in bootloader.
...

Fixed up trivial debug conflicts in drivers/mtd/devices/{m25p80.c,mtd_dataflash.c}

+6159 -696
+39
Documentation/powerpc/dts-bindings/4xx/ndfc.txt
··· 1 + AMCC NDFC (NanD Flash Controller) 2 + 3 + Required properties: 4 + - compatible : "ibm,ndfc". 5 + - reg : should specify chip select and size used for the chip (0x2000). 6 + 7 + Optional properties: 8 + - ccr : NDFC config and control register value (default 0). 9 + - bank-settings : NDFC bank configuration register value (default 0). 10 + 11 + Notes: 12 + - partition(s) - follows the OF MTD standard for partitions 13 + 14 + Example: 15 + 16 + ndfc@1,0 { 17 + compatible = "ibm,ndfc"; 18 + reg = <0x00000001 0x00000000 0x00002000>; 19 + ccr = <0x00001000>; 20 + bank-settings = <0x80002222>; 21 + #address-cells = <1>; 22 + #size-cells = <1>; 23 + 24 + nand { 25 + #address-cells = <1>; 26 + #size-cells = <1>; 27 + 28 + partition@0 { 29 + label = "kernel"; 30 + reg = <0x00000000 0x00200000>; 31 + }; 32 + partition@200000 { 33 + label = "root"; 34 + reg = <0x00200000 0x03E00000>; 35 + }; 36 + }; 37 + }; 38 + 39 +
+54
arch/arm/mach-pxa/corgi.c
··· 27 27 #include <linux/spi/spi.h> 28 28 #include <linux/spi/ads7846.h> 29 29 #include <linux/spi/corgi_lcd.h> 30 + #include <linux/mtd/sharpsl.h> 30 31 #include <video/w100fb.h> 31 32 32 33 #include <asm/setup.h> ··· 543 542 static inline void corgi_init_spi(void) {} 544 543 #endif 545 544 545 + static struct mtd_partition sharpsl_nand_partitions[] = { 546 + { 547 + .name = "System Area", 548 + .offset = 0, 549 + .size = 7 * 1024 * 1024, 550 + }, 551 + { 552 + .name = "Root Filesystem", 553 + .offset = 7 * 1024 * 1024, 554 + .size = 25 * 1024 * 1024, 555 + }, 556 + { 557 + .name = "Home Filesystem", 558 + .offset = MTDPART_OFS_APPEND, 559 + .size = MTDPART_SIZ_FULL, 560 + }, 561 + }; 562 + 563 + static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 564 + 565 + static struct nand_bbt_descr sharpsl_bbt = { 566 + .options = 0, 567 + .offs = 4, 568 + .len = 2, 569 + .pattern = scan_ff_pattern 570 + }; 571 + 572 + static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = { 573 + .badblock_pattern = &sharpsl_bbt, 574 + .partitions = sharpsl_nand_partitions, 575 + .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions), 576 + }; 577 + 578 + static struct resource sharpsl_nand_resources[] = { 579 + { 580 + .start = 0x0C000000, 581 + .end = 0x0C000FFF, 582 + .flags = IORESOURCE_MEM, 583 + }, 584 + }; 585 + 586 + static struct platform_device sharpsl_nand_device = { 587 + .name = "sharpsl-nand", 588 + .id = -1, 589 + .resource = sharpsl_nand_resources, 590 + .num_resources = ARRAY_SIZE(sharpsl_nand_resources), 591 + .dev.platform_data = &sharpsl_nand_platform_data, 592 + }; 593 + 546 594 static struct mtd_partition sharpsl_rom_parts[] = { 547 595 { 548 596 .name ="Boot PROM Filesystem", ··· 627 577 &corgifb_device, 628 578 &corgikbd_device, 629 579 &corgiled_device, 580 + &sharpsl_nand_device, 630 581 &sharpsl_rom_device, 631 582 }; 632 583 ··· 667 616 pxa_set_i2c_info(NULL); 668 617 669 618 platform_scoop_config = &corgi_pcmcia_config; 619 + 620 + if (machine_is_husky()) 621 + sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; 670 622 671 623 platform_add_devices(devices, ARRAY_SIZE(devices)); 672 624 }
+51
arch/arm/mach-pxa/poodle.c
··· 24 24 #include <linux/gpio.h> 25 25 #include <linux/spi/spi.h> 26 26 #include <linux/spi/ads7846.h> 27 + #include <linux/mtd/sharpsl.h> 27 28 28 29 #include <mach/hardware.h> 29 30 #include <asm/mach-types.h> ··· 415 414 .lcd_conn = LCD_COLOR_TFT_16BPP, 416 415 }; 417 416 417 + static struct mtd_partition sharpsl_nand_partitions[] = { 418 + { 419 + .name = "System Area", 420 + .offset = 0, 421 + .size = 7 * 1024 * 1024, 422 + }, 423 + { 424 + .name = "Root Filesystem", 425 + .offset = 7 * 1024 * 1024, 426 + .size = 22 * 1024 * 1024, 427 + }, 428 + { 429 + .name = "Home Filesystem", 430 + .offset = MTDPART_OFS_APPEND, 431 + .size = MTDPART_SIZ_FULL, 432 + }, 433 + }; 434 + 435 + static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 436 + 437 + static struct nand_bbt_descr sharpsl_bbt = { 438 + .options = 0, 439 + .offs = 4, 440 + .len = 2, 441 + .pattern = scan_ff_pattern 442 + }; 443 + 444 + static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = { 445 + .badblock_pattern = &sharpsl_bbt, 446 + .partitions = sharpsl_nand_partitions, 447 + .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions), 448 + }; 449 + 450 + static struct resource sharpsl_nand_resources[] = { 451 + { 452 + .start = 0x0C000000, 453 + .end = 0x0C000FFF, 454 + .flags = IORESOURCE_MEM, 455 + }, 456 + }; 457 + 458 + static struct platform_device sharpsl_nand_device = { 459 + .name = "sharpsl-nand", 460 + .id = -1, 461 + .resource = sharpsl_nand_resources, 462 + .num_resources = ARRAY_SIZE(sharpsl_nand_resources), 463 + .dev.platform_data = &sharpsl_nand_platform_data, 464 + }; 465 + 418 466 static struct mtd_partition sharpsl_rom_parts[] = { 419 467 { 420 468 .name ="Boot PROM Filesystem", ··· 497 447 static struct platform_device *devices[] __initdata = { 498 448 &poodle_locomo_device, 499 449 &poodle_scoop_device, 450 + &sharpsl_nand_device, 500 451 &sharpsl_rom_device, 501 452 }; 502 453
+77
arch/arm/mach-pxa/spitz.c
··· 31 31 #include <linux/spi/spi.h> 32 32 #include <linux/spi/ads7846.h> 33 33 #include <linux/spi/corgi_lcd.h> 34 + #include <linux/mtd/sharpsl.h> 34 35 35 36 #include <asm/setup.h> 36 37 #include <asm/memory.h> ··· 614 613 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_ALTERNATE_MAPPING, 615 614 }; 616 615 616 + static struct mtd_partition sharpsl_nand_partitions[] = { 617 + { 618 + .name = "System Area", 619 + .offset = 0, 620 + .size = 7 * 1024 * 1024, 621 + }, 622 + { 623 + .name = "Root Filesystem", 624 + .offset = 7 * 1024 * 1024, 625 + }, 626 + { 627 + .name = "Home Filesystem", 628 + .offset = MTDPART_OFS_APPEND, 629 + .size = MTDPART_SIZ_FULL, 630 + }, 631 + }; 632 + 633 + static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 634 + 635 + static struct nand_bbt_descr sharpsl_bbt = { 636 + .options = 0, 637 + .offs = 4, 638 + .len = 2, 639 + .pattern = scan_ff_pattern 640 + }; 641 + 642 + static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = { 643 + .badblock_pattern = &sharpsl_bbt, 644 + .partitions = sharpsl_nand_partitions, 645 + .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions), 646 + }; 647 + 648 + static struct resource sharpsl_nand_resources[] = { 649 + { 650 + .start = 0x0C000000, 651 + .end = 0x0C000FFF, 652 + .flags = IORESOURCE_MEM, 653 + }, 654 + }; 655 + 656 + static struct platform_device sharpsl_nand_device = { 657 + .name = "sharpsl-nand", 658 + .id = -1, 659 + .resource = sharpsl_nand_resources, 660 + .num_resources = ARRAY_SIZE(sharpsl_nand_resources), 661 + .dev.platform_data = &sharpsl_nand_platform_data, 662 + }; 663 + 617 664 618 665 static struct mtd_partition sharpsl_rom_parts[] = { 619 666 { ··· 697 648 &spitzscoop_device, 698 649 &spitzkbd_device, 699 650 &spitzled_device, 651 + &sharpsl_nand_device, 700 652 &sharpsl_rom_device, 701 653 }; 702 654 ··· 720 670 init_gpio_reset(SPITZ_GPIO_ON_RESET, 1); 721 671 pm_power_off = spitz_poweroff; 722 672 arm_pm_restart = spitz_restart; 673 + 674 + if (machine_is_spitz()) { 675 + sharpsl_nand_partitions[1].size = 5 * 1024 * 1024; 676 + } else if (machine_is_akita()) { 677 + sharpsl_nand_partitions[1].size = 58 * 1024 * 1024; 678 + } else if (machine_is_borzoi()) { 679 + sharpsl_nand_partitions[1].size = 32 * 1024 * 1024; 680 + } 723 681 724 682 PMCR = 0x00; 725 683 ··· 773 715 }, 774 716 }; 775 717 718 + static struct nand_bbt_descr sharpsl_akita_bbt = { 719 + .options = 0, 720 + .offs = 4, 721 + .len = 1, 722 + .pattern = scan_ff_pattern 723 + }; 724 + 725 + static struct nand_ecclayout akita_oobinfo = { 726 + .eccbytes = 24, 727 + .eccpos = { 728 + 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, 729 + 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, 730 + 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, 731 + .oobfree = {{0x08, 0x09}} 732 + }; 733 + 776 734 static void __init akita_init(void) 777 735 { 778 736 spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; 737 + 738 + sharpsl_nand_platform_data.badblock_pattern = &sharpsl_akita_bbt; 739 + sharpsl_nand_platform_data.ecc_layout = &akita_oobinfo; 779 740 780 741 /* We just pretend the second element of the array doesn't exist */ 781 742 spitz_pcmcia_config.num_devs = 1;
+10
drivers/mtd/Kconfig
··· 45 45 devices. Partitioning on NFTL 'devices' is a different - that's the 46 46 'normal' form of partitioning used on a block device. 47 47 48 + config MTD_TESTS 49 + tristate "MTD tests support" 50 + depends on m 51 + help 52 + This option includes various MTD tests into compilation. The tests 53 + should normally be compiled as kernel modules. The modules perform 54 + various checks and verifications when loaded. 55 + 48 56 config MTD_REDBOOT_PARTS 49 57 tristate "RedBoot partition table parsing" 50 58 depends on MTD_PARTITIONS ··· 323 315 source "drivers/mtd/nand/Kconfig" 324 316 325 317 source "drivers/mtd/onenand/Kconfig" 318 + 319 + source "drivers/mtd/lpddr/Kconfig" 326 320 327 321 source "drivers/mtd/ubi/Kconfig" 328 322
+1 -1
drivers/mtd/Makefile
··· 29 29 nftl-objs := nftlcore.o nftlmount.o 30 30 inftl-objs := inftlcore.o inftlmount.o 31 31 32 - obj-y += chips/ maps/ devices/ nand/ onenand/ 32 + obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ 33 33 34 34 obj-$(CONFIG_MTD_UBI) += ubi/
+6 -6
drivers/mtd/chips/cfi_cmdset_0001.c
··· 58 58 static int cfi_intelext_writev(struct mtd_info *, const struct kvec *, unsigned long, loff_t, size_t *); 59 59 static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); 60 60 static void cfi_intelext_sync (struct mtd_info *); 61 - static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len); 62 - static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); 61 + static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 62 + static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 63 63 #ifdef CONFIG_MTD_OTP 64 64 static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); 65 65 static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); ··· 558 558 } 559 559 560 560 for (i=0; i<mtd->numeraseregions;i++){ 561 - printk(KERN_DEBUG "erase region %d: offset=0x%x,size=0x%x,blocks=%d\n", 562 - i,mtd->eraseregions[i].offset, 561 + printk(KERN_DEBUG "erase region %d: offset=0x%llx,size=0x%x,blocks=%d\n", 562 + i,(unsigned long long)mtd->eraseregions[i].offset, 563 563 mtd->eraseregions[i].erasesize, 564 564 mtd->eraseregions[i].numblocks); 565 565 } ··· 2058 2058 return ret; 2059 2059 } 2060 2060 2061 - static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 2061 + static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 2062 2062 { 2063 2063 int ret; 2064 2064 ··· 2082 2082 return ret; 2083 2083 } 2084 2084 2085 - static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 2085 + static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 2086 2086 { 2087 2087 int ret; 2088 2088
+14 -4
drivers/mtd/chips/cfi_cmdset_0002.c
··· 71 71 static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); 72 72 #include "fwh_lock.h" 73 73 74 - static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len); 75 - static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); 74 + static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 75 + static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 76 76 77 77 static struct mtd_chip_driver cfi_amdstd_chipdrv = { 78 78 .probe = NULL, /* Not usable directly */ ··· 322 322 }; 323 323 324 324 325 + static void cfi_fixup_major_minor(struct cfi_private *cfi, 326 + struct cfi_pri_amdstd *extp) 327 + { 328 + if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && 329 + extp->MajorVersion == '0') 330 + extp->MajorVersion = '1'; 331 + } 332 + 325 333 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) 326 334 { 327 335 struct cfi_private *cfi = map->fldrv_priv; ··· 370 362 kfree(mtd); 371 363 return NULL; 372 364 } 365 + 366 + cfi_fixup_major_minor(cfi, extp); 373 367 374 368 if (extp->MajorVersion != '1' || 375 369 (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { ··· 1784 1774 return ret; 1785 1775 } 1786 1776 1787 - static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 1777 + static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 1788 1778 { 1789 1779 return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL); 1790 1780 } 1791 1781 1792 - static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1782 + static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 1793 1783 { 1794 1784 return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL); 1795 1785 }
+7 -7
drivers/mtd/chips/cfi_cmdset_0020.c
··· 42 42 unsigned long count, loff_t to, size_t *retlen); 43 43 static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *); 44 44 static void cfi_staa_sync (struct mtd_info *); 45 - static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len); 46 - static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); 45 + static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 46 + static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 47 47 static int cfi_staa_suspend (struct mtd_info *); 48 48 static void cfi_staa_resume (struct mtd_info *); 49 49 ··· 221 221 } 222 222 223 223 for (i=0; i<mtd->numeraseregions;i++){ 224 - printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n", 225 - i,mtd->eraseregions[i].offset, 224 + printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n", 225 + i, (unsigned long long)mtd->eraseregions[i].offset, 226 226 mtd->eraseregions[i].erasesize, 227 227 mtd->eraseregions[i].numblocks); 228 228 } ··· 964 964 adr += regions[i].erasesize; 965 965 len -= regions[i].erasesize; 966 966 967 - if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) 967 + if (adr % (1<< cfi->chipshift) == (((unsigned long)regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) 968 968 i++; 969 969 970 970 if (adr >> cfi->chipshift) { ··· 1135 1135 spin_unlock_bh(chip->mutex); 1136 1136 return 0; 1137 1137 } 1138 - static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 1138 + static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 1139 1139 { 1140 1140 struct map_info *map = mtd->priv; 1141 1141 struct cfi_private *cfi = map->fldrv_priv; ··· 1284 1284 spin_unlock_bh(chip->mutex); 1285 1285 return 0; 1286 1286 } 1287 - static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1287 + static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 1288 1288 { 1289 1289 struct map_info *map = mtd->priv; 1290 1290 struct cfi_private *cfi = map->fldrv_priv;
+2 -2
drivers/mtd/chips/fwh_lock.h
··· 77 77 } 78 78 79 79 80 - static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len) 80 + static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len) 81 81 { 82 82 int ret; 83 83 ··· 88 88 } 89 89 90 90 91 - static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len) 91 + static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len) 92 92 { 93 93 int ret; 94 94
+2 -4
drivers/mtd/devices/lart.c
··· 619 619 }; 620 620 #endif 621 621 622 - int __init lart_flash_init (void) 622 + static int __init lart_flash_init (void) 623 623 { 624 624 int result; 625 625 memset (&mtd,0,sizeof (mtd)); ··· 690 690 return (result); 691 691 } 692 692 693 - void __exit lart_flash_exit (void) 693 + static void __exit lart_flash_exit (void) 694 694 { 695 695 #ifndef HAVE_PARTITIONS 696 696 del_mtd_device (&mtd); ··· 705 705 MODULE_LICENSE("GPL"); 706 706 MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>"); 707 707 MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board"); 708 - 709 -
+21 -20
drivers/mtd/devices/m25p80.c
··· 20 20 #include <linux/device.h> 21 21 #include <linux/interrupt.h> 22 22 #include <linux/mutex.h> 23 + #include <linux/math64.h> 23 24 24 25 #include <linux/mtd/mtd.h> 25 26 #include <linux/mtd/partitions.h> ··· 170 169 */ 171 170 static int erase_chip(struct m25p *flash) 172 171 { 173 - DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n", 174 - dev_name(&flash->spi->dev), __func__, 175 - flash->mtd.size / 1024); 172 + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n", 173 + dev_name(&flash->spi->dev), __func__, 174 + (long long)(flash->mtd.size >> 10)); 176 175 177 176 /* Wait until finished previous write command. */ 178 177 if (wait_till_ready(flash)) ··· 233 232 { 234 233 struct m25p *flash = mtd_to_m25p(mtd); 235 234 u32 addr,len; 235 + uint32_t rem; 236 236 237 - DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", 238 - dev_name(&flash->spi->dev), __func__, "at", 239 - (u32)instr->addr, instr->len); 237 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n", 238 + dev_name(&flash->spi->dev), __func__, "at", 239 + (long long)instr->addr, (long long)instr->len); 240 240 241 241 /* sanity checks */ 242 242 if (instr->addr + instr->len > flash->mtd.size) 243 243 return -EINVAL; 244 - if ((instr->addr % mtd->erasesize) != 0 245 - || (instr->len % mtd->erasesize) != 0) { 244 + div_u64_rem(instr->len, mtd->erasesize, &rem); 245 + if (rem) 246 246 return -EINVAL; 247 - } 248 247 249 248 addr = instr->addr; 250 249 len = instr->len; ··· 678 677 flash->mtd.erasesize = info->sector_size; 679 678 } 680 679 681 - dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name, 682 - flash->mtd.size / 1024); 680 + dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name, 681 + (long long)flash->mtd.size >> 10); 683 682 684 683 DEBUG(MTD_DEBUG_LEVEL2, 685 - "mtd .name = %s, .size = 0x%.8x (%uMiB) " 684 + "mtd .name = %s, .size = 0x%llx (%lldMiB) " 686 685 ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", 687 686 flash->mtd.name, 688 - flash->mtd.size, flash->mtd.size / (1024*1024), 687 + (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), 689 688 flash->mtd.erasesize, flash->mtd.erasesize / 1024, 690 689 flash->mtd.numeraseregions); 691 690 692 691 if (flash->mtd.numeraseregions) 693 692 for (i = 0; i < flash->mtd.numeraseregions; i++) 694 693 DEBUG(MTD_DEBUG_LEVEL2, 695 - "mtd.eraseregions[%d] = { .offset = 0x%.8x, " 694 + "mtd.eraseregions[%d] = { .offset = 0x%llx, " 696 695 ".erasesize = 0x%.8x (%uKiB), " 697 696 ".numblocks = %d }\n", 698 - i, flash->mtd.eraseregions[i].offset, 697 + i, (long long)flash->mtd.eraseregions[i].offset, 699 698 flash->mtd.eraseregions[i].erasesize, 700 699 flash->mtd.eraseregions[i].erasesize / 1024, 701 700 flash->mtd.eraseregions[i].numblocks); ··· 723 722 if (nr_parts > 0) { 724 723 for (i = 0; i < nr_parts; i++) { 725 724 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " 726 - "{.name = %s, .offset = 0x%.8x, " 727 - ".size = 0x%.8x (%uKiB) }\n", 725 + "{.name = %s, .offset = 0x%llx, " 726 + ".size = 0x%llx (%lldKiB) }\n", 728 727 i, parts[i].name, 729 - parts[i].offset, 730 - parts[i].size, 731 - parts[i].size / 1024); 728 + (long long)parts[i].offset, 729 + (long long)parts[i].size, 730 + (long long)(parts[i].size >> 10)); 732 731 } 733 732 flash->partitioned = 1; 734 733 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+15 -9
drivers/mtd/devices/mtd_dataflash.c
··· 16 16 #include <linux/device.h> 17 17 #include <linux/mutex.h> 18 18 #include <linux/err.h> 19 + #include <linux/math64.h> 19 20 20 21 #include <linux/spi/spi.h> 21 22 #include <linux/spi/flash.h> ··· 153 152 struct spi_message msg; 154 153 unsigned blocksize = priv->page_size << 3; 155 154 uint8_t *command; 155 + uint32_t rem; 156 156 157 - DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", 158 - dev_name(&spi->dev), 159 - instr->addr, instr->len); 157 + DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n", 158 + dev_name(&spi->dev), (long long)instr->addr, 159 + (long long)instr->len); 160 160 161 161 /* Sanity checks */ 162 - if ((instr->addr + instr->len) > mtd->size 163 - || (instr->len % priv->page_size) != 0 164 - || (instr->addr % priv->page_size) != 0) 162 + if (instr->addr + instr->len > mtd->size) 163 + return -EINVAL; 164 + div_u64_rem(instr->len, priv->page_size, &rem); 165 + if (rem) 166 + return -EINVAL; 167 + div_u64_rem(instr->addr, priv->page_size, &rem); 168 + if (rem) 165 169 return -EINVAL; 166 170 167 171 spi_message_init(&msg); ··· 184 178 /* Calculate flash page address; use block erase (for speed) if 185 179 * we're at a block boundary and need to erase the whole block. 186 180 */ 187 - pageaddr = instr->addr / priv->page_size; 181 + pageaddr = div_u64(instr->len, priv->page_size); 188 182 do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize; 189 183 pageaddr = pageaddr << priv->page_offset; 190 184 ··· 673 667 if (revision >= 'c') 674 668 otp_tag = otp_setup(device, revision); 675 669 676 - dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n", 677 - name, DIV_ROUND_UP(device->size, 1024), 670 + dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n", 671 + name, (long long)((device->size + 1023) >> 10), 678 672 pagesize, otp_tag); 679 673 dev_set_drvdata(&spi->dev, priv); 680 674
+50 -50
drivers/mtd/ftl.c
··· 109 109 /* Each memory region corresponds to a minor device */ 110 110 typedef struct partition_t { 111 111 struct mtd_blktrans_dev mbd; 112 - u_int32_t state; 113 - u_int32_t *VirtualBlockMap; 114 - u_int32_t *VirtualPageMap; 115 - u_int32_t FreeTotal; 112 + uint32_t state; 113 + uint32_t *VirtualBlockMap; 114 + uint32_t *VirtualPageMap; 115 + uint32_t FreeTotal; 116 116 struct eun_info_t { 117 - u_int32_t Offset; 118 - u_int32_t EraseCount; 119 - u_int32_t Free; 120 - u_int32_t Deleted; 117 + uint32_t Offset; 118 + uint32_t EraseCount; 119 + uint32_t Free; 120 + uint32_t Deleted; 121 121 } *EUNInfo; 122 122 struct xfer_info_t { 123 - u_int32_t Offset; 124 - u_int32_t EraseCount; 125 - u_int16_t state; 123 + uint32_t Offset; 124 + uint32_t EraseCount; 125 + uint16_t state; 126 126 } *XferInfo; 127 - u_int16_t bam_index; 128 - u_int32_t *bam_cache; 129 - u_int16_t DataUnits; 130 - u_int32_t BlocksPerUnit; 127 + uint16_t bam_index; 128 + uint32_t *bam_cache; 129 + uint16_t DataUnits; 130 + uint32_t BlocksPerUnit; 131 131 erase_unit_header_t header; 132 132 } partition_t; 133 133 ··· 199 199 static int build_maps(partition_t *part) 200 200 { 201 201 erase_unit_header_t header; 202 - u_int16_t xvalid, xtrans, i; 203 - u_int blocks, j; 202 + uint16_t xvalid, xtrans, i; 203 + unsigned blocks, j; 204 204 int hdr_ok, ret = -1; 205 205 ssize_t retval; 206 206 loff_t offset; ··· 269 269 270 270 /* Set up virtual page map */ 271 271 blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize; 272 - part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t)); 272 + part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t)); 273 273 if (!part->VirtualBlockMap) 274 274 goto out_XferInfo; 275 275 276 - memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t)); 276 + memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t)); 277 277 part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize; 278 278 279 - part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t), 279 + part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t), 280 280 GFP_KERNEL); 281 281 if (!part->bam_cache) 282 282 goto out_VirtualBlockMap; ··· 290 290 offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); 291 291 292 292 ret = part->mbd.mtd->read(part->mbd.mtd, offset, 293 - part->BlocksPerUnit * sizeof(u_int32_t), &retval, 293 + part->BlocksPerUnit * sizeof(uint32_t), &retval, 294 294 (unsigned char *)part->bam_cache); 295 295 296 296 if (ret) ··· 332 332 ======================================================================*/ 333 333 334 334 static int erase_xfer(partition_t *part, 335 - u_int16_t xfernum) 335 + uint16_t xfernum) 336 336 { 337 337 int ret; 338 338 struct xfer_info_t *xfer; ··· 408 408 erase_unit_header_t header; 409 409 struct xfer_info_t *xfer; 410 410 int nbam, ret; 411 - u_int32_t ctl; 411 + uint32_t ctl; 412 412 ssize_t retlen; 413 413 loff_t offset; 414 414 ··· 430 430 } 431 431 432 432 /* Write the BAM stub */ 433 - nbam = (part->BlocksPerUnit * sizeof(u_int32_t) + 433 + nbam = (part->BlocksPerUnit * sizeof(uint32_t) + 434 434 le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE; 435 435 436 436 offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset); 437 437 ctl = cpu_to_le32(BLOCK_CONTROL); 438 438 439 - for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) { 439 + for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) { 440 440 441 - ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), 441 + ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t), 442 442 &retlen, (u_char *)&ctl); 443 443 444 444 if (ret) ··· 461 461 462 462 ======================================================================*/ 463 463 464 - static int copy_erase_unit(partition_t *part, u_int16_t srcunit, 465 - u_int16_t xferunit) 464 + static int copy_erase_unit(partition_t *part, uint16_t srcunit, 465 + uint16_t xferunit) 466 466 { 467 467 u_char buf[SECTOR_SIZE]; 468 468 struct eun_info_t *eun; 469 469 struct xfer_info_t *xfer; 470 - u_int32_t src, dest, free, i; 471 - u_int16_t unit; 470 + uint32_t src, dest, free, i; 471 + uint16_t unit; 472 472 int ret; 473 473 ssize_t retlen; 474 474 loff_t offset; 475 - u_int16_t srcunitswap = cpu_to_le16(srcunit); 475 + uint16_t srcunitswap = cpu_to_le16(srcunit); 476 476 477 477 eun = &part->EUNInfo[srcunit]; 478 478 xfer = &part->XferInfo[xferunit]; ··· 486 486 offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); 487 487 488 488 ret = part->mbd.mtd->read(part->mbd.mtd, offset, 489 - part->BlocksPerUnit * sizeof(u_int32_t), 489 + part->BlocksPerUnit * sizeof(uint32_t), 490 490 &retlen, (u_char *) (part->bam_cache)); 491 491 492 492 /* mark the cache bad, in case we get an error later */ ··· 503 503 offset = xfer->Offset + 20; /* Bad! */ 504 504 unit = cpu_to_le16(0x7fff); 505 505 506 - ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t), 506 + ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint16_t), 507 507 &retlen, (u_char *) &unit); 508 508 509 509 if (ret) { ··· 560 560 561 561 562 562 /* All clear? Then update the LogicalEUN again */ 563 - ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t), 563 + ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t), 564 564 &retlen, (u_char *)&srcunitswap); 565 565 566 566 if (ret) { ··· 605 605 606 606 static int reclaim_block(partition_t *part) 607 607 { 608 - u_int16_t i, eun, xfer; 609 - u_int32_t best; 608 + uint16_t i, eun, xfer; 609 + uint32_t best; 610 610 int queued, ret; 611 611 612 612 DEBUG(0, "ftl_cs: reclaiming space...\n"); ··· 723 723 } 724 724 #endif 725 725 726 - static u_int32_t find_free(partition_t *part) 726 + static uint32_t find_free(partition_t *part) 727 727 { 728 - u_int16_t stop, eun; 729 - u_int32_t blk; 728 + uint16_t stop, eun; 729 + uint32_t blk; 730 730 size_t retlen; 731 731 int ret; 732 732 ··· 749 749 750 750 ret = part->mbd.mtd->read(part->mbd.mtd, 751 751 part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), 752 - part->BlocksPerUnit * sizeof(u_int32_t), 752 + part->BlocksPerUnit * sizeof(uint32_t), 753 753 &retlen, (u_char *) (part->bam_cache)); 754 754 755 755 if (ret) { ··· 786 786 static int ftl_read(partition_t *part, caddr_t buffer, 787 787 u_long sector, u_long nblocks) 788 788 { 789 - u_int32_t log_addr, bsize; 789 + uint32_t log_addr, bsize; 790 790 u_long i; 791 791 int ret; 792 792 size_t offset, retlen; ··· 829 829 830 830 ======================================================================*/ 831 831 832 - static int set_bam_entry(partition_t *part, u_int32_t log_addr, 833 - u_int32_t virt_addr) 832 + static int set_bam_entry(partition_t *part, uint32_t log_addr, 833 + uint32_t virt_addr) 834 834 { 835 - u_int32_t bsize, blk, le_virt_addr; 835 + uint32_t bsize, blk, le_virt_addr; 836 836 #ifdef PSYCHO_DEBUG 837 - u_int32_t old_addr; 837 + uint32_t old_addr; 838 838 #endif 839 - u_int16_t eun; 839 + uint16_t eun; 840 840 int ret; 841 841 size_t retlen, offset; 842 842 ··· 845 845 bsize = 1 << part->header.EraseUnitSize; 846 846 eun = log_addr / bsize; 847 847 blk = (log_addr % bsize) / SECTOR_SIZE; 848 - offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) + 848 + offset = (part->EUNInfo[eun].Offset + blk * sizeof(uint32_t) + 849 849 le32_to_cpu(part->header.BAMOffset)); 850 850 851 851 #ifdef PSYCHO_DEBUG 852 - ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t), 852 + ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(uint32_t), 853 853 &retlen, (u_char *)&old_addr); 854 854 if (ret) { 855 855 printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret); ··· 886 886 #endif 887 887 part->bam_cache[blk] = le_virt_addr; 888 888 } 889 - ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), 889 + ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t), 890 890 &retlen, (u_char *)&le_virt_addr); 891 891 892 892 if (ret) { ··· 900 900 static int ftl_write(partition_t *part, caddr_t buffer, 901 901 u_long sector, u_long nblocks) 902 902 { 903 - u_int32_t bsize, log_addr, virt_addr, old_addr, blk; 903 + uint32_t bsize, log_addr, virt_addr, old_addr, blk; 904 904 u_long i; 905 905 int ret; 906 906 size_t retlen, offset;
+1 -1
drivers/mtd/inftlcore.c
··· 50 50 struct INFTLrecord *inftl; 51 51 unsigned long temp; 52 52 53 - if (mtd->type != MTD_NANDFLASH) 53 + if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) 54 54 return; 55 55 /* OK, this is moderately ugly. But probably safe. Alternatives? */ 56 56 if (memcmp(mtd->name, "DiskOnChip", 10))
+2 -2
drivers/mtd/inftlmount.c
··· 63 63 * otherwise. 64 64 */ 65 65 inftl->EraseSize = inftl->mbd.mtd->erasesize; 66 - inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; 66 + inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize; 67 67 68 68 inftl->MediaUnit = BLOCK_NIL; 69 69 ··· 187 187 mh->BlockMultiplierBits); 188 188 inftl->EraseSize = inftl->mbd.mtd->erasesize << 189 189 mh->BlockMultiplierBits; 190 - inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize; 190 + inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize; 191 191 block >>= mh->BlockMultiplierBits; 192 192 } 193 193
+22
drivers/mtd/lpddr/Kconfig
··· 1 + # drivers/mtd/chips/Kconfig 2 + 3 + menu "LPDDR flash memory drivers" 4 + depends on MTD!=n 5 + 6 + config MTD_LPDDR 7 + tristate "Support for LPDDR flash chips" 8 + select MTD_QINFO_PROBE 9 + help 10 + This option enables support of LPDDR (Low power double data rate) 11 + flash chips. Synonymous with Mobile-DDR. It is a new standard for 12 + DDR memories, intended for battery-operated systems. 13 + 14 + config MTD_QINFO_PROBE 15 + tristate "Detect flash chips by QINFO probe" 16 + help 17 + Device Information for LPDDR chips is offered through the Overlay 18 + Window QINFO interface, permits software to be used for entire 19 + families of devices. This serves similar purpose of CFI on legacy 20 + Flash products 21 + endmenu 22 +
+6
drivers/mtd/lpddr/Makefile
··· 1 + # 2 + # linux/drivers/mtd/lpddr/Makefile 3 + # 4 + 5 + obj-$(CONFIG_MTD_QINFO_PROBE) += qinfo_probe.o 6 + obj-$(CONFIG_MTD_LPDDR) += lpddr_cmds.o
+796
drivers/mtd/lpddr/lpddr_cmds.c
··· 1 + /* 2 + * LPDDR flash memory device operations. This module provides read, write, 3 + * erase, lock/unlock support for LPDDR flash memories 4 + * (C) 2008 Korolev Alexey <akorolev@infradead.org> 5 + * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com> 6 + * Many thanks to Roman Borisov for intial enabling 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * as published by the Free Software Foundation; either version 2 11 + * of the License, or (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21 + * 02110-1301, USA. 22 + * TODO: 23 + * Implement VPP management 24 + * Implement XIP support 25 + * Implement OTP support 26 + */ 27 + #include <linux/mtd/pfow.h> 28 + #include <linux/mtd/qinfo.h> 29 + 30 + static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len, 31 + size_t *retlen, u_char *buf); 32 + static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, 33 + size_t len, size_t *retlen, const u_char *buf); 34 + static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs, 35 + unsigned long count, loff_t to, size_t *retlen); 36 + static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr); 37 + static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 38 + static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 39 + static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len, 40 + size_t *retlen, void **mtdbuf, resource_size_t *phys); 41 + static void lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len); 42 + static int get_chip(struct map_info *map, struct flchip *chip, int mode); 43 + static int chip_ready(struct map_info *map, struct flchip *chip, int mode); 44 + static void put_chip(struct map_info *map, struct flchip *chip); 45 + 46 + struct mtd_info *lpddr_cmdset(struct map_info *map) 47 + { 48 + struct lpddr_private *lpddr = map->fldrv_priv; 49 + struct flchip_shared *shared; 50 + struct flchip *chip; 51 + struct mtd_info *mtd; 52 + int numchips; 53 + int i, j; 54 + 55 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 56 + if (!mtd) { 57 + printk(KERN_ERR "Failed to allocate memory for MTD device\n"); 58 + return NULL; 59 + } 60 + mtd->priv = map; 61 + mtd->type = MTD_NORFLASH; 62 + 63 + /* Fill in the default mtd operations */ 64 + mtd->read = lpddr_read; 65 + mtd->type = MTD_NORFLASH; 66 + mtd->flags = MTD_CAP_NORFLASH; 67 + mtd->flags &= ~MTD_BIT_WRITEABLE; 68 + mtd->erase = lpddr_erase; 69 + mtd->write = lpddr_write_buffers; 70 + mtd->writev = lpddr_writev; 71 + mtd->read_oob = NULL; 72 + mtd->write_oob = NULL; 73 + mtd->sync = NULL; 74 + mtd->lock = lpddr_lock; 75 + mtd->unlock = lpddr_unlock; 76 + mtd->suspend = NULL; 77 + mtd->resume = NULL; 78 + if (map_is_linear(map)) { 79 + mtd->point = lpddr_point; 80 + mtd->unpoint = lpddr_unpoint; 81 + } 82 + mtd->block_isbad = NULL; 83 + mtd->block_markbad = NULL; 84 + mtd->size = 1 << lpddr->qinfo->DevSizeShift; 85 + mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift; 86 + mtd->writesize = 1 << lpddr->qinfo->BufSizeShift; 87 + 88 + shared = kmalloc(sizeof(struct flchip_shared) * lpddr->numchips, 89 + GFP_KERNEL); 90 + if (!shared) { 91 + kfree(lpddr); 92 + kfree(mtd); 93 + return NULL; 94 + } 95 + 96 + chip = &lpddr->chips[0]; 97 + numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; 98 + for (i = 0; i < numchips; i++) { 99 + shared[i].writing = shared[i].erasing = NULL; 100 + spin_lock_init(&shared[i].lock); 101 + for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { 102 + *chip = lpddr->chips[i]; 103 + chip->start += j << lpddr->chipshift; 104 + chip->oldstate = chip->state = FL_READY; 105 + chip->priv = &shared[i]; 106 + /* those should be reset too since 107 + they create memory references. */ 108 + init_waitqueue_head(&chip->wq); 109 + spin_lock_init(&chip->_spinlock); 110 + chip->mutex = &chip->_spinlock; 111 + chip++; 112 + } 113 + } 114 + 115 + return mtd; 116 + } 117 + EXPORT_SYMBOL(lpddr_cmdset); 118 + 119 + static int wait_for_ready(struct map_info *map, struct flchip *chip, 120 + unsigned int chip_op_time) 121 + { 122 + unsigned int timeo, reset_timeo, sleep_time; 123 + unsigned int dsr; 124 + flstate_t chip_state = chip->state; 125 + int ret = 0; 126 + 127 + /* set our timeout to 8 times the expected delay */ 128 + timeo = chip_op_time * 8; 129 + if (!timeo) 130 + timeo = 500000; 131 + reset_timeo = timeo; 132 + sleep_time = chip_op_time / 2; 133 + 134 + for (;;) { 135 + dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR)); 136 + if (dsr & DSR_READY_STATUS) 137 + break; 138 + if (!timeo) { 139 + printk(KERN_ERR "%s: Flash timeout error state %d \n", 140 + map->name, chip_state); 141 + ret = -ETIME; 142 + break; 143 + } 144 + 145 + /* OK Still waiting. Drop the lock, wait a while and retry. */ 146 + spin_unlock(chip->mutex); 147 + if (sleep_time >= 1000000/HZ) { 148 + /* 149 + * Half of the normal delay still remaining 150 + * can be performed with a sleeping delay instead 151 + * of busy waiting. 152 + */ 153 + msleep(sleep_time/1000); 154 + timeo -= sleep_time; 155 + sleep_time = 1000000/HZ; 156 + } else { 157 + udelay(1); 158 + cond_resched(); 159 + timeo--; 160 + } 161 + spin_lock(chip->mutex); 162 + 163 + while (chip->state != chip_state) { 164 + /* Someone's suspended the operation: sleep */ 165 + DECLARE_WAITQUEUE(wait, current); 166 + set_current_state(TASK_UNINTERRUPTIBLE); 167 + add_wait_queue(&chip->wq, &wait); 168 + spin_unlock(chip->mutex); 169 + schedule(); 170 + remove_wait_queue(&chip->wq, &wait); 171 + spin_lock(chip->mutex); 172 + } 173 + if (chip->erase_suspended || chip->write_suspended) { 174 + /* Suspend has occured while sleep: reset timeout */ 175 + timeo = reset_timeo; 176 + chip->erase_suspended = chip->write_suspended = 0; 177 + } 178 + } 179 + /* check status for errors */ 180 + if (dsr & DSR_ERR) { 181 + /* Clear DSR*/ 182 + map_write(map, CMD(~(DSR_ERR)), map->pfow_base + PFOW_DSR); 183 + printk(KERN_WARNING"%s: Bad status on wait: 0x%x \n", 184 + map->name, dsr); 185 + print_drs_error(dsr); 186 + ret = -EIO; 187 + } 188 + chip->state = FL_READY; 189 + return ret; 190 + } 191 + 192 + static int get_chip(struct map_info *map, struct flchip *chip, int mode) 193 + { 194 + int ret; 195 + DECLARE_WAITQUEUE(wait, current); 196 + 197 + retry: 198 + if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING) 199 + && chip->state != FL_SYNCING) { 200 + /* 201 + * OK. We have possibility for contension on the write/erase 202 + * operations which are global to the real chip and not per 203 + * partition. So let's fight it over in the partition which 204 + * currently has authority on the operation. 205 + * 206 + * The rules are as follows: 207 + * 208 + * - any write operation must own shared->writing. 209 + * 210 + * - any erase operation must own _both_ shared->writing and 211 + * shared->erasing. 212 + * 213 + * - contension arbitration is handled in the owner's context. 214 + * 215 + * The 'shared' struct can be read and/or written only when 216 + * its lock is taken. 217 + */ 218 + struct flchip_shared *shared = chip->priv; 219 + struct flchip *contender; 220 + spin_lock(&shared->lock); 221 + contender = shared->writing; 222 + if (contender && contender != chip) { 223 + /* 224 + * The engine to perform desired operation on this 225 + * partition is already in use by someone else. 226 + * Let's fight over it in the context of the chip 227 + * currently using it. If it is possible to suspend, 228 + * that other partition will do just that, otherwise 229 + * it'll happily send us to sleep. In any case, when 230 + * get_chip returns success we're clear to go ahead. 231 + */ 232 + ret = spin_trylock(contender->mutex); 233 + spin_unlock(&shared->lock); 234 + if (!ret) 235 + goto retry; 236 + spin_unlock(chip->mutex); 237 + ret = chip_ready(map, contender, mode); 238 + spin_lock(chip->mutex); 239 + 240 + if (ret == -EAGAIN) { 241 + spin_unlock(contender->mutex); 242 + goto retry; 243 + } 244 + if (ret) { 245 + spin_unlock(contender->mutex); 246 + return ret; 247 + } 248 + spin_lock(&shared->lock); 249 + 250 + /* We should not own chip if it is already in FL_SYNCING 251 + * state. Put contender and retry. */ 252 + if (chip->state == FL_SYNCING) { 253 + put_chip(map, contender); 254 + spin_unlock(contender->mutex); 255 + goto retry; 256 + } 257 + spin_unlock(contender->mutex); 258 + } 259 + 260 + /* Check if we have suspended erase on this chip. 261 + Must sleep in such a case. */ 262 + if (mode == FL_ERASING && shared->erasing 263 + && shared->erasing->oldstate == FL_ERASING) { 264 + spin_unlock(&shared->lock); 265 + set_current_state(TASK_UNINTERRUPTIBLE); 266 + add_wait_queue(&chip->wq, &wait); 267 + spin_unlock(chip->mutex); 268 + schedule(); 269 + remove_wait_queue(&chip->wq, &wait); 270 + spin_lock(chip->mutex); 271 + goto retry; 272 + } 273 + 274 + /* We now own it */ 275 + shared->writing = chip; 276 + if (mode == FL_ERASING) 277 + shared->erasing = chip; 278 + spin_unlock(&shared->lock); 279 + } 280 + 281 + ret = chip_ready(map, chip, mode); 282 + if (ret == -EAGAIN) 283 + goto retry; 284 + 285 + return ret; 286 + } 287 + 288 + static int chip_ready(struct map_info *map, struct flchip *chip, int mode) 289 + { 290 + struct lpddr_private *lpddr = map->fldrv_priv; 291 + int ret = 0; 292 + DECLARE_WAITQUEUE(wait, current); 293 + 294 + /* Prevent setting state FL_SYNCING for chip in suspended state. */ 295 + if (FL_SYNCING == mode && FL_READY != chip->oldstate) 296 + goto sleep; 297 + 298 + switch (chip->state) { 299 + case FL_READY: 300 + case FL_JEDEC_QUERY: 301 + return 0; 302 + 303 + case FL_ERASING: 304 + if (!lpddr->qinfo->SuspEraseSupp || 305 + !(mode == FL_READY || mode == FL_POINT)) 306 + goto sleep; 307 + 308 + map_write(map, CMD(LPDDR_SUSPEND), 309 + map->pfow_base + PFOW_PROGRAM_ERASE_SUSPEND); 310 + chip->oldstate = FL_ERASING; 311 + chip->state = FL_ERASE_SUSPENDING; 312 + ret = wait_for_ready(map, chip, 0); 313 + if (ret) { 314 + /* Oops. something got wrong. */ 315 + /* Resume and pretend we weren't here. */ 316 + map_write(map, CMD(LPDDR_RESUME), 317 + map->pfow_base + PFOW_COMMAND_CODE); 318 + map_write(map, CMD(LPDDR_START_EXECUTION), 319 + map->pfow_base + PFOW_COMMAND_EXECUTE); 320 + chip->state = FL_ERASING; 321 + chip->oldstate = FL_READY; 322 + printk(KERN_ERR "%s: suspend operation failed." 323 + "State may be wrong \n", map->name); 324 + return -EIO; 325 + } 326 + chip->erase_suspended = 1; 327 + chip->state = FL_READY; 328 + return 0; 329 + /* Erase suspend */ 330 + case FL_POINT: 331 + /* Only if there's no operation suspended... */ 332 + if (mode == FL_READY && chip->oldstate == FL_READY) 333 + return 0; 334 + 335 + default: 336 + sleep: 337 + set_current_state(TASK_UNINTERRUPTIBLE); 338 + add_wait_queue(&chip->wq, &wait); 339 + spin_unlock(chip->mutex); 340 + schedule(); 341 + remove_wait_queue(&chip->wq, &wait); 342 + spin_lock(chip->mutex); 343 + return -EAGAIN; 344 + } 345 + } 346 + 347 + static void put_chip(struct map_info *map, struct flchip *chip) 348 + { 349 + if (chip->priv) { 350 + struct flchip_shared *shared = chip->priv; 351 + spin_lock(&shared->lock); 352 + if (shared->writing == chip && chip->oldstate == FL_READY) { 353 + /* We own the ability to write, but we're done */ 354 + shared->writing = shared->erasing; 355 + if (shared->writing && shared->writing != chip) { 356 + /* give back the ownership */ 357 + struct flchip *loaner = shared->writing; 358 + spin_lock(loaner->mutex); 359 + spin_unlock(&shared->lock); 360 + spin_unlock(chip->mutex); 361 + put_chip(map, loaner); 362 + spin_lock(chip->mutex); 363 + spin_unlock(loaner->mutex); 364 + wake_up(&chip->wq); 365 + return; 366 + } 367 + shared->erasing = NULL; 368 + shared->writing = NULL; 369 + } else if (shared->erasing == chip && shared->writing != chip) { 370 + /* 371 + * We own the ability to erase without the ability 372 + * to write, which means the erase was suspended 373 + * and some other partition is currently writing. 374 + * Don't let the switch below mess things up since 375 + * we don't have ownership to resume anything. 376 + */ 377 + spin_unlock(&shared->lock); 378 + wake_up(&chip->wq); 379 + return; 380 + } 381 + spin_unlock(&shared->lock); 382 + } 383 + 384 + switch (chip->oldstate) { 385 + case FL_ERASING: 386 + chip->state = chip->oldstate; 387 + map_write(map, CMD(LPDDR_RESUME), 388 + map->pfow_base + PFOW_COMMAND_CODE); 389 + map_write(map, CMD(LPDDR_START_EXECUTION), 390 + map->pfow_base + PFOW_COMMAND_EXECUTE); 391 + chip->oldstate = FL_READY; 392 + chip->state = FL_ERASING; 393 + break; 394 + case FL_READY: 395 + break; 396 + default: 397 + printk(KERN_ERR "%s: put_chip() called with oldstate %d!\n", 398 + map->name, chip->oldstate); 399 + } 400 + wake_up(&chip->wq); 401 + } 402 + 403 + int do_write_buffer(struct map_info *map, struct flchip *chip, 404 + unsigned long adr, const struct kvec **pvec, 405 + unsigned long *pvec_seek, int len) 406 + { 407 + struct lpddr_private *lpddr = map->fldrv_priv; 408 + map_word datum; 409 + int ret, wbufsize, word_gap, words; 410 + const struct kvec *vec; 411 + unsigned long vec_seek; 412 + unsigned long prog_buf_ofs; 413 + 414 + wbufsize = 1 << lpddr->qinfo->BufSizeShift; 415 + 416 + spin_lock(chip->mutex); 417 + ret = get_chip(map, chip, FL_WRITING); 418 + if (ret) { 419 + spin_unlock(chip->mutex); 420 + return ret; 421 + } 422 + /* Figure out the number of words to write */ 423 + word_gap = (-adr & (map_bankwidth(map)-1)); 424 + words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map); 425 + if (!word_gap) { 426 + words--; 427 + } else { 428 + word_gap = map_bankwidth(map) - word_gap; 429 + adr -= word_gap; 430 + datum = map_word_ff(map); 431 + } 432 + /* Write data */ 433 + /* Get the program buffer offset from PFOW register data first*/ 434 + prog_buf_ofs = map->pfow_base + CMDVAL(map_read(map, 435 + map->pfow_base + PFOW_PROGRAM_BUFFER_OFFSET)); 436 + vec = *pvec; 437 + vec_seek = *pvec_seek; 438 + do { 439 + int n = map_bankwidth(map) - word_gap; 440 + 441 + if (n > vec->iov_len - vec_seek) 442 + n = vec->iov_len - vec_seek; 443 + if (n > len) 444 + n = len; 445 + 446 + if (!word_gap && (len < map_bankwidth(map))) 447 + datum = map_word_ff(map); 448 + 449 + datum = map_word_load_partial(map, datum, 450 + vec->iov_base + vec_seek, word_gap, n); 451 + 452 + len -= n; 453 + word_gap += n; 454 + if (!len || word_gap == map_bankwidth(map)) { 455 + map_write(map, datum, prog_buf_ofs); 456 + prog_buf_ofs += map_bankwidth(map); 457 + word_gap = 0; 458 + } 459 + 460 + vec_seek += n; 461 + if (vec_seek == vec->iov_len) { 462 + vec++; 463 + vec_seek = 0; 464 + } 465 + } while (len); 466 + *pvec = vec; 467 + *pvec_seek = vec_seek; 468 + 469 + /* GO GO GO */ 470 + send_pfow_command(map, LPDDR_BUFF_PROGRAM, adr, wbufsize, NULL); 471 + chip->state = FL_WRITING; 472 + ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->ProgBufferTime)); 473 + if (ret) { 474 + printk(KERN_WARNING"%s Buffer program error: %d at %lx; \n", 475 + map->name, ret, adr); 476 + goto out; 477 + } 478 + 479 + out: put_chip(map, chip); 480 + spin_unlock(chip->mutex); 481 + return ret; 482 + } 483 + 484 + int do_erase_oneblock(struct mtd_info *mtd, loff_t adr) 485 + { 486 + struct map_info *map = mtd->priv; 487 + struct lpddr_private *lpddr = map->fldrv_priv; 488 + int chipnum = adr >> lpddr->chipshift; 489 + struct flchip *chip = &lpddr->chips[chipnum]; 490 + int ret; 491 + 492 + spin_lock(chip->mutex); 493 + ret = get_chip(map, chip, FL_ERASING); 494 + if (ret) { 495 + spin_unlock(chip->mutex); 496 + return ret; 497 + } 498 + send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL); 499 + chip->state = FL_ERASING; 500 + ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->BlockEraseTime)*1000); 501 + if (ret) { 502 + printk(KERN_WARNING"%s Erase block error %d at : %llx\n", 503 + map->name, ret, adr); 504 + goto out; 505 + } 506 + out: put_chip(map, chip); 507 + spin_unlock(chip->mutex); 508 + return ret; 509 + } 510 + 511 + static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len, 512 + size_t *retlen, u_char *buf) 513 + { 514 + struct map_info *map = mtd->priv; 515 + struct lpddr_private *lpddr = map->fldrv_priv; 516 + int chipnum = adr >> lpddr->chipshift; 517 + struct flchip *chip = &lpddr->chips[chipnum]; 518 + int ret = 0; 519 + 520 + spin_lock(chip->mutex); 521 + ret = get_chip(map, chip, FL_READY); 522 + if (ret) { 523 + spin_unlock(chip->mutex); 524 + return ret; 525 + } 526 + 527 + map_copy_from(map, buf, adr, len); 528 + *retlen = len; 529 + 530 + put_chip(map, chip); 531 + spin_unlock(chip->mutex); 532 + return ret; 533 + } 534 + 535 + static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len, 536 + size_t *retlen, void **mtdbuf, resource_size_t *phys) 537 + { 538 + struct map_info *map = mtd->priv; 539 + struct lpddr_private *lpddr = map->fldrv_priv; 540 + int chipnum = adr >> lpddr->chipshift; 541 + unsigned long ofs, last_end = 0; 542 + struct flchip *chip = &lpddr->chips[chipnum]; 543 + int ret = 0; 544 + 545 + if (!map->virt || (adr + len > mtd->size)) 546 + return -EINVAL; 547 + 548 + /* ofs: offset within the first chip that the first read should start */ 549 + ofs = adr - (chipnum << lpddr->chipshift); 550 + 551 + *mtdbuf = (void *)map->virt + chip->start + ofs; 552 + *retlen = 0; 553 + 554 + while (len) { 555 + unsigned long thislen; 556 + 557 + if (chipnum >= lpddr->numchips) 558 + break; 559 + 560 + /* We cannot point across chips that are virtually disjoint */ 561 + if (!last_end) 562 + last_end = chip->start; 563 + else if (chip->start != last_end) 564 + break; 565 + 566 + if ((len + ofs - 1) >> lpddr->chipshift) 567 + thislen = (1<<lpddr->chipshift) - ofs; 568 + else 569 + thislen = len; 570 + /* get the chip */ 571 + spin_lock(chip->mutex); 572 + ret = get_chip(map, chip, FL_POINT); 573 + spin_unlock(chip->mutex); 574 + if (ret) 575 + break; 576 + 577 + chip->state = FL_POINT; 578 + chip->ref_point_counter++; 579 + *retlen += thislen; 580 + len -= thislen; 581 + 582 + ofs = 0; 583 + last_end += 1 << lpddr->chipshift; 584 + chipnum++; 585 + chip = &lpddr->chips[chipnum]; 586 + } 587 + return 0; 588 + } 589 + 590 + static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len) 591 + { 592 + struct map_info *map = mtd->priv; 593 + struct lpddr_private *lpddr = map->fldrv_priv; 594 + int chipnum = adr >> lpddr->chipshift; 595 + unsigned long ofs; 596 + 597 + /* ofs: offset within the first chip that the first read should start */ 598 + ofs = adr - (chipnum << lpddr->chipshift); 599 + 600 + while (len) { 601 + unsigned long thislen; 602 + struct flchip *chip; 603 + 604 + chip = &lpddr->chips[chipnum]; 605 + if (chipnum >= lpddr->numchips) 606 + break; 607 + 608 + if ((len + ofs - 1) >> lpddr->chipshift) 609 + thislen = (1<<lpddr->chipshift) - ofs; 610 + else 611 + thislen = len; 612 + 613 + spin_lock(chip->mutex); 614 + if (chip->state == FL_POINT) { 615 + chip->ref_point_counter--; 616 + if (chip->ref_point_counter == 0) 617 + chip->state = FL_READY; 618 + } else 619 + printk(KERN_WARNING "%s: Warning: unpoint called on non" 620 + "pointed region\n", map->name); 621 + 622 + put_chip(map, chip); 623 + spin_unlock(chip->mutex); 624 + 625 + len -= thislen; 626 + ofs = 0; 627 + chipnum++; 628 + } 629 + } 630 + 631 + static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, 632 + size_t *retlen, const u_char *buf) 633 + { 634 + struct kvec vec; 635 + 636 + vec.iov_base = (void *) buf; 637 + vec.iov_len = len; 638 + 639 + return lpddr_writev(mtd, &vec, 1, to, retlen); 640 + } 641 + 642 + 643 + static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs, 644 + unsigned long count, loff_t to, size_t *retlen) 645 + { 646 + struct map_info *map = mtd->priv; 647 + struct lpddr_private *lpddr = map->fldrv_priv; 648 + int ret = 0; 649 + int chipnum; 650 + unsigned long ofs, vec_seek, i; 651 + int wbufsize = 1 << lpddr->qinfo->BufSizeShift; 652 + 653 + size_t len = 0; 654 + 655 + for (i = 0; i < count; i++) 656 + len += vecs[i].iov_len; 657 + 658 + *retlen = 0; 659 + if (!len) 660 + return 0; 661 + 662 + chipnum = to >> lpddr->chipshift; 663 + 664 + ofs = to; 665 + vec_seek = 0; 666 + 667 + do { 668 + /* We must not cross write block boundaries */ 669 + int size = wbufsize - (ofs & (wbufsize-1)); 670 + 671 + if (size > len) 672 + size = len; 673 + 674 + ret = do_write_buffer(map, &lpddr->chips[chipnum], 675 + ofs, &vecs, &vec_seek, size); 676 + if (ret) 677 + return ret; 678 + 679 + ofs += size; 680 + (*retlen) += size; 681 + len -= size; 682 + 683 + /* Be nice and reschedule with the chip in a usable 684 + * state for other processes */ 685 + cond_resched(); 686 + 687 + } while (len); 688 + 689 + return 0; 690 + } 691 + 692 + static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr) 693 + { 694 + unsigned long ofs, len; 695 + int ret; 696 + struct map_info *map = mtd->priv; 697 + struct lpddr_private *lpddr = map->fldrv_priv; 698 + int size = 1 << lpddr->qinfo->UniformBlockSizeShift; 699 + 700 + ofs = instr->addr; 701 + len = instr->len; 702 + 703 + if (ofs > mtd->size || (len + ofs) > mtd->size) 704 + return -EINVAL; 705 + 706 + while (len > 0) { 707 + ret = do_erase_oneblock(mtd, ofs); 708 + if (ret) 709 + return ret; 710 + ofs += size; 711 + len -= size; 712 + } 713 + instr->state = MTD_ERASE_DONE; 714 + mtd_erase_callback(instr); 715 + 716 + return 0; 717 + } 718 + 719 + #define DO_XXLOCK_LOCK 1 720 + #define DO_XXLOCK_UNLOCK 2 721 + int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk) 722 + { 723 + int ret = 0; 724 + struct map_info *map = mtd->priv; 725 + struct lpddr_private *lpddr = map->fldrv_priv; 726 + int chipnum = adr >> lpddr->chipshift; 727 + struct flchip *chip = &lpddr->chips[chipnum]; 728 + 729 + spin_lock(chip->mutex); 730 + ret = get_chip(map, chip, FL_LOCKING); 731 + if (ret) { 732 + spin_unlock(chip->mutex); 733 + return ret; 734 + } 735 + 736 + if (thunk == DO_XXLOCK_LOCK) { 737 + send_pfow_command(map, LPDDR_LOCK_BLOCK, adr, adr + len, NULL); 738 + chip->state = FL_LOCKING; 739 + } else if (thunk == DO_XXLOCK_UNLOCK) { 740 + send_pfow_command(map, LPDDR_UNLOCK_BLOCK, adr, adr + len, NULL); 741 + chip->state = FL_UNLOCKING; 742 + } else 743 + BUG(); 744 + 745 + ret = wait_for_ready(map, chip, 1); 746 + if (ret) { 747 + printk(KERN_ERR "%s: block unlock error status %d \n", 748 + map->name, ret); 749 + goto out; 750 + } 751 + out: put_chip(map, chip); 752 + spin_unlock(chip->mutex); 753 + return ret; 754 + } 755 + 756 + static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 757 + { 758 + return do_xxlock(mtd, ofs, len, DO_XXLOCK_LOCK); 759 + } 760 + 761 + static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 762 + { 763 + return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK); 764 + } 765 + 766 + int word_program(struct map_info *map, loff_t adr, uint32_t curval) 767 + { 768 + int ret; 769 + struct lpddr_private *lpddr = map->fldrv_priv; 770 + int chipnum = adr >> lpddr->chipshift; 771 + struct flchip *chip = &lpddr->chips[chipnum]; 772 + 773 + spin_lock(chip->mutex); 774 + ret = get_chip(map, chip, FL_WRITING); 775 + if (ret) { 776 + spin_unlock(chip->mutex); 777 + return ret; 778 + } 779 + 780 + send_pfow_command(map, LPDDR_WORD_PROGRAM, adr, 0x00, (map_word *)&curval); 781 + 782 + ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->SingleWordProgTime)); 783 + if (ret) { 784 + printk(KERN_WARNING"%s word_program error at: %llx; val: %x\n", 785 + map->name, adr, curval); 786 + goto out; 787 + } 788 + 789 + out: put_chip(map, chip); 790 + spin_unlock(chip->mutex); 791 + return ret; 792 + } 793 + 794 + MODULE_LICENSE("GPL"); 795 + MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>"); 796 + MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");
+255
drivers/mtd/lpddr/qinfo_probe.c
··· 1 + /* 2 + * Probing flash chips with QINFO records. 3 + * (C) 2008 Korolev Alexey <akorolev@infradead.org> 4 + * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 + * 02110-1301, USA. 20 + */ 21 + #include <linux/module.h> 22 + #include <linux/types.h> 23 + #include <linux/kernel.h> 24 + #include <linux/init.h> 25 + #include <linux/errno.h> 26 + #include <linux/slab.h> 27 + #include <linux/interrupt.h> 28 + 29 + #include <linux/mtd/xip.h> 30 + #include <linux/mtd/map.h> 31 + #include <linux/mtd/pfow.h> 32 + #include <linux/mtd/qinfo.h> 33 + 34 + static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr); 35 + struct mtd_info *lpddr_probe(struct map_info *map); 36 + static struct lpddr_private *lpddr_probe_chip(struct map_info *map); 37 + static int lpddr_pfow_present(struct map_info *map, 38 + struct lpddr_private *lpddr); 39 + 40 + static struct qinfo_query_info qinfo_array[] = { 41 + /* General device info */ 42 + {0, 0, "DevSizeShift", "Device size 2^n bytes"}, 43 + {0, 3, "BufSizeShift", "Program buffer size 2^n bytes"}, 44 + /* Erase block information */ 45 + {1, 1, "TotalBlocksNum", "Total number of blocks"}, 46 + {1, 2, "UniformBlockSizeShift", "Uniform block size 2^n bytes"}, 47 + /* Partition information */ 48 + {2, 1, "HWPartsNum", "Number of hardware partitions"}, 49 + /* Optional features */ 50 + {5, 1, "SuspEraseSupp", "Suspend erase supported"}, 51 + /* Operation typical time */ 52 + {10, 0, "SingleWordProgTime", "Single word program 2^n u-sec"}, 53 + {10, 1, "ProgBufferTime", "Program buffer write 2^n u-sec"}, 54 + {10, 2, "BlockEraseTime", "Block erase 2^n m-sec"}, 55 + {10, 3, "FullChipEraseTime", "Full chip erase 2^n m-sec"}, 56 + }; 57 + 58 + static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str) 59 + { 60 + int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info); 61 + int i; 62 + int bankwidth = map_bankwidth(map) * 8; 63 + int major, minor; 64 + 65 + for (i = 0; i < qinfo_lines; i++) { 66 + if (strcmp(id_str, qinfo_array[i].id_str) == 0) { 67 + major = qinfo_array[i].major & ((1 << bankwidth) - 1); 68 + minor = qinfo_array[i].minor & ((1 << bankwidth) - 1); 69 + return minor | (major << bankwidth); 70 + } 71 + } 72 + printk(KERN_ERR"%s qinfo id string is wrong! \n", map->name); 73 + BUG(); 74 + return -1; 75 + } 76 + 77 + static uint16_t lpddr_info_query(struct map_info *map, char *id_str) 78 + { 79 + unsigned int dsr, val; 80 + int bits_per_chip = map_bankwidth(map) * 8; 81 + unsigned long adr = lpddr_get_qinforec_pos(map, id_str); 82 + int attempts = 20; 83 + 84 + /* Write a request for the PFOW record */ 85 + map_write(map, CMD(LPDDR_INFO_QUERY), 86 + map->pfow_base + PFOW_COMMAND_CODE); 87 + map_write(map, CMD(adr & ((1 << bits_per_chip) - 1)), 88 + map->pfow_base + PFOW_COMMAND_ADDRESS_L); 89 + map_write(map, CMD(adr >> bits_per_chip), 90 + map->pfow_base + PFOW_COMMAND_ADDRESS_H); 91 + map_write(map, CMD(LPDDR_START_EXECUTION), 92 + map->pfow_base + PFOW_COMMAND_EXECUTE); 93 + 94 + while ((attempts--) > 0) { 95 + dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR)); 96 + if (dsr & DSR_READY_STATUS) 97 + break; 98 + udelay(10); 99 + } 100 + 101 + val = CMDVAL(map_read(map, map->pfow_base + PFOW_COMMAND_DATA)); 102 + return val; 103 + } 104 + 105 + static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr) 106 + { 107 + map_word pfow_val[4]; 108 + 109 + /* Check identification string */ 110 + pfow_val[0] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_P); 111 + pfow_val[1] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_F); 112 + pfow_val[2] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_O); 113 + pfow_val[3] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_W); 114 + 115 + if (!map_word_equal(map, CMD('P'), pfow_val[0])) 116 + goto out; 117 + 118 + if (!map_word_equal(map, CMD('F'), pfow_val[1])) 119 + goto out; 120 + 121 + if (!map_word_equal(map, CMD('O'), pfow_val[2])) 122 + goto out; 123 + 124 + if (!map_word_equal(map, CMD('W'), pfow_val[3])) 125 + goto out; 126 + 127 + return 1; /* "PFOW" is found */ 128 + out: 129 + printk(KERN_WARNING"%s: PFOW string at 0x%lx is not found \n", 130 + map->name, map->pfow_base); 131 + return 0; 132 + } 133 + 134 + static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr) 135 + { 136 + 137 + lpddr->qinfo = kmalloc(sizeof(struct qinfo_chip), GFP_KERNEL); 138 + if (!lpddr->qinfo) { 139 + printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n", 140 + map->name); 141 + return 0; 142 + } 143 + memset(lpddr->qinfo, 0, sizeof(struct qinfo_chip)); 144 + 145 + /* Get the ManuID */ 146 + lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID)); 147 + /* Get the DeviceID */ 148 + lpddr->DevId = CMDVAL(map_read(map, map->pfow_base + PFOW_DEVICE_ID)); 149 + /* read parameters from chip qinfo table */ 150 + lpddr->qinfo->DevSizeShift = lpddr_info_query(map, "DevSizeShift"); 151 + lpddr->qinfo->TotalBlocksNum = lpddr_info_query(map, "TotalBlocksNum"); 152 + lpddr->qinfo->BufSizeShift = lpddr_info_query(map, "BufSizeShift"); 153 + lpddr->qinfo->HWPartsNum = lpddr_info_query(map, "HWPartsNum"); 154 + lpddr->qinfo->UniformBlockSizeShift = 155 + lpddr_info_query(map, "UniformBlockSizeShift"); 156 + lpddr->qinfo->SuspEraseSupp = lpddr_info_query(map, "SuspEraseSupp"); 157 + lpddr->qinfo->SingleWordProgTime = 158 + lpddr_info_query(map, "SingleWordProgTime"); 159 + lpddr->qinfo->ProgBufferTime = lpddr_info_query(map, "ProgBufferTime"); 160 + lpddr->qinfo->BlockEraseTime = lpddr_info_query(map, "BlockEraseTime"); 161 + return 1; 162 + } 163 + static struct lpddr_private *lpddr_probe_chip(struct map_info *map) 164 + { 165 + struct lpddr_private lpddr; 166 + struct lpddr_private *retlpddr; 167 + int numvirtchips; 168 + 169 + 170 + if ((map->pfow_base + 0x1000) >= map->size) { 171 + printk(KERN_NOTICE"%s Probe at base (0x%08lx) past the end of" 172 + "the map(0x%08lx)\n", map->name, 173 + (unsigned long)map->pfow_base, map->size - 1); 174 + return NULL; 175 + } 176 + memset(&lpddr, 0, sizeof(struct lpddr_private)); 177 + if (!lpddr_pfow_present(map, &lpddr)) 178 + return NULL; 179 + 180 + if (!lpddr_chip_setup(map, &lpddr)) 181 + return NULL; 182 + 183 + /* Ok so we found a chip */ 184 + lpddr.chipshift = lpddr.qinfo->DevSizeShift; 185 + lpddr.numchips = 1; 186 + 187 + numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum; 188 + retlpddr = kmalloc(sizeof(struct lpddr_private) + 189 + numvirtchips * sizeof(struct flchip), GFP_KERNEL); 190 + if (!retlpddr) 191 + return NULL; 192 + 193 + memset(retlpddr, 0, sizeof(struct lpddr_private) + 194 + numvirtchips * sizeof(struct flchip)); 195 + memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private)); 196 + 197 + retlpddr->numchips = numvirtchips; 198 + retlpddr->chipshift = retlpddr->qinfo->DevSizeShift - 199 + __ffs(retlpddr->qinfo->HWPartsNum); 200 + 201 + return retlpddr; 202 + } 203 + 204 + struct mtd_info *lpddr_probe(struct map_info *map) 205 + { 206 + struct mtd_info *mtd = NULL; 207 + struct lpddr_private *lpddr; 208 + 209 + /* First probe the map to see if we havecan open PFOW here */ 210 + lpddr = lpddr_probe_chip(map); 211 + if (!lpddr) 212 + return NULL; 213 + 214 + map->fldrv_priv = lpddr; 215 + mtd = lpddr_cmdset(map); 216 + if (mtd) { 217 + if (mtd->size > map->size) { 218 + printk(KERN_WARNING "Reducing visibility of %ldKiB chip" 219 + "to %ldKiB\n", (unsigned long)mtd->size >> 10, 220 + (unsigned long)map->size >> 10); 221 + mtd->size = map->size; 222 + } 223 + return mtd; 224 + } 225 + 226 + kfree(lpddr->qinfo); 227 + kfree(lpddr); 228 + map->fldrv_priv = NULL; 229 + return NULL; 230 + } 231 + 232 + static struct mtd_chip_driver lpddr_chipdrv = { 233 + .probe = lpddr_probe, 234 + .name = "qinfo_probe", 235 + .module = THIS_MODULE 236 + }; 237 + 238 + static int __init lpddr_probe_init(void) 239 + { 240 + register_mtd_chip_driver(&lpddr_chipdrv); 241 + return 0; 242 + } 243 + 244 + static void __exit lpddr_probe_exit(void) 245 + { 246 + unregister_mtd_chip_driver(&lpddr_chipdrv); 247 + } 248 + 249 + module_init(lpddr_probe_init); 250 + module_exit(lpddr_probe_exit); 251 + 252 + MODULE_LICENSE("GPL"); 253 + MODULE_AUTHOR("Vasiliy Leonenko <vasiliy.leonenko@gmail.com>"); 254 + MODULE_DESCRIPTION("Driver to probe qinfo flash chips"); 255 +
+16 -5
drivers/mtd/maps/Kconfig
··· 10 10 paged mappings of flash chips. 11 11 12 12 config MTD_PHYSMAP 13 - tristate "CFI Flash device in physical memory map" 14 - depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM 13 + tristate "Flash device in physical memory map" 14 + depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_LPDDR 15 15 help 16 16 This provides a 'mapping' driver which allows the NOR Flash and 17 17 ROM driver code to communicate with chips which are mapped ··· 23 23 To compile this driver as a module, choose M here: the 24 24 module will be called physmap. 25 25 26 + config MTD_PHYSMAP_COMPAT 27 + bool "Physmap compat support" 28 + depends on MTD_PHYSMAP 29 + default n 30 + help 31 + Setup a simple mapping via the Kconfig options. Normally the 32 + physmap configuration options are done via your board's 33 + resource file. 34 + 35 + If unsure, say N here. 36 + 26 37 config MTD_PHYSMAP_START 27 38 hex "Physical start address of flash mapping" 28 - depends on MTD_PHYSMAP 39 + depends on MTD_PHYSMAP_COMPAT 29 40 default "0x8000000" 30 41 help 31 42 This is the physical memory location at which the flash chips ··· 48 37 49 38 config MTD_PHYSMAP_LEN 50 39 hex "Physical length of flash mapping" 51 - depends on MTD_PHYSMAP 40 + depends on MTD_PHYSMAP_COMPAT 52 41 default "0" 53 42 help 54 43 This is the total length of the mapping of the flash chips on ··· 62 51 63 52 config MTD_PHYSMAP_BANKWIDTH 64 53 int "Bank width in octets" 65 - depends on MTD_PHYSMAP 54 + depends on MTD_PHYSMAP_COMPAT 66 55 default "2" 67 56 help 68 57 This is the total width of the data bus of the flash devices
+1 -1
drivers/mtd/maps/alchemy-flash.c
··· 111 111 112 112 static struct mtd_info *mymtd; 113 113 114 - int __init alchemy_mtd_init(void) 114 + static int __init alchemy_mtd_init(void) 115 115 { 116 116 struct mtd_partition *parts; 117 117 int nb_parts = 0;
+2 -2
drivers/mtd/maps/amd76xrom.c
··· 232 232 /* Trim the size if we are larger than the map */ 233 233 if (map->mtd->size > map->map.size) { 234 234 printk(KERN_WARNING MOD_NAME 235 - " rom(%u) larger than window(%lu). fixing...\n", 236 - map->mtd->size, map->map.size); 235 + " rom(%llu) larger than window(%lu). fixing...\n", 236 + (unsigned long long)map->mtd->size, map->map.size); 237 237 map->mtd->size = map->map.size; 238 238 } 239 239 if (window->rsrc.parent) {
+1 -1
drivers/mtd/maps/cfi_flagadm.c
··· 88 88 89 89 static struct mtd_info *mymtd; 90 90 91 - int __init init_flagadm(void) 91 + static int __init init_flagadm(void) 92 92 { 93 93 printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n", 94 94 FLASH_SIZE, FLASH_PHYS_ADDR);
+2 -2
drivers/mtd/maps/ck804xrom.c
··· 263 263 /* Trim the size if we are larger than the map */ 264 264 if (map->mtd->size > map->map.size) { 265 265 printk(KERN_WARNING MOD_NAME 266 - " rom(%u) larger than window(%lu). fixing...\n", 267 - map->mtd->size, map->map.size); 266 + " rom(%llu) larger than window(%lu). fixing...\n", 267 + (unsigned long long)map->mtd->size, map->map.size); 268 268 map->mtd->size = map->map.size; 269 269 } 270 270 if (window->rsrc.parent) {
+1 -1
drivers/mtd/maps/dbox2-flash.c
··· 69 69 .phys = WINDOW_ADDR, 70 70 }; 71 71 72 - int __init init_dbox2_flash(void) 72 + static int __init init_dbox2_flash(void) 73 73 { 74 74 printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); 75 75 dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
+1 -1
drivers/mtd/maps/edb7312.c
··· 71 71 static int mtd_parts_nb = 0; 72 72 static struct mtd_partition *mtd_parts = 0; 73 73 74 - int __init init_edb7312nor(void) 74 + static int __init init_edb7312nor(void) 75 75 { 76 76 static const char *rom_probe_types[] = PROBETYPES; 77 77 const char **type;
+2 -2
drivers/mtd/maps/esb2rom.c
··· 324 324 /* Trim the size if we are larger than the map */ 325 325 if (map->mtd->size > map->map.size) { 326 326 printk(KERN_WARNING MOD_NAME 327 - " rom(%u) larger than window(%lu). fixing...\n", 328 - map->mtd->size, map->map.size); 327 + " rom(%llu) larger than window(%lu). fixing...\n", 328 + (unsigned long long)map->mtd->size, map->map.size); 329 329 map->mtd->size = map->map.size; 330 330 } 331 331 if (window->rsrc.parent) {
+1 -1
drivers/mtd/maps/fortunet.c
··· 181 181 /* Backwards-spelling-compatibility */ 182 182 __setup("MTD_Partion=", MTD_New_Partition); 183 183 184 - int __init init_fortunet(void) 184 + static int __init init_fortunet(void) 185 185 { 186 186 int ix,iy; 187 187 for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
+1 -1
drivers/mtd/maps/h720x-flash.c
··· 65 65 /* 66 66 * Initialize FLASH support 67 67 */ 68 - int __init h720x_mtd_init(void) 68 + static int __init h720x_mtd_init(void) 69 69 { 70 70 71 71 char *part_type = NULL;
+2 -2
drivers/mtd/maps/ichxrom.c
··· 258 258 /* Trim the size if we are larger than the map */ 259 259 if (map->mtd->size > map->map.size) { 260 260 printk(KERN_WARNING MOD_NAME 261 - " rom(%u) larger than window(%lu). fixing...\n", 262 - map->mtd->size, map->map.size); 261 + " rom(%llu) larger than window(%lu). fixing...\n", 262 + (unsigned long long)map->mtd->size, map->map.size); 263 263 map->mtd->size = map->map.size; 264 264 } 265 265 if (window->rsrc.parent) {
+1 -1
drivers/mtd/maps/impa7.c
··· 70 70 71 71 static const char *probes[] = { "cmdlinepart", NULL }; 72 72 73 - int __init init_impa7(void) 73 + static int __init init_impa7(void) 74 74 { 75 75 static const char *rom_probe_types[] = PROBETYPES; 76 76 const char **type;
+1 -1
drivers/mtd/maps/ipaq-flash.c
··· 202 202 203 203 static int __init h1900_special_case(void); 204 204 205 - int __init ipaq_mtd_init(void) 205 + static int __init ipaq_mtd_init(void) 206 206 { 207 207 struct mtd_partition *parts = NULL; 208 208 int nb_parts = 0;
+1 -1
drivers/mtd/maps/mbx860.c
··· 55 55 .bankwidth = 4, 56 56 }; 57 57 58 - int __init init_mbx(void) 58 + static int __init init_mbx(void) 59 59 { 60 60 printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR); 61 61 mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
+4 -5
drivers/mtd/maps/nettel.c
··· 226 226 227 227 if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { 228 228 printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", 229 - amd_mtd->size>>10); 229 + (int)(amd_mtd->size>>10)); 230 230 231 231 amd_mtd->owner = THIS_MODULE; 232 232 ··· 357 357 *intel1par = 0; 358 358 } 359 359 360 - printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", 361 - (intel_mtd->size >> 10)); 360 + printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %lldKiB\n", 361 + (unsigned long long)(intel_mtd->size >> 10)); 362 362 363 363 intel_mtd->owner = THIS_MODULE; 364 364 365 - num_intel_partitions = sizeof(nettel_intel_partitions) / 366 - sizeof(nettel_intel_partitions[0]); 365 + num_intel_partitions = ARRAY_SIZE(nettel_intel_partitions); 367 366 368 367 if (intelboot) { 369 368 /*
+1 -1
drivers/mtd/maps/octagon-5066.c
··· 184 184 release_region(PAGE_IO, 1); 185 185 } 186 186 187 - int __init init_oct5066(void) 187 + static int __init init_oct5066(void) 188 188 { 189 189 int i; 190 190 int ret = 0;
+19 -22
drivers/mtd/maps/physmap.c
··· 29 29 struct map_info map[MAX_RESOURCES]; 30 30 #ifdef CONFIG_MTD_PARTITIONS 31 31 int nr_parts; 32 - struct mtd_partition *parts; 33 32 #endif 34 33 }; 35 34 ··· 55 56 for (i = 0; i < MAX_RESOURCES; i++) { 56 57 if (info->mtd[i] != NULL) { 57 58 #ifdef CONFIG_MTD_PARTITIONS 58 - if (info->nr_parts) { 59 + if (info->nr_parts || physmap_data->nr_parts) 59 60 del_mtd_partitions(info->mtd[i]); 60 - kfree(info->parts); 61 - } else if (physmap_data->nr_parts) { 62 - del_mtd_partitions(info->mtd[i]); 63 - } else { 61 + else 64 62 del_mtd_device(info->mtd[i]); 65 - } 66 63 #else 67 64 del_mtd_device(info->mtd[i]); 68 65 #endif ··· 68 73 return 0; 69 74 } 70 75 71 - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; 76 + static const char *rom_probe_types[] = { 77 + "cfi_probe", 78 + "jedec_probe", 79 + "qinfo_probe", 80 + "map_rom", 81 + NULL }; 72 82 #ifdef CONFIG_MTD_PARTITIONS 73 83 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; 74 84 #endif ··· 86 86 int err = 0; 87 87 int i; 88 88 int devices_found = 0; 89 + #ifdef CONFIG_MTD_PARTITIONS 90 + struct mtd_partition *parts; 91 + #endif 89 92 90 93 physmap_data = dev->dev.platform_data; 91 94 if (physmap_data == NULL) ··· 122 119 info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1; 123 120 info->map[i].bankwidth = physmap_data->width; 124 121 info->map[i].set_vpp = physmap_data->set_vpp; 122 + info->map[i].pfow_base = physmap_data->pfow_base; 125 123 126 124 info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys, 127 125 info->map[i].size); ··· 167 163 goto err_out; 168 164 169 165 #ifdef CONFIG_MTD_PARTITIONS 170 - err = parse_mtd_partitions(info->cmtd, part_probe_types, &info->parts, 0); 166 + err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0); 171 167 if (err > 0) { 172 - add_mtd_partitions(info->cmtd, info->parts, err); 168 + add_mtd_partitions(info->cmtd, parts, err); 169 + kfree(parts); 173 170 return 0; 174 171 } 175 172 ··· 256 251 }; 257 252 258 253 259 - #ifdef CONFIG_MTD_PHYSMAP_LEN 260 - #if CONFIG_MTD_PHYSMAP_LEN != 0 261 - #warning using PHYSMAP compat code 262 - #define PHYSMAP_COMPAT 263 - #endif 264 - #endif 265 - 266 - #ifdef PHYSMAP_COMPAT 254 + #ifdef CONFIG_MTD_PHYSMAP_COMPAT 267 255 static struct physmap_flash_data physmap_flash_data = { 268 256 .width = CONFIG_MTD_PHYSMAP_BANKWIDTH, 269 257 }; ··· 300 302 int err; 301 303 302 304 err = platform_driver_register(&physmap_flash_driver); 303 - #ifdef PHYSMAP_COMPAT 305 + #ifdef CONFIG_MTD_PHYSMAP_COMPAT 304 306 if (err == 0) 305 307 platform_device_register(&physmap_flash); 306 308 #endif ··· 310 312 311 313 static void __exit physmap_exit(void) 312 314 { 313 - #ifdef PHYSMAP_COMPAT 315 + #ifdef CONFIG_MTD_PHYSMAP_COMPAT 314 316 platform_device_unregister(&physmap_flash); 315 317 #endif 316 318 platform_driver_unregister(&physmap_flash_driver); ··· 324 326 MODULE_DESCRIPTION("Generic configurable MTD map driver"); 325 327 326 328 /* legacy platform drivers can't hotplug or coldplg */ 327 - #ifndef PHYSMAP_COMPAT 329 + #ifndef CONFIG_MTD_PHYSMAP_COMPAT 328 330 /* work with hotplug and coldplug */ 329 331 MODULE_ALIAS("platform:physmap-flash"); 330 332 #endif 331 -
+1 -1
drivers/mtd/maps/pmcmsp-flash.c
··· 48 48 49 49 #define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__) 50 50 51 - int __init init_msp_flash(void) 51 + static int __init init_msp_flash(void) 52 52 { 53 53 int i, j; 54 54 int offset, coff;
+1 -1
drivers/mtd/maps/redwood.c
··· 122 122 123 123 static struct mtd_info *redwood_mtd; 124 124 125 - int __init init_redwood_flash(void) 125 + static int __init init_redwood_flash(void) 126 126 { 127 127 int err; 128 128
+1 -1
drivers/mtd/maps/rpxlite.c
··· 23 23 .phys = WINDOW_ADDR, 24 24 }; 25 25 26 - int __init init_rpxlite(void) 26 + static int __init init_rpxlite(void) 27 27 { 28 28 printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); 29 29 rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
+1 -1
drivers/mtd/maps/sbc8240.c
··· 136 136 #endif /* CONFIG_MTD_PARTITIONS */ 137 137 138 138 139 - int __init init_sbc8240_mtd (void) 139 + static int __init init_sbc8240_mtd (void) 140 140 { 141 141 static struct _cjs { 142 142 u_long addr;
+5 -3
drivers/mtd/maps/scb2_flash.c
··· 118 118 struct mtd_erase_region_info *region = &mtd->eraseregions[i]; 119 119 120 120 if (region->numblocks * region->erasesize > mtd->size) { 121 - region->numblocks = (mtd->size / region->erasesize); 121 + region->numblocks = ((unsigned long)mtd->size / 122 + region->erasesize); 122 123 done = 1; 123 124 } else { 124 125 region->numblocks = 0; ··· 188 187 return -ENODEV; 189 188 } 190 189 191 - printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n", 192 - scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size); 190 + printk(KERN_NOTICE MODNAME ": chip size 0x%llx at offset 0x%llx\n", 191 + (unsigned long long)scb2_mtd->size, 192 + (unsigned long long)(SCB2_WINDOW - scb2_mtd->size)); 193 193 194 194 add_mtd_device(scb2_mtd); 195 195
+1 -1
drivers/mtd/maps/sharpsl-flash.c
··· 47 47 } 48 48 }; 49 49 50 - int __init init_sharpsl(void) 50 + static int __init init_sharpsl(void) 51 51 { 52 52 struct mtd_partition *parts; 53 53 int nb_parts = 0;
+1 -1
drivers/mtd/maps/tqm8xxl.c
··· 109 109 }; 110 110 #endif 111 111 112 - int __init init_tqm_mtd(void) 112 + static int __init init_tqm_mtd(void) 113 113 { 114 114 int idx = 0, ret = 0; 115 115 unsigned long flash_addr, flash_size, mtd_size = 0;
+2 -2
drivers/mtd/maps/uclinux.c
··· 51 51 52 52 /****************************************************************************/ 53 53 54 - int __init uclinux_mtd_init(void) 54 + static int __init uclinux_mtd_init(void) 55 55 { 56 56 struct mtd_info *mtd; 57 57 struct map_info *mapp; ··· 94 94 95 95 /****************************************************************************/ 96 96 97 - void __exit uclinux_mtd_cleanup(void) 97 + static void __exit uclinux_mtd_cleanup(void) 98 98 { 99 99 if (uclinux_ram_mtdinfo) { 100 100 del_mtd_partitions(uclinux_ram_mtdinfo);
+1 -1
drivers/mtd/maps/vmax301.c
··· 146 146 iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START); 147 147 } 148 148 149 - int __init init_vmax301(void) 149 + static int __init init_vmax301(void) 150 150 { 151 151 int i; 152 152 unsigned long iomapadr;
+1 -1
drivers/mtd/maps/wr_sbc82xx_flash.c
··· 74 74 } \ 75 75 } while (0); 76 76 77 - int __init init_sbc82xx_flash(void) 77 + static int __init init_sbc82xx_flash(void) 78 78 { 79 79 volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl; 80 80 int bigflash;
+5 -1
drivers/mtd/mtdchar.c
··· 450 450 if (!erase) 451 451 ret = -ENOMEM; 452 452 else { 453 + struct erase_info_user einfo; 454 + 453 455 wait_queue_head_t waitq; 454 456 DECLARE_WAITQUEUE(wait, current); 455 457 456 458 init_waitqueue_head(&waitq); 457 459 458 - if (copy_from_user(&erase->addr, argp, 460 + if (copy_from_user(&einfo, argp, 459 461 sizeof(struct erase_info_user))) { 460 462 kfree(erase); 461 463 return -EFAULT; 462 464 } 465 + erase->addr = einfo.start; 466 + erase->len = einfo.length; 463 467 erase->mtd = mtd; 464 468 erase->callback = mtdchar_erase_callback; 465 469 erase->priv = (unsigned long)&waitq;
+20 -15
drivers/mtd/mtdconcat.c
··· 197 197 continue; 198 198 } 199 199 200 - size = min(total_len, (size_t)(subdev->size - to)); 200 + size = min_t(uint64_t, total_len, subdev->size - to); 201 201 wsize = size; /* store for future use */ 202 202 203 203 entry_high = entry_low; ··· 385 385 struct mtd_concat *concat = CONCAT(mtd); 386 386 struct mtd_info *subdev; 387 387 int i, err; 388 - u_int32_t length, offset = 0; 388 + uint64_t length, offset = 0; 389 389 struct erase_info *erase; 390 390 391 391 if (!(mtd->flags & MTD_WRITEABLE)) ··· 518 518 return 0; 519 519 } 520 520 521 - static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 521 + static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 522 522 { 523 523 struct mtd_concat *concat = CONCAT(mtd); 524 524 int i, err = -EINVAL; ··· 528 528 529 529 for (i = 0; i < concat->num_subdev; i++) { 530 530 struct mtd_info *subdev = concat->subdev[i]; 531 - size_t size; 531 + uint64_t size; 532 532 533 533 if (ofs >= subdev->size) { 534 534 size = 0; ··· 556 556 return err; 557 557 } 558 558 559 - static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 559 + static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 560 560 { 561 561 struct mtd_concat *concat = CONCAT(mtd); 562 562 int i, err = 0; ··· 566 566 567 567 for (i = 0; i < concat->num_subdev; i++) { 568 568 struct mtd_info *subdev = concat->subdev[i]; 569 - size_t size; 569 + uint64_t size; 570 570 571 571 if (ofs >= subdev->size) { 572 572 size = 0; ··· 696 696 int i; 697 697 size_t size; 698 698 struct mtd_concat *concat; 699 - u_int32_t max_erasesize, curr_erasesize; 699 + uint32_t max_erasesize, curr_erasesize; 700 700 int num_erase_region; 701 701 702 702 printk(KERN_NOTICE "Concatenating MTD devices:\n"); ··· 842 842 concat->mtd.erasesize = curr_erasesize; 843 843 concat->mtd.numeraseregions = 0; 844 844 } else { 845 + uint64_t tmp64; 846 + 845 847 /* 846 848 * erase block size varies across the subdevices: allocate 847 849 * space to store the data describing the variable erase regions 848 850 */ 849 851 struct mtd_erase_region_info *erase_region_p; 850 - u_int32_t begin, position; 852 + uint64_t begin, position; 851 853 852 854 concat->mtd.erasesize = max_erasesize; 853 855 concat->mtd.numeraseregions = num_erase_region; ··· 881 879 erase_region_p->offset = begin; 882 880 erase_region_p->erasesize = 883 881 curr_erasesize; 884 - erase_region_p->numblocks = 885 - (position - begin) / curr_erasesize; 882 + tmp64 = position - begin; 883 + do_div(tmp64, curr_erasesize); 884 + erase_region_p->numblocks = tmp64; 886 885 begin = position; 887 886 888 887 curr_erasesize = subdev[i]->erasesize; ··· 900 897 erase_region_p->offset = begin; 901 898 erase_region_p->erasesize = 902 899 curr_erasesize; 903 - erase_region_p->numblocks = 904 - (position - 905 - begin) / curr_erasesize; 900 + tmp64 = position - begin; 901 + do_div(tmp64, curr_erasesize); 902 + erase_region_p->numblocks = tmp64; 906 903 begin = position; 907 904 908 905 curr_erasesize = ··· 912 909 } 913 910 position += 914 911 subdev[i]->eraseregions[j]. 915 - numblocks * curr_erasesize; 912 + numblocks * (uint64_t)curr_erasesize; 916 913 } 917 914 } 918 915 } 919 916 /* Now write the final entry */ 920 917 erase_region_p->offset = begin; 921 918 erase_region_p->erasesize = curr_erasesize; 922 - erase_region_p->numblocks = (position - begin) / curr_erasesize; 919 + tmp64 = position - begin; 920 + do_div(tmp64, curr_erasesize); 921 + erase_region_p->numblocks = tmp64; 923 922 } 924 923 925 924 return &concat->mtd;
+15 -1
drivers/mtd/mtdcore.c
··· 57 57 mtd->index = i; 58 58 mtd->usecount = 0; 59 59 60 + if (is_power_of_2(mtd->erasesize)) 61 + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; 62 + else 63 + mtd->erasesize_shift = 0; 64 + 65 + if (is_power_of_2(mtd->writesize)) 66 + mtd->writesize_shift = ffs(mtd->writesize) - 1; 67 + else 68 + mtd->writesize_shift = 0; 69 + 70 + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; 71 + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; 72 + 60 73 /* Some chips always power up locked. Unlock them now */ 61 74 if ((mtd->flags & MTD_WRITEABLE) 62 75 && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) { ··· 357 344 if (!this) 358 345 return 0; 359 346 360 - return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size, 347 + return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", i, 348 + (unsigned long long)this->size, 361 349 this->erasesize, this->name); 362 350 } 363 351
+6 -3
drivers/mtd/mtdoops.c
··· 80 80 if (ret) { 81 81 set_current_state(TASK_RUNNING); 82 82 remove_wait_queue(&wait_q, &wait); 83 - printk (KERN_WARNING "mtdoops: erase of region [0x%x, 0x%x] " 83 + printk (KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] " 84 84 "on \"%s\" failed\n", 85 - erase.addr, erase.len, mtd->name); 85 + (unsigned long long)erase.addr, (unsigned long long)erase.len, mtd->name); 86 86 return ret; 87 87 } 88 88 ··· 289 289 } 290 290 291 291 cxt->mtd = mtd; 292 - cxt->oops_pages = mtd->size / OOPS_PAGE_SIZE; 292 + if (mtd->size > INT_MAX) 293 + cxt->oops_pages = INT_MAX / OOPS_PAGE_SIZE; 294 + else 295 + cxt->oops_pages = (int)mtd->size / OOPS_PAGE_SIZE; 293 296 294 297 find_next_position(cxt); 295 298
+17 -17
drivers/mtd/mtdpart.c
··· 26 26 struct mtd_part { 27 27 struct mtd_info mtd; 28 28 struct mtd_info *master; 29 - u_int32_t offset; 29 + uint64_t offset; 30 30 int index; 31 31 struct list_head list; 32 32 int registered; ··· 235 235 } 236 236 EXPORT_SYMBOL_GPL(mtd_erase_callback); 237 237 238 - static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 238 + static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 239 239 { 240 240 struct mtd_part *part = PART(mtd); 241 241 if ((len + ofs) > mtd->size) ··· 243 243 return part->master->lock(part->master, ofs + part->offset, len); 244 244 } 245 245 246 - static int part_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 246 + static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 247 247 { 248 248 struct mtd_part *part = PART(mtd); 249 249 if ((len + ofs) > mtd->size) ··· 317 317 318 318 static struct mtd_part *add_one_partition(struct mtd_info *master, 319 319 const struct mtd_partition *part, int partno, 320 - u_int32_t cur_offset) 320 + uint64_t cur_offset) 321 321 { 322 322 struct mtd_part *slave; 323 323 ··· 395 395 slave->offset = cur_offset; 396 396 if (slave->offset == MTDPART_OFS_NXTBLK) { 397 397 slave->offset = cur_offset; 398 - if ((cur_offset % master->erasesize) != 0) { 398 + if (mtd_mod_by_eb(cur_offset, master) != 0) { 399 399 /* Round up to next erasesize */ 400 - slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize; 400 + slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize; 401 401 printk(KERN_NOTICE "Moving partition %d: " 402 - "0x%08x -> 0x%08x\n", partno, 403 - cur_offset, slave->offset); 402 + "0x%012llx -> 0x%012llx\n", partno, 403 + (unsigned long long)cur_offset, (unsigned long long)slave->offset); 404 404 } 405 405 } 406 406 if (slave->mtd.size == MTDPART_SIZ_FULL) 407 407 slave->mtd.size = master->size - slave->offset; 408 408 409 - printk(KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, 410 - slave->offset + slave->mtd.size, slave->mtd.name); 409 + printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, 410 + (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name); 411 411 412 412 /* let's do some sanity checks */ 413 413 if (slave->offset >= master->size) { ··· 420 420 } 421 421 if (slave->offset + slave->mtd.size > master->size) { 422 422 slave->mtd.size = master->size - slave->offset; 423 - printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n", 424 - part->name, master->name, slave->mtd.size); 423 + printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n", 424 + part->name, master->name, (unsigned long long)slave->mtd.size); 425 425 } 426 426 if (master->numeraseregions > 1) { 427 427 /* Deal with variable erase size stuff */ 428 428 int i, max = master->numeraseregions; 429 - u32 end = slave->offset + slave->mtd.size; 429 + u64 end = slave->offset + slave->mtd.size; 430 430 struct mtd_erase_region_info *regions = master->eraseregions; 431 431 432 432 /* Find the first erase regions which is part of this ··· 449 449 } 450 450 451 451 if ((slave->mtd.flags & MTD_WRITEABLE) && 452 - (slave->offset % slave->mtd.erasesize)) { 452 + mtd_mod_by_eb(slave->offset, &slave->mtd)) { 453 453 /* Doesn't start on a boundary of major erase size */ 454 454 /* FIXME: Let it be writable if it is on a boundary of 455 455 * _minor_ erase size though */ ··· 458 458 part->name); 459 459 } 460 460 if ((slave->mtd.flags & MTD_WRITEABLE) && 461 - (slave->mtd.size % slave->mtd.erasesize)) { 461 + mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) { 462 462 slave->mtd.flags &= ~MTD_WRITEABLE; 463 463 printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", 464 464 part->name); ··· 466 466 467 467 slave->mtd.ecclayout = master->ecclayout; 468 468 if (master->block_isbad) { 469 - uint32_t offs = 0; 469 + uint64_t offs = 0; 470 470 471 471 while (offs < slave->mtd.size) { 472 472 if (master->block_isbad(master, ··· 501 501 int nbparts) 502 502 { 503 503 struct mtd_part *slave; 504 - u_int32_t cur_offset = 0; 504 + uint64_t cur_offset = 0; 505 505 int i; 506 506 507 507 printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
+7
drivers/mtd/nand/Kconfig
··· 163 163 incorrect ECC generation, and if using these, the default of 164 164 software ECC is preferable. 165 165 166 + config MTD_NAND_NDFC 167 + tristate "NDFC NanD Flash Controller" 168 + depends on 4xx 169 + select MTD_NAND_ECC_SMC 170 + help 171 + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs 172 + 166 173 config MTD_NAND_S3C2410_CLKSTOP 167 174 bool "S3C2410 NAND IDLE clock stop" 168 175 depends on MTD_NAND_S3C2410
+3 -3
drivers/mtd/nand/alauda.c
··· 676 676 goto error; 677 677 678 678 al->write_out = usb_sndbulkpipe(al->dev, 679 - ep_wr->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); 679 + usb_endpoint_num(ep_wr)); 680 680 al->bulk_in = usb_rcvbulkpipe(al->dev, 681 - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); 681 + usb_endpoint_num(ep_in)); 682 682 al->bulk_out = usb_sndbulkpipe(al->dev, 683 - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); 683 + usb_endpoint_num(ep_out)); 684 684 685 685 /* second device is identical up to now */ 686 686 memcpy(al+1, al, sizeof(*al));
+5 -2
drivers/mtd/nand/cafe_nand.c
··· 90 90 module_param_array(timing, int, &numtimings, 0644); 91 91 92 92 #ifdef CONFIG_MTD_PARTITIONS 93 - static const char *part_probes[] = { "RedBoot", NULL }; 93 + static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; 94 94 #endif 95 95 96 96 /* Hrm. Why isn't this already conditional on something in the struct device? */ ··· 805 805 add_mtd_device(mtd); 806 806 807 807 #ifdef CONFIG_MTD_PARTITIONS 808 + #ifdef CONFIG_MTD_CMDLINE_PARTS 809 + mtd->name = "cafe_nand"; 810 + #endif 808 811 nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0); 809 812 if (nr_parts > 0) { 810 813 cafe->parts = parts; 811 - dev_info(&cafe->pdev->dev, "%d RedBoot partitions found\n", nr_parts); 814 + dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts); 812 815 add_mtd_partitions(mtd, parts, nr_parts); 813 816 } 814 817 #endif
+3 -1
drivers/mtd/nand/fsl_elbc_nand.c
··· 777 777 /* Fill in fsl_elbc_mtd structure */ 778 778 priv->mtd.priv = chip; 779 779 priv->mtd.owner = THIS_MODULE; 780 - priv->fmr = 0; /* rest filled in later */ 780 + 781 + /* Set the ECCM according to the settings in bootloader.*/ 782 + priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM; 781 783 782 784 /* fill in nand_chip structure */ 783 785 /* set up function call table */
+15 -10
drivers/mtd/nand/nand_base.c
··· 2014 2014 int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, 2015 2015 int allowbbt) 2016 2016 { 2017 - int page, len, status, pages_per_block, ret, chipnr; 2017 + int page, status, pages_per_block, ret, chipnr; 2018 2018 struct nand_chip *chip = mtd->priv; 2019 - int rewrite_bbt[NAND_MAX_CHIPS]={0}; 2019 + loff_t rewrite_bbt[NAND_MAX_CHIPS]={0}; 2020 2020 unsigned int bbt_masked_page = 0xffffffff; 2021 + loff_t len; 2021 2022 2022 - DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n", 2023 - (unsigned int)instr->addr, (unsigned int)instr->len); 2023 + DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%012llx, len = %llu\n", 2024 + (unsigned long long)instr->addr, (unsigned long long)instr->len); 2024 2025 2025 2026 /* Start address must align on block boundary */ 2026 2027 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) { ··· 2117 2116 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " 2118 2117 "Failed erase, page 0x%08x\n", page); 2119 2118 instr->state = MTD_ERASE_FAILED; 2120 - instr->fail_addr = (page << chip->page_shift); 2119 + instr->fail_addr = 2120 + ((loff_t)page << chip->page_shift); 2121 2121 goto erase_exit; 2122 2122 } 2123 2123 ··· 2128 2126 */ 2129 2127 if (bbt_masked_page != 0xffffffff && 2130 2128 (page & BBT_PAGE_MASK) == bbt_masked_page) 2131 - rewrite_bbt[chipnr] = (page << chip->page_shift); 2129 + rewrite_bbt[chipnr] = 2130 + ((loff_t)page << chip->page_shift); 2132 2131 2133 2132 /* Increment page address and decrement length */ 2134 2133 len -= (1 << chip->phys_erase_shift); ··· 2176 2173 continue; 2177 2174 /* update the BBT for chip */ 2178 2175 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt " 2179 - "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr], 2176 + "(%d:0x%0llx 0x%0x)\n", chipnr, rewrite_bbt[chipnr], 2180 2177 chip->bbt_td->pages[chipnr]); 2181 2178 nand_update_bbt(mtd, rewrite_bbt[chipnr]); 2182 2179 } ··· 2368 2365 if (!mtd->name) 2369 2366 mtd->name = type->name; 2370 2367 2371 - chip->chipsize = type->chipsize << 20; 2368 + chip->chipsize = (uint64_t)type->chipsize << 20; 2372 2369 2373 2370 /* Newer devices have all the information in additional id bytes */ 2374 2371 if (!type->pagesize) { ··· 2426 2423 2427 2424 chip->bbt_erase_shift = chip->phys_erase_shift = 2428 2425 ffs(mtd->erasesize) - 1; 2429 - chip->chip_shift = ffs(chip->chipsize) - 1; 2426 + if (chip->chipsize & 0xffffffff) 2427 + chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; 2428 + else 2429 + chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; 2430 2430 2431 2431 /* Set the bad block position */ 2432 2432 chip->badblockpos = mtd->writesize > 512 ? ··· 2523 2517 /** 2524 2518 * nand_scan_tail - [NAND Interface] Scan for the NAND device 2525 2519 * @mtd: MTD device structure 2526 - * @maxchips: Number of chips to scan for 2527 2520 * 2528 2521 * This is the second phase of the normal nand_scan() function. It 2529 2522 * fills out all the uninitialized function pointers with the defaults
+15 -16
drivers/mtd/nand/nand_bbt.c
··· 171 171 if (tmp == msk) 172 172 continue; 173 173 if (reserved_block_code && (tmp == reserved_block_code)) { 174 - printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", 175 - ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); 174 + printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n", 175 + (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); 176 176 this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); 177 177 mtd->ecc_stats.bbtblocks++; 178 178 continue; 179 179 } 180 180 /* Leave it for now, if its matured we can move this 181 181 * message to MTD_DEBUG_LEVEL0 */ 182 - printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", 183 - ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); 182 + printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n", 183 + (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); 184 184 /* Factory marked bad or worn out ? */ 185 185 if (tmp == 0) 186 186 this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); ··· 284 284 285 285 /* Read the primary version, if available */ 286 286 if (td->options & NAND_BBT_VERSION) { 287 - scan_read_raw(mtd, buf, td->pages[0] << this->page_shift, 287 + scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, 288 288 mtd->writesize); 289 289 td->version[0] = buf[mtd->writesize + td->veroffs]; 290 290 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", ··· 293 293 294 294 /* Read the mirror version, if available */ 295 295 if (md && (md->options & NAND_BBT_VERSION)) { 296 - scan_read_raw(mtd, buf, md->pages[0] << this->page_shift, 296 + scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, 297 297 mtd->writesize); 298 298 md->version[0] = buf[mtd->writesize + md->veroffs]; 299 299 printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", ··· 411 411 numblocks = this->chipsize >> (this->bbt_erase_shift - 1); 412 412 startblock = chip * numblocks; 413 413 numblocks += startblock; 414 - from = startblock << (this->bbt_erase_shift - 1); 414 + from = (loff_t)startblock << (this->bbt_erase_shift - 1); 415 415 } 416 416 417 417 for (i = startblock; i < numblocks;) { ··· 428 428 429 429 if (ret) { 430 430 this->bbt[i >> 3] |= 0x03 << (i & 0x6); 431 - printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 432 - i >> 1, (unsigned int)from); 431 + printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n", 432 + i >> 1, (unsigned long long)from); 433 433 mtd->ecc_stats.badblocks++; 434 434 } 435 435 ··· 495 495 for (block = 0; block < td->maxblocks; block++) { 496 496 497 497 int actblock = startblock + dir * block; 498 - loff_t offs = actblock << this->bbt_erase_shift; 498 + loff_t offs = (loff_t)actblock << this->bbt_erase_shift; 499 499 500 500 /* Read first page */ 501 501 scan_read_raw(mtd, buf, offs, mtd->writesize); ··· 719 719 720 720 memset(&einfo, 0, sizeof(einfo)); 721 721 einfo.mtd = mtd; 722 - einfo.addr = (unsigned long)to; 722 + einfo.addr = to; 723 723 einfo.len = 1 << this->bbt_erase_shift; 724 724 res = nand_erase_nand(mtd, &einfo, 1); 725 725 if (res < 0) ··· 729 729 if (res < 0) 730 730 goto outerr; 731 731 732 - printk(KERN_DEBUG "Bad block table written to 0x%08x, version " 733 - "0x%02X\n", (unsigned int)to, td->version[chip]); 732 + printk(KERN_DEBUG "Bad block table written to 0x%012llx, version " 733 + "0x%02X\n", (unsigned long long)to, td->version[chip]); 734 734 735 735 /* Mark it as used */ 736 736 td->pages[chip] = page; ··· 910 910 newval = oldval | (0x2 << (block & 0x06)); 911 911 this->bbt[(block >> 3)] = newval; 912 912 if ((oldval != newval) && td->reserved_block_code) 913 - nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1)); 913 + nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1)); 914 914 continue; 915 915 } 916 916 update = 0; ··· 931 931 new ones have been marked, then we need to update the stored 932 932 bbts. This should only happen once. */ 933 933 if (update && td->reserved_block_code) 934 - nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1)); 934 + nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); 935 935 } 936 936 } 937 937 ··· 1027 1027 if (!this->bbt || !td) 1028 1028 return -EINVAL; 1029 1029 1030 - len = mtd->size >> (this->bbt_erase_shift + 2); 1031 1030 /* Allocate a temporary buffer for one eraseblock incl. oob */ 1032 1031 len = (1 << this->bbt_erase_shift); 1033 1032 len += (len >> this->page_shift) * mtd->oobsize;
+296 -43
drivers/mtd/nand/nandsim.c
··· 38 38 #include <linux/delay.h> 39 39 #include <linux/list.h> 40 40 #include <linux/random.h> 41 + #include <linux/sched.h> 42 + #include <linux/fs.h> 43 + #include <linux/pagemap.h> 41 44 42 45 /* Default simulator parameters values */ 43 46 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ ··· 103 100 static char *gravepages = NULL; 104 101 static unsigned int rptwear = 0; 105 102 static unsigned int overridesize = 0; 103 + static char *cache_file = NULL; 106 104 107 105 module_param(first_id_byte, uint, 0400); 108 106 module_param(second_id_byte, uint, 0400); ··· 126 122 module_param(gravepages, charp, 0400); 127 123 module_param(rptwear, uint, 0400); 128 124 module_param(overridesize, uint, 0400); 125 + module_param(cache_file, charp, 0400); 129 126 130 127 MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); 131 128 MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); 132 129 MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); 133 130 MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); 134 - MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)"); 131 + MODULE_PARM_DESC(access_delay, "Initial page access delay (microseconds)"); 135 132 MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds"); 136 133 MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)"); 137 134 MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)"); ··· 158 153 MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " 159 154 "The size is specified in erase blocks and as the exponent of a power of two" 160 155 " e.g. 5 means a size of 32 erase blocks"); 156 + MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); 161 157 162 158 /* The largest possible page size */ 163 159 #define NS_LARGEST_PAGE_SIZE 2048 ··· 272 266 */ 273 267 #define NS_MAX_PREVSTATES 1 274 268 269 + /* Maximum page cache pages needed to read or write a NAND page to the cache_file */ 270 + #define NS_MAX_HELD_PAGES 16 271 + 275 272 /* 276 273 * A union to represent flash memory contents and flash buffer. 277 274 */ ··· 303 294 304 295 /* The simulated NAND flash pages array */ 305 296 union ns_mem *pages; 297 + 298 + /* Slab allocator for nand pages */ 299 + struct kmem_cache *nand_pages_slab; 306 300 307 301 /* Internal buffer of page + OOB size bytes */ 308 302 union ns_mem buf; ··· 347 335 int ale; /* address Latch Enable */ 348 336 int wp; /* write Protect */ 349 337 } lines; 338 + 339 + /* Fields needed when using a cache file */ 340 + struct file *cfile; /* Open file */ 341 + unsigned char *pages_written; /* Which pages have been written */ 342 + void *file_buf; 343 + struct page *held_pages[NS_MAX_HELD_PAGES]; 344 + int held_cnt; 350 345 }; 351 346 352 347 /* ··· 439 420 static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; 440 421 441 422 /* 442 - * Allocate array of page pointers and initialize the array to NULL 443 - * pointers. 423 + * Allocate array of page pointers, create slab allocation for an array 424 + * and initialize the array by NULL pointers. 444 425 * 445 426 * RETURNS: 0 if success, -ENOMEM if memory alloc fails. 446 427 */ 447 428 static int alloc_device(struct nandsim *ns) 448 429 { 449 - int i; 430 + struct file *cfile; 431 + int i, err; 432 + 433 + if (cache_file) { 434 + cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600); 435 + if (IS_ERR(cfile)) 436 + return PTR_ERR(cfile); 437 + if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) { 438 + NS_ERR("alloc_device: cache file not readable\n"); 439 + err = -EINVAL; 440 + goto err_close; 441 + } 442 + if (!cfile->f_op->write && !cfile->f_op->aio_write) { 443 + NS_ERR("alloc_device: cache file not writeable\n"); 444 + err = -EINVAL; 445 + goto err_close; 446 + } 447 + ns->pages_written = vmalloc(ns->geom.pgnum); 448 + if (!ns->pages_written) { 449 + NS_ERR("alloc_device: unable to allocate pages written array\n"); 450 + err = -ENOMEM; 451 + goto err_close; 452 + } 453 + ns->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL); 454 + if (!ns->file_buf) { 455 + NS_ERR("alloc_device: unable to allocate file buf\n"); 456 + err = -ENOMEM; 457 + goto err_free; 458 + } 459 + ns->cfile = cfile; 460 + memset(ns->pages_written, 0, ns->geom.pgnum); 461 + return 0; 462 + } 450 463 451 464 ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem)); 452 465 if (!ns->pages) { 453 - NS_ERR("alloc_map: unable to allocate page array\n"); 466 + NS_ERR("alloc_device: unable to allocate page array\n"); 454 467 return -ENOMEM; 455 468 } 456 469 for (i = 0; i < ns->geom.pgnum; i++) { 457 470 ns->pages[i].byte = NULL; 458 471 } 472 + ns->nand_pages_slab = kmem_cache_create("nandsim", 473 + ns->geom.pgszoob, 0, 0, NULL); 474 + if (!ns->nand_pages_slab) { 475 + NS_ERR("cache_create: unable to create kmem_cache\n"); 476 + return -ENOMEM; 477 + } 459 478 460 479 return 0; 480 + 481 + err_free: 482 + vfree(ns->pages_written); 483 + err_close: 484 + filp_close(cfile, NULL); 485 + return err; 461 486 } 462 487 463 488 /* ··· 511 448 { 512 449 int i; 513 450 451 + if (ns->cfile) { 452 + kfree(ns->file_buf); 453 + vfree(ns->pages_written); 454 + filp_close(ns->cfile, NULL); 455 + return; 456 + } 457 + 514 458 if (ns->pages) { 515 459 for (i = 0; i < ns->geom.pgnum; i++) { 516 460 if (ns->pages[i].byte) 517 - kfree(ns->pages[i].byte); 461 + kmem_cache_free(ns->nand_pages_slab, 462 + ns->pages[i].byte); 518 463 } 464 + kmem_cache_destroy(ns->nand_pages_slab); 519 465 vfree(ns->pages); 520 466 } 521 467 } ··· 536 464 return kstrdup(buf, GFP_KERNEL); 537 465 } 538 466 539 - static u_int64_t divide(u_int64_t n, u_int32_t d) 467 + static uint64_t divide(uint64_t n, uint32_t d) 540 468 { 541 469 do_div(n, d); 542 470 return n; ··· 552 480 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 553 481 struct nandsim *ns = (struct nandsim *)(chip->priv); 554 482 int i, ret = 0; 555 - u_int64_t remains; 556 - u_int64_t next_offset; 483 + uint64_t remains; 484 + uint64_t next_offset; 557 485 558 486 if (NS_IS_INITIALIZED(ns)) { 559 487 NS_ERR("init_nandsim: nandsim is already initialized\n"); ··· 620 548 remains = ns->geom.totsz; 621 549 next_offset = 0; 622 550 for (i = 0; i < parts_num; ++i) { 623 - u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz; 551 + uint64_t part_sz = (uint64_t)parts[i] * ns->geom.secsz; 624 552 625 553 if (!part_sz || part_sz > remains) { 626 554 NS_ERR("bad partition size.\n"); ··· 1283 1211 return -1; 1284 1212 } 1285 1213 1214 + static void put_pages(struct nandsim *ns) 1215 + { 1216 + int i; 1217 + 1218 + for (i = 0; i < ns->held_cnt; i++) 1219 + page_cache_release(ns->held_pages[i]); 1220 + } 1221 + 1222 + /* Get page cache pages in advance to provide NOFS memory allocation */ 1223 + static int get_pages(struct nandsim *ns, struct file *file, size_t count, loff_t pos) 1224 + { 1225 + pgoff_t index, start_index, end_index; 1226 + struct page *page; 1227 + struct address_space *mapping = file->f_mapping; 1228 + 1229 + start_index = pos >> PAGE_CACHE_SHIFT; 1230 + end_index = (pos + count - 1) >> PAGE_CACHE_SHIFT; 1231 + if (end_index - start_index + 1 > NS_MAX_HELD_PAGES) 1232 + return -EINVAL; 1233 + ns->held_cnt = 0; 1234 + for (index = start_index; index <= end_index; index++) { 1235 + page = find_get_page(mapping, index); 1236 + if (page == NULL) { 1237 + page = find_or_create_page(mapping, index, GFP_NOFS); 1238 + if (page == NULL) { 1239 + write_inode_now(mapping->host, 1); 1240 + page = find_or_create_page(mapping, index, GFP_NOFS); 1241 + } 1242 + if (page == NULL) { 1243 + put_pages(ns); 1244 + return -ENOMEM; 1245 + } 1246 + unlock_page(page); 1247 + } 1248 + ns->held_pages[ns->held_cnt++] = page; 1249 + } 1250 + return 0; 1251 + } 1252 + 1253 + static int set_memalloc(void) 1254 + { 1255 + if (current->flags & PF_MEMALLOC) 1256 + return 0; 1257 + current->flags |= PF_MEMALLOC; 1258 + return 1; 1259 + } 1260 + 1261 + static void clear_memalloc(int memalloc) 1262 + { 1263 + if (memalloc) 1264 + current->flags &= ~PF_MEMALLOC; 1265 + } 1266 + 1267 + static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos) 1268 + { 1269 + mm_segment_t old_fs; 1270 + ssize_t tx; 1271 + int err, memalloc; 1272 + 1273 + err = get_pages(ns, file, count, *pos); 1274 + if (err) 1275 + return err; 1276 + old_fs = get_fs(); 1277 + set_fs(get_ds()); 1278 + memalloc = set_memalloc(); 1279 + tx = vfs_read(file, (char __user *)buf, count, pos); 1280 + clear_memalloc(memalloc); 1281 + set_fs(old_fs); 1282 + put_pages(ns); 1283 + return tx; 1284 + } 1285 + 1286 + static ssize_t write_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos) 1287 + { 1288 + mm_segment_t old_fs; 1289 + ssize_t tx; 1290 + int err, memalloc; 1291 + 1292 + err = get_pages(ns, file, count, *pos); 1293 + if (err) 1294 + return err; 1295 + old_fs = get_fs(); 1296 + set_fs(get_ds()); 1297 + memalloc = set_memalloc(); 1298 + tx = vfs_write(file, (char __user *)buf, count, pos); 1299 + clear_memalloc(memalloc); 1300 + set_fs(old_fs); 1301 + put_pages(ns); 1302 + return tx; 1303 + } 1304 + 1286 1305 /* 1287 1306 * Returns a pointer to the current page. 1288 1307 */ ··· 1390 1227 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; 1391 1228 } 1392 1229 1230 + int do_read_error(struct nandsim *ns, int num) 1231 + { 1232 + unsigned int page_no = ns->regs.row; 1233 + 1234 + if (read_error(page_no)) { 1235 + int i; 1236 + memset(ns->buf.byte, 0xFF, num); 1237 + for (i = 0; i < num; ++i) 1238 + ns->buf.byte[i] = random32(); 1239 + NS_WARN("simulating read error in page %u\n", page_no); 1240 + return 1; 1241 + } 1242 + return 0; 1243 + } 1244 + 1245 + void do_bit_flips(struct nandsim *ns, int num) 1246 + { 1247 + if (bitflips && random32() < (1 << 22)) { 1248 + int flips = 1; 1249 + if (bitflips > 1) 1250 + flips = (random32() % (int) bitflips) + 1; 1251 + while (flips--) { 1252 + int pos = random32() % (num * 8); 1253 + ns->buf.byte[pos / 8] ^= (1 << (pos % 8)); 1254 + NS_WARN("read_page: flipping bit %d in page %d " 1255 + "reading from %d ecc: corrected=%u failed=%u\n", 1256 + pos, ns->regs.row, ns->regs.column + ns->regs.off, 1257 + nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed); 1258 + } 1259 + } 1260 + } 1261 + 1393 1262 /* 1394 1263 * Fill the NAND buffer with data read from the specified page. 1395 1264 */ ··· 1429 1234 { 1430 1235 union ns_mem *mypage; 1431 1236 1237 + if (ns->cfile) { 1238 + if (!ns->pages_written[ns->regs.row]) { 1239 + NS_DBG("read_page: page %d not written\n", ns->regs.row); 1240 + memset(ns->buf.byte, 0xFF, num); 1241 + } else { 1242 + loff_t pos; 1243 + ssize_t tx; 1244 + 1245 + NS_DBG("read_page: page %d written, reading from %d\n", 1246 + ns->regs.row, ns->regs.column + ns->regs.off); 1247 + if (do_read_error(ns, num)) 1248 + return; 1249 + pos = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off; 1250 + tx = read_file(ns, ns->cfile, ns->buf.byte, num, &pos); 1251 + if (tx != num) { 1252 + NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); 1253 + return; 1254 + } 1255 + do_bit_flips(ns, num); 1256 + } 1257 + return; 1258 + } 1259 + 1432 1260 mypage = NS_GET_PAGE(ns); 1433 1261 if (mypage->byte == NULL) { 1434 1262 NS_DBG("read_page: page %d not allocated\n", ns->regs.row); 1435 1263 memset(ns->buf.byte, 0xFF, num); 1436 1264 } else { 1437 - unsigned int page_no = ns->regs.row; 1438 1265 NS_DBG("read_page: page %d allocated, reading from %d\n", 1439 1266 ns->regs.row, ns->regs.column + ns->regs.off); 1440 - if (read_error(page_no)) { 1441 - int i; 1442 - memset(ns->buf.byte, 0xFF, num); 1443 - for (i = 0; i < num; ++i) 1444 - ns->buf.byte[i] = random32(); 1445 - NS_WARN("simulating read error in page %u\n", page_no); 1267 + if (do_read_error(ns, num)) 1446 1268 return; 1447 - } 1448 1269 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); 1449 - if (bitflips && random32() < (1 << 22)) { 1450 - int flips = 1; 1451 - if (bitflips > 1) 1452 - flips = (random32() % (int) bitflips) + 1; 1453 - while (flips--) { 1454 - int pos = random32() % (num * 8); 1455 - ns->buf.byte[pos / 8] ^= (1 << (pos % 8)); 1456 - NS_WARN("read_page: flipping bit %d in page %d " 1457 - "reading from %d ecc: corrected=%u failed=%u\n", 1458 - pos, ns->regs.row, ns->regs.column + ns->regs.off, 1459 - nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed); 1460 - } 1461 - } 1270 + do_bit_flips(ns, num); 1462 1271 } 1463 1272 } 1464 1273 ··· 1474 1275 union ns_mem *mypage; 1475 1276 int i; 1476 1277 1278 + if (ns->cfile) { 1279 + for (i = 0; i < ns->geom.pgsec; i++) 1280 + if (ns->pages_written[ns->regs.row + i]) { 1281 + NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i); 1282 + ns->pages_written[ns->regs.row + i] = 0; 1283 + } 1284 + return; 1285 + } 1286 + 1477 1287 mypage = NS_GET_PAGE(ns); 1478 1288 for (i = 0; i < ns->geom.pgsec; i++) { 1479 1289 if (mypage->byte != NULL) { 1480 1290 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); 1481 - kfree(mypage->byte); 1291 + kmem_cache_free(ns->nand_pages_slab, mypage->byte); 1482 1292 mypage->byte = NULL; 1483 1293 } 1484 1294 mypage++; ··· 1503 1295 union ns_mem *mypage; 1504 1296 u_char *pg_off; 1505 1297 1298 + if (ns->cfile) { 1299 + loff_t off, pos; 1300 + ssize_t tx; 1301 + int all; 1302 + 1303 + NS_DBG("prog_page: writing page %d\n", ns->regs.row); 1304 + pg_off = ns->file_buf + ns->regs.column + ns->regs.off; 1305 + off = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off; 1306 + if (!ns->pages_written[ns->regs.row]) { 1307 + all = 1; 1308 + memset(ns->file_buf, 0xff, ns->geom.pgszoob); 1309 + } else { 1310 + all = 0; 1311 + pos = off; 1312 + tx = read_file(ns, ns->cfile, pg_off, num, &pos); 1313 + if (tx != num) { 1314 + NS_ERR("prog_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); 1315 + return -1; 1316 + } 1317 + } 1318 + for (i = 0; i < num; i++) 1319 + pg_off[i] &= ns->buf.byte[i]; 1320 + if (all) { 1321 + pos = (loff_t)ns->regs.row * ns->geom.pgszoob; 1322 + tx = write_file(ns, ns->cfile, ns->file_buf, ns->geom.pgszoob, &pos); 1323 + if (tx != ns->geom.pgszoob) { 1324 + NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); 1325 + return -1; 1326 + } 1327 + ns->pages_written[ns->regs.row] = 1; 1328 + } else { 1329 + pos = off; 1330 + tx = write_file(ns, ns->cfile, pg_off, num, &pos); 1331 + if (tx != num) { 1332 + NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); 1333 + return -1; 1334 + } 1335 + } 1336 + return 0; 1337 + } 1338 + 1506 1339 mypage = NS_GET_PAGE(ns); 1507 1340 if (mypage->byte == NULL) { 1508 1341 NS_DBG("prog_page: allocating page %d\n", ns->regs.row); 1509 1342 /* 1510 1343 * We allocate memory with GFP_NOFS because a flash FS may 1511 1344 * utilize this. If it is holding an FS lock, then gets here, 1512 - * then kmalloc runs writeback which goes to the FS again 1513 - * and deadlocks. This was seen in practice. 1345 + * then kernel memory alloc runs writeback which goes to the FS 1346 + * again and deadlocks. This was seen in practice. 1514 1347 */ 1515 - mypage->byte = kmalloc(ns->geom.pgszoob, GFP_NOFS); 1348 + mypage->byte = kmem_cache_alloc(ns->nand_pages_slab, GFP_NOFS); 1516 1349 if (mypage->byte == NULL) { 1517 1350 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); 1518 1351 return -1; ··· 1985 1736 1986 1737 /* Check if chip is expecting command */ 1987 1738 if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { 1988 - /* 1989 - * We are in situation when something else (not command) 1990 - * was expected but command was input. In this case ignore 1991 - * previous command(s)/state(s) and accept the last one. 1992 - */ 1993 - NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, " 1994 - "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); 1739 + /* Do not warn if only 2 id bytes are read */ 1740 + if (!(ns->regs.command == NAND_CMD_READID && 1741 + NS_STATE(ns->state) == STATE_DATAOUT_ID && ns->regs.count == 2)) { 1742 + /* 1743 + * We are in situation when something else (not command) 1744 + * was expected but command was input. In this case ignore 1745 + * previous command(s)/state(s) and accept the last one. 1746 + */ 1747 + NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, " 1748 + "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); 1749 + } 1995 1750 switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); 1996 1751 } 1997 1752 ··· 2297 2044 } 2298 2045 2299 2046 if (overridesize) { 2300 - u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize; 2047 + uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; 2301 2048 if (new_size >> overridesize != nsmtd->erasesize) { 2302 2049 NS_ERR("overridesize is too big\n"); 2303 2050 goto err_exit;
+146 -149
drivers/mtd/nand/ndfc.c
··· 2 2 * drivers/mtd/ndfc.c 3 3 * 4 4 * Overview: 5 - * Platform independend driver for NDFC (NanD Flash Controller) 5 + * Platform independent driver for NDFC (NanD Flash Controller) 6 6 * integrated into EP440 cores 7 + * 8 + * Ported to an OF platform driver by Sean MacLennan 9 + * 10 + * The NDFC supports multiple chips, but this driver only supports a 11 + * single chip since I do not have access to any boards with 12 + * multiple chips. 7 13 * 8 14 * Author: Thomas Gleixner 9 15 * 10 16 * Copyright 2006 IBM 17 + * Copyright 2008 PIKA Technologies 18 + * Sean MacLennan <smaclennan@pikatech.com> 11 19 * 12 20 * This program is free software; you can redistribute it and/or modify it 13 21 * under the terms of the GNU General Public License as published by the ··· 29 21 #include <linux/mtd/partitions.h> 30 22 #include <linux/mtd/ndfc.h> 31 23 #include <linux/mtd/mtd.h> 32 - #include <linux/platform_device.h> 33 - 24 + #include <linux/of_platform.h> 34 25 #include <asm/io.h> 35 - #ifdef CONFIG_40x 36 - #include <asm/ibm405.h> 37 - #else 38 - #include <asm/ibm44x.h> 39 - #endif 40 26 41 - struct ndfc_nand_mtd { 42 - struct mtd_info mtd; 43 - struct nand_chip chip; 44 - struct platform_nand_chip *pl_chip; 45 - }; 46 - 47 - static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS]; 48 27 49 28 struct ndfc_controller { 50 - void __iomem *ndfcbase; 51 - struct nand_hw_control ndfc_control; 52 - atomic_t childs_active; 29 + struct of_device *ofdev; 30 + void __iomem *ndfcbase; 31 + struct mtd_info mtd; 32 + struct nand_chip chip; 33 + int chip_select; 34 + struct nand_hw_control ndfc_control; 35 + #ifdef CONFIG_MTD_PARTITIONS 36 + struct mtd_partition *parts; 37 + #endif 53 38 }; 54 39 55 40 static struct ndfc_controller ndfc_ctrl; ··· 51 50 { 52 51 uint32_t ccr; 53 52 struct ndfc_controller *ndfc = &ndfc_ctrl; 54 - struct nand_chip *nandchip = mtd->priv; 55 - struct ndfc_nand_mtd *nandmtd = nandchip->priv; 56 - struct platform_nand_chip *pchip = nandmtd->pl_chip; 57 53 58 - ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); 54 + ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); 59 55 if (chip >= 0) { 60 56 ccr &= ~NDFC_CCR_BS_MASK; 61 - ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); 57 + ccr |= NDFC_CCR_BS(chip + ndfc->chip_select); 62 58 } else 63 59 ccr |= NDFC_CCR_RESET_CE; 64 - __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); 60 + out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 65 61 } 66 62 67 63 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) ··· 78 80 { 79 81 struct ndfc_controller *ndfc = &ndfc_ctrl; 80 82 81 - return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; 83 + return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; 82 84 } 83 85 84 86 static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) ··· 86 88 uint32_t ccr; 87 89 struct ndfc_controller *ndfc = &ndfc_ctrl; 88 90 89 - ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); 91 + ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); 90 92 ccr |= NDFC_CCR_RESET_ECC; 91 - __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); 93 + out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 92 94 wmb(); 93 95 } 94 96 ··· 100 102 uint8_t *p = (uint8_t *)&ecc; 101 103 102 104 wmb(); 103 - ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC); 104 - ecc_code[0] = p[1]; 105 - ecc_code[1] = p[2]; 105 + ecc = in_be32(ndfc->ndfcbase + NDFC_ECC); 106 + /* The NDFC uses Smart Media (SMC) bytes order */ 107 + ecc_code[0] = p[2]; 108 + ecc_code[1] = p[1]; 106 109 ecc_code[2] = p[3]; 107 110 108 111 return 0; ··· 122 123 uint32_t *p = (uint32_t *) buf; 123 124 124 125 for(;len > 0; len -= 4) 125 - *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA); 126 + *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA); 126 127 } 127 128 128 129 static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) ··· 131 132 uint32_t *p = (uint32_t *) buf; 132 133 133 134 for(;len > 0; len -= 4) 134 - __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA); 135 + out_be32(ndfc->ndfcbase + NDFC_DATA, *p++); 135 136 } 136 137 137 138 static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) ··· 140 141 uint32_t *p = (uint32_t *) buf; 141 142 142 143 for(;len > 0; len -= 4) 143 - if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA)) 144 + if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA)) 144 145 return -EFAULT; 145 146 return 0; 146 147 } ··· 148 149 /* 149 150 * Initialize chip structure 150 151 */ 151 - static void ndfc_chip_init(struct ndfc_nand_mtd *mtd) 152 + static int ndfc_chip_init(struct ndfc_controller *ndfc, 153 + struct device_node *node) 152 154 { 153 - struct ndfc_controller *ndfc = &ndfc_ctrl; 154 - struct nand_chip *chip = &mtd->chip; 155 + #ifdef CONFIG_MTD_PARTITIONS 156 + #ifdef CONFIG_MTD_CMDLINE_PARTS 157 + static const char *part_types[] = { "cmdlinepart", NULL }; 158 + #else 159 + static const char *part_types[] = { NULL }; 160 + #endif 161 + #endif 162 + struct device_node *flash_np; 163 + struct nand_chip *chip = &ndfc->chip; 164 + int ret; 155 165 156 166 chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; 157 167 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; ··· 168 160 chip->dev_ready = ndfc_ready; 169 161 chip->select_chip = ndfc_select_chip; 170 162 chip->chip_delay = 50; 171 - chip->priv = mtd; 172 - chip->options = mtd->pl_chip->options; 173 163 chip->controller = &ndfc->ndfc_control; 174 164 chip->read_buf = ndfc_read_buf; 175 165 chip->write_buf = ndfc_write_buf; ··· 178 172 chip->ecc.mode = NAND_ECC_HW; 179 173 chip->ecc.size = 256; 180 174 chip->ecc.bytes = 3; 181 - chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout; 182 - mtd->mtd.priv = chip; 183 - mtd->mtd.owner = THIS_MODULE; 184 - } 185 175 186 - static int ndfc_chip_probe(struct platform_device *pdev) 187 - { 188 - struct platform_nand_chip *nc = pdev->dev.platform_data; 189 - struct ndfc_chip_settings *settings = nc->priv; 190 - struct ndfc_controller *ndfc = &ndfc_ctrl; 191 - struct ndfc_nand_mtd *nandmtd; 176 + ndfc->mtd.priv = chip; 177 + ndfc->mtd.owner = THIS_MODULE; 192 178 193 - if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS) 194 - return -EINVAL; 195 - 196 - /* Set the bank settings */ 197 - __raw_writel(settings->bank_settings, 198 - ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2)); 199 - 200 - nandmtd = &ndfc_mtd[pdev->id]; 201 - if (nandmtd->pl_chip) 202 - return -EBUSY; 203 - 204 - nandmtd->pl_chip = nc; 205 - ndfc_chip_init(nandmtd); 206 - 207 - /* Scan for chips */ 208 - if (nand_scan(&nandmtd->mtd, nc->nr_chips)) { 209 - nandmtd->pl_chip = NULL; 179 + flash_np = of_get_next_child(node, NULL); 180 + if (!flash_np) 210 181 return -ENODEV; 182 + 183 + ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", 184 + ndfc->ofdev->dev.bus_id, flash_np->name); 185 + if (!ndfc->mtd.name) { 186 + ret = -ENOMEM; 187 + goto err; 211 188 } 189 + 190 + ret = nand_scan(&ndfc->mtd, 1); 191 + if (ret) 192 + goto err; 212 193 213 194 #ifdef CONFIG_MTD_PARTITIONS 214 - printk("Number of partitions %d\n", nc->nr_partitions); 215 - if (nc->nr_partitions) { 216 - /* Add the full device, so complete dumps can be made */ 217 - add_mtd_device(&nandmtd->mtd); 218 - add_mtd_partitions(&nandmtd->mtd, nc->partitions, 219 - nc->nr_partitions); 195 + ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); 196 + if (ret < 0) 197 + goto err; 220 198 221 - } else 222 - #else 223 - add_mtd_device(&nandmtd->mtd); 224 - #endif 225 - 226 - atomic_inc(&ndfc->childs_active); 227 - return 0; 228 - } 229 - 230 - static int ndfc_chip_remove(struct platform_device *pdev) 231 - { 232 - return 0; 233 - } 234 - 235 - static int ndfc_nand_probe(struct platform_device *pdev) 236 - { 237 - struct platform_nand_ctrl *nc = pdev->dev.platform_data; 238 - struct ndfc_controller_settings *settings = nc->priv; 239 - struct resource *res = pdev->resource; 240 - struct ndfc_controller *ndfc = &ndfc_ctrl; 241 - unsigned long long phys = settings->ndfc_erpn | res->start; 242 - 243 - #ifndef CONFIG_PHYS_64BIT 244 - ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1); 245 - #else 246 - ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1); 247 - #endif 248 - if (!ndfc->ndfcbase) { 249 - printk(KERN_ERR "NDFC: ioremap failed\n"); 250 - return -EIO; 199 + #ifdef CONFIG_MTD_OF_PARTS 200 + if (ret == 0) { 201 + ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, 202 + &ndfc->parts); 203 + if (ret < 0) 204 + goto err; 251 205 } 206 + #endif 252 207 253 - __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR); 208 + if (ret > 0) 209 + ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret); 210 + else 211 + #endif 212 + ret = add_mtd_device(&ndfc->mtd); 213 + 214 + err: 215 + of_node_put(flash_np); 216 + if (ret) 217 + kfree(ndfc->mtd.name); 218 + return ret; 219 + } 220 + 221 + static int __devinit ndfc_probe(struct of_device *ofdev, 222 + const struct of_device_id *match) 223 + { 224 + struct ndfc_controller *ndfc = &ndfc_ctrl; 225 + const u32 *reg; 226 + u32 ccr; 227 + int err, len; 254 228 255 229 spin_lock_init(&ndfc->ndfc_control.lock); 256 230 init_waitqueue_head(&ndfc->ndfc_control.wq); 231 + ndfc->ofdev = ofdev; 232 + dev_set_drvdata(&ofdev->dev, ndfc); 257 233 258 - platform_set_drvdata(pdev, ndfc); 259 - 260 - printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n", 261 - __raw_readl(ndfc->ndfcbase + NDFC_REVID)); 262 - 263 - return 0; 264 - } 265 - 266 - static int ndfc_nand_remove(struct platform_device *pdev) 267 - { 268 - struct ndfc_controller *ndfc = platform_get_drvdata(pdev); 269 - 270 - if (atomic_read(&ndfc->childs_active)) 271 - return -EBUSY; 272 - 273 - if (ndfc) { 274 - platform_set_drvdata(pdev, NULL); 275 - iounmap(ndfc_ctrl.ndfcbase); 276 - ndfc_ctrl.ndfcbase = NULL; 234 + /* Read the reg property to get the chip select */ 235 + reg = of_get_property(ofdev->node, "reg", &len); 236 + if (reg == NULL || len != 12) { 237 + dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); 238 + return -ENOENT; 277 239 } 240 + ndfc->chip_select = reg[0]; 241 + 242 + ndfc->ndfcbase = of_iomap(ofdev->node, 0); 243 + if (!ndfc->ndfcbase) { 244 + dev_err(&ofdev->dev, "failed to get memory\n"); 245 + return -EIO; 246 + } 247 + 248 + ccr = NDFC_CCR_BS(ndfc->chip_select); 249 + 250 + /* It is ok if ccr does not exist - just default to 0 */ 251 + reg = of_get_property(ofdev->node, "ccr", NULL); 252 + if (reg) 253 + ccr |= *reg; 254 + 255 + out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); 256 + 257 + /* Set the bank settings if given */ 258 + reg = of_get_property(ofdev->node, "bank-settings", NULL); 259 + if (reg) { 260 + int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); 261 + out_be32(ndfc->ndfcbase + offset, *reg); 262 + } 263 + 264 + err = ndfc_chip_init(ndfc, ofdev->node); 265 + if (err) { 266 + iounmap(ndfc->ndfcbase); 267 + return err; 268 + } 269 + 278 270 return 0; 279 271 } 280 272 281 - /* driver device registration */ 273 + static int __devexit ndfc_remove(struct of_device *ofdev) 274 + { 275 + struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); 282 276 283 - static struct platform_driver ndfc_chip_driver = { 284 - .probe = ndfc_chip_probe, 285 - .remove = ndfc_chip_remove, 286 - .driver = { 287 - .name = "ndfc-chip", 288 - .owner = THIS_MODULE, 289 - }, 277 + nand_release(&ndfc->mtd); 278 + 279 + return 0; 280 + } 281 + 282 + static const struct of_device_id ndfc_match[] = { 283 + { .compatible = "ibm,ndfc", }, 284 + {} 290 285 }; 286 + MODULE_DEVICE_TABLE(of, ndfc_match); 291 287 292 - static struct platform_driver ndfc_nand_driver = { 293 - .probe = ndfc_nand_probe, 294 - .remove = ndfc_nand_remove, 295 - .driver = { 296 - .name = "ndfc-nand", 297 - .owner = THIS_MODULE, 288 + static struct of_platform_driver ndfc_driver = { 289 + .driver = { 290 + .name = "ndfc", 298 291 }, 292 + .match_table = ndfc_match, 293 + .probe = ndfc_probe, 294 + .remove = __devexit_p(ndfc_remove), 299 295 }; 300 296 301 297 static int __init ndfc_nand_init(void) 302 298 { 303 - int ret; 304 - 305 - spin_lock_init(&ndfc_ctrl.ndfc_control.lock); 306 - init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq); 307 - 308 - ret = platform_driver_register(&ndfc_nand_driver); 309 - if (!ret) 310 - ret = platform_driver_register(&ndfc_chip_driver); 311 - return ret; 299 + return of_register_platform_driver(&ndfc_driver); 312 300 } 313 301 314 302 static void __exit ndfc_nand_exit(void) 315 303 { 316 - platform_driver_unregister(&ndfc_chip_driver); 317 - platform_driver_unregister(&ndfc_nand_driver); 304 + of_unregister_platform_driver(&ndfc_driver); 318 305 } 319 306 320 307 module_init(ndfc_nand_init); ··· 315 316 316 317 MODULE_LICENSE("GPL"); 317 318 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); 318 - MODULE_DESCRIPTION("Platform driver for NDFC"); 319 - MODULE_ALIAS("platform:ndfc-chip"); 320 - MODULE_ALIAS("platform:ndfc-nand"); 319 + MODULE_DESCRIPTION("OF Platform driver for NDFC");
+3 -3
drivers/mtd/nand/pxa3xx_nand.c
··· 298 298 #define NDTR1_tAR(c) (min((c), 15) << 0) 299 299 300 300 /* convert nano-seconds to nand flash controller clock cycles */ 301 - #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1) 301 + #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) - 1) 302 302 303 303 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, 304 304 const struct pxa3xx_nand_timing *t) ··· 368 368 /* large block, 2 cycles for column address 369 369 * row address starts from 3rd cycle 370 370 */ 371 - info->ndcb1 |= (page_addr << 16) | (column & 0xffff); 371 + info->ndcb1 |= page_addr << 16; 372 372 if (info->row_addr_cycles == 3) 373 373 info->ndcb2 = (page_addr >> 16) & 0xff; 374 374 } else 375 375 /* small block, 1 cycles for column address 376 376 * row address starts from 2nd cycle 377 377 */ 378 - info->ndcb1 = (page_addr << 8) | (column & 0xff); 378 + info->ndcb1 = page_addr << 8; 379 379 380 380 if (cmd == cmdset->program) 381 381 info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
+123 -126
drivers/mtd/nand/sharpsl.c
··· 2 2 * drivers/mtd/nand/sharpsl.c 3 3 * 4 4 * Copyright (C) 2004 Richard Purdie 5 + * Copyright (C) 2008 Dmitry Baryshkov 5 6 * 6 7 * Based on Sharp's NAND driver sharp_sl.c 7 8 * ··· 20 19 #include <linux/mtd/nand.h> 21 20 #include <linux/mtd/nand_ecc.h> 22 21 #include <linux/mtd/partitions.h> 22 + #include <linux/mtd/sharpsl.h> 23 23 #include <linux/interrupt.h> 24 + #include <linux/platform_device.h> 25 + 24 26 #include <asm/io.h> 25 27 #include <mach/hardware.h> 26 28 #include <asm/mach-types.h> 27 29 28 - static void __iomem *sharpsl_io_base; 29 - static int sharpsl_phys_base = 0x0C000000; 30 + struct sharpsl_nand { 31 + struct mtd_info mtd; 32 + struct nand_chip chip; 33 + 34 + void __iomem *io; 35 + }; 36 + 37 + #define mtd_to_sharpsl(_mtd) container_of(_mtd, struct sharpsl_nand, mtd) 30 38 31 39 /* register offset */ 32 - #define ECCLPLB sharpsl_io_base+0x00 /* line parity 7 - 0 bit */ 33 - #define ECCLPUB sharpsl_io_base+0x04 /* line parity 15 - 8 bit */ 34 - #define ECCCP sharpsl_io_base+0x08 /* column parity 5 - 0 bit */ 35 - #define ECCCNTR sharpsl_io_base+0x0C /* ECC byte counter */ 36 - #define ECCCLRR sharpsl_io_base+0x10 /* cleare ECC */ 37 - #define FLASHIO sharpsl_io_base+0x14 /* Flash I/O */ 38 - #define FLASHCTL sharpsl_io_base+0x18 /* Flash Control */ 40 + #define ECCLPLB 0x00 /* line parity 7 - 0 bit */ 41 + #define ECCLPUB 0x04 /* line parity 15 - 8 bit */ 42 + #define ECCCP 0x08 /* column parity 5 - 0 bit */ 43 + #define ECCCNTR 0x0C /* ECC byte counter */ 44 + #define ECCCLRR 0x10 /* cleare ECC */ 45 + #define FLASHIO 0x14 /* Flash I/O */ 46 + #define FLASHCTL 0x18 /* Flash Control */ 39 47 40 48 /* Flash control bit */ 41 49 #define FLRYBY (1 << 5) ··· 53 43 #define FLALE (1 << 2) 54 44 #define FLCLE (1 << 1) 55 45 #define FLCE0 (1 << 0) 56 - 57 - /* 58 - * MTD structure for SharpSL 59 - */ 60 - static struct mtd_info *sharpsl_mtd = NULL; 61 - 62 - /* 63 - * Define partitions for flash device 64 - */ 65 - #define DEFAULT_NUM_PARTITIONS 3 66 - 67 - static int nr_partitions; 68 - static struct mtd_partition sharpsl_nand_default_partition_info[] = { 69 - { 70 - .name = "System Area", 71 - .offset = 0, 72 - .size = 7 * 1024 * 1024, 73 - }, 74 - { 75 - .name = "Root Filesystem", 76 - .offset = 7 * 1024 * 1024, 77 - .size = 30 * 1024 * 1024, 78 - }, 79 - { 80 - .name = "Home Filesystem", 81 - .offset = MTDPART_OFS_APPEND, 82 - .size = MTDPART_SIZ_FULL, 83 - }, 84 - }; 85 46 86 47 /* 87 48 * hardware specific access to control-lines ··· 65 84 static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, 66 85 unsigned int ctrl) 67 86 { 87 + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); 68 88 struct nand_chip *chip = mtd->priv; 69 89 70 90 if (ctrl & NAND_CTRL_CHANGE) { ··· 75 93 76 94 bits ^= 0x11; 77 95 78 - writeb((readb(FLASHCTL) & ~0x17) | bits, FLASHCTL); 96 + writeb((readb(sharpsl->io + FLASHCTL) & ~0x17) | bits, sharpsl->io + FLASHCTL); 79 97 } 80 98 81 99 if (cmd != NAND_CMD_NONE) 82 100 writeb(cmd, chip->IO_ADDR_W); 83 101 } 84 102 85 - static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 86 - 87 - static struct nand_bbt_descr sharpsl_bbt = { 88 - .options = 0, 89 - .offs = 4, 90 - .len = 2, 91 - .pattern = scan_ff_pattern 92 - }; 93 - 94 - static struct nand_bbt_descr sharpsl_akita_bbt = { 95 - .options = 0, 96 - .offs = 4, 97 - .len = 1, 98 - .pattern = scan_ff_pattern 99 - }; 100 - 101 - static struct nand_ecclayout akita_oobinfo = { 102 - .eccbytes = 24, 103 - .eccpos = { 104 - 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, 105 - 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, 106 - 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, 107 - .oobfree = {{0x08, 0x09}} 108 - }; 109 - 110 103 static int sharpsl_nand_dev_ready(struct mtd_info *mtd) 111 104 { 112 - return !((readb(FLASHCTL) & FLRYBY) == 0); 105 + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); 106 + return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0); 113 107 } 114 108 115 109 static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode) 116 110 { 117 - writeb(0, ECCCLRR); 111 + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); 112 + writeb(0, sharpsl->io + ECCCLRR); 118 113 } 119 114 120 115 static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) 121 116 { 122 - ecc_code[0] = ~readb(ECCLPUB); 123 - ecc_code[1] = ~readb(ECCLPLB); 124 - ecc_code[2] = (~readb(ECCCP) << 2) | 0x03; 125 - return readb(ECCCNTR) != 0; 117 + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); 118 + ecc_code[0] = ~readb(sharpsl->io + ECCLPUB); 119 + ecc_code[1] = ~readb(sharpsl->io + ECCLPLB); 120 + ecc_code[2] = (~readb(sharpsl->io + ECCCP) << 2) | 0x03; 121 + return readb(sharpsl->io + ECCCNTR) != 0; 126 122 } 127 123 128 124 #ifdef CONFIG_MTD_PARTITIONS 129 - const char *part_probes[] = { "cmdlinepart", NULL }; 125 + static const char *part_probes[] = { "cmdlinepart", NULL }; 130 126 #endif 131 127 132 128 /* 133 129 * Main initialization routine 134 130 */ 135 - static int __init sharpsl_nand_init(void) 131 + static int __devinit sharpsl_nand_probe(struct platform_device *pdev) 136 132 { 137 133 struct nand_chip *this; 134 + #ifdef CONFIG_MTD_PARTITIONS 138 135 struct mtd_partition *sharpsl_partition_info; 136 + int nr_partitions; 137 + #endif 138 + struct resource *r; 139 139 int err = 0; 140 + struct sharpsl_nand *sharpsl; 141 + struct sharpsl_nand_platform_data *data = pdev->dev.platform_data; 142 + 143 + if (!data) { 144 + dev_err(&pdev->dev, "no platform data!\n"); 145 + return -EINVAL; 146 + } 140 147 141 148 /* Allocate memory for MTD device structure and private data */ 142 - sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); 143 - if (!sharpsl_mtd) { 149 + sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL); 150 + if (!sharpsl) { 144 151 printk("Unable to allocate SharpSL NAND MTD device structure.\n"); 145 152 return -ENOMEM; 146 153 } 147 154 155 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 156 + if (!r) { 157 + dev_err(&pdev->dev, "no io memory resource defined!\n"); 158 + err = -ENODEV; 159 + goto err_get_res; 160 + } 161 + 148 162 /* map physical address */ 149 - sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); 150 - if (!sharpsl_io_base) { 163 + sharpsl->io = ioremap(r->start, resource_size(r)); 164 + if (!sharpsl->io) { 151 165 printk("ioremap to access Sharp SL NAND chip failed\n"); 152 - kfree(sharpsl_mtd); 153 - return -EIO; 166 + err = -EIO; 167 + goto err_ioremap; 154 168 } 155 169 156 170 /* Get pointer to private data */ 157 - this = (struct nand_chip *)(&sharpsl_mtd[1]); 158 - 159 - /* Initialize structures */ 160 - memset(sharpsl_mtd, 0, sizeof(struct mtd_info)); 161 - memset(this, 0, sizeof(struct nand_chip)); 171 + this = (struct nand_chip *)(&sharpsl->chip); 162 172 163 173 /* Link the private data with the MTD structure */ 164 - sharpsl_mtd->priv = this; 165 - sharpsl_mtd->owner = THIS_MODULE; 174 + sharpsl->mtd.priv = this; 175 + sharpsl->mtd.owner = THIS_MODULE; 176 + 177 + platform_set_drvdata(pdev, sharpsl); 166 178 167 179 /* 168 180 * PXA initialize 169 181 */ 170 - writeb(readb(FLASHCTL) | FLWP, FLASHCTL); 182 + writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL); 171 183 172 184 /* Set address of NAND IO lines */ 173 - this->IO_ADDR_R = FLASHIO; 174 - this->IO_ADDR_W = FLASHIO; 185 + this->IO_ADDR_R = sharpsl->io + FLASHIO; 186 + this->IO_ADDR_W = sharpsl->io + FLASHIO; 175 187 /* Set address of hardware control function */ 176 188 this->cmd_ctrl = sharpsl_nand_hwcontrol; 177 189 this->dev_ready = sharpsl_nand_dev_ready; ··· 175 199 this->ecc.mode = NAND_ECC_HW; 176 200 this->ecc.size = 256; 177 201 this->ecc.bytes = 3; 178 - this->badblock_pattern = &sharpsl_bbt; 179 - if (machine_is_akita() || machine_is_borzoi()) { 180 - this->badblock_pattern = &sharpsl_akita_bbt; 181 - this->ecc.layout = &akita_oobinfo; 182 - } 202 + this->badblock_pattern = data->badblock_pattern; 203 + this->ecc.layout = data->ecc_layout; 183 204 this->ecc.hwctl = sharpsl_nand_enable_hwecc; 184 205 this->ecc.calculate = sharpsl_nand_calculate_ecc; 185 206 this->ecc.correct = nand_correct_data; 186 207 187 208 /* Scan to find existence of the device */ 188 - err = nand_scan(sharpsl_mtd, 1); 189 - if (err) { 190 - iounmap(sharpsl_io_base); 191 - kfree(sharpsl_mtd); 192 - return err; 193 - } 209 + err = nand_scan(&sharpsl->mtd, 1); 210 + if (err) 211 + goto err_scan; 194 212 195 213 /* Register the partitions */ 196 - sharpsl_mtd->name = "sharpsl-nand"; 197 - nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0); 198 - 214 + sharpsl->mtd.name = "sharpsl-nand"; 215 + #ifdef CONFIG_MTD_PARTITIONS 216 + nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); 199 217 if (nr_partitions <= 0) { 200 - nr_partitions = DEFAULT_NUM_PARTITIONS; 201 - sharpsl_partition_info = sharpsl_nand_default_partition_info; 202 - if (machine_is_poodle()) { 203 - sharpsl_partition_info[1].size = 22 * 1024 * 1024; 204 - } else if (machine_is_corgi() || machine_is_shepherd()) { 205 - sharpsl_partition_info[1].size = 25 * 1024 * 1024; 206 - } else if (machine_is_husky()) { 207 - sharpsl_partition_info[1].size = 53 * 1024 * 1024; 208 - } else if (machine_is_spitz()) { 209 - sharpsl_partition_info[1].size = 5 * 1024 * 1024; 210 - } else if (machine_is_akita()) { 211 - sharpsl_partition_info[1].size = 58 * 1024 * 1024; 212 - } else if (machine_is_borzoi()) { 213 - sharpsl_partition_info[1].size = 32 * 1024 * 1024; 214 - } 218 + nr_partitions = data->nr_partitions; 219 + sharpsl_partition_info = data->partitions; 215 220 } 216 221 217 - add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions); 222 + if (nr_partitions > 0) 223 + err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions); 224 + else 225 + #endif 226 + err = add_mtd_device(&sharpsl->mtd); 227 + if (err) 228 + goto err_add; 218 229 219 230 /* Return happy */ 220 231 return 0; 221 - } 222 232 223 - module_init(sharpsl_nand_init); 233 + err_add: 234 + nand_release(&sharpsl->mtd); 235 + 236 + err_scan: 237 + platform_set_drvdata(pdev, NULL); 238 + iounmap(sharpsl->io); 239 + err_ioremap: 240 + err_get_res: 241 + kfree(sharpsl); 242 + return err; 243 + } 224 244 225 245 /* 226 246 * Clean up routine 227 247 */ 228 - static void __exit sharpsl_nand_cleanup(void) 248 + static int __devexit sharpsl_nand_remove(struct platform_device *pdev) 229 249 { 230 - /* Release resources, unregister device */ 231 - nand_release(sharpsl_mtd); 250 + struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); 232 251 233 - iounmap(sharpsl_io_base); 252 + /* Release resources, unregister device */ 253 + nand_release(&sharpsl->mtd); 254 + 255 + platform_set_drvdata(pdev, NULL); 256 + 257 + iounmap(sharpsl->io); 234 258 235 259 /* Free the MTD device structure */ 236 - kfree(sharpsl_mtd); 260 + kfree(sharpsl); 261 + 262 + return 0; 237 263 } 238 264 239 - module_exit(sharpsl_nand_cleanup); 265 + static struct platform_driver sharpsl_nand_driver = { 266 + .driver = { 267 + .name = "sharpsl-nand", 268 + .owner = THIS_MODULE, 269 + }, 270 + .probe = sharpsl_nand_probe, 271 + .remove = __devexit_p(sharpsl_nand_remove), 272 + }; 273 + 274 + static int __init sharpsl_nand_init(void) 275 + { 276 + return platform_driver_register(&sharpsl_nand_driver); 277 + } 278 + module_init(sharpsl_nand_init); 279 + 280 + static void __exit sharpsl_nand_exit(void) 281 + { 282 + platform_driver_unregister(&sharpsl_nand_driver); 283 + } 284 + module_exit(sharpsl_nand_exit); 240 285 241 286 MODULE_LICENSE("GPL"); 242 287 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+1 -1
drivers/mtd/nftlcore.c
··· 39 39 struct NFTLrecord *nftl; 40 40 unsigned long temp; 41 41 42 - if (mtd->type != MTD_NANDFLASH) 42 + if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) 43 43 return; 44 44 /* OK, this is moderately ugly. But probably safe. Alternatives? */ 45 45 if (memcmp(mtd->name, "DiskOnChip", 10))
+2 -2
drivers/mtd/nftlmount.c
··· 51 51 the mtd device accordingly. We could even get rid of 52 52 nftl->EraseSize if there were any point in doing so. */ 53 53 nftl->EraseSize = nftl->mbd.mtd->erasesize; 54 - nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; 54 + nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize; 55 55 56 56 nftl->MediaUnit = BLOCK_NIL; 57 57 nftl->SpareMediaUnit = BLOCK_NIL; ··· 168 168 printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n", 169 169 mh->UnitSizeFactor); 170 170 nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor); 171 - nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize; 171 + nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize; 172 172 } 173 173 #endif 174 174 nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
+4 -4
drivers/mtd/onenand/onenand_base.c
··· 1772 1772 int len; 1773 1773 int ret = 0; 1774 1774 1775 - DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); 1775 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len); 1776 1776 1777 1777 block_size = (1 << this->erase_shift); 1778 1778 ··· 1810 1810 1811 1811 /* Check if we have a bad block, we do not erase bad blocks */ 1812 1812 if (onenand_block_isbad_nolock(mtd, addr, 0)) { 1813 - printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr); 1813 + printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr); 1814 1814 instr->state = MTD_ERASE_FAILED; 1815 1815 goto erase_exit; 1816 1816 } ··· 2029 2029 * 2030 2030 * Lock one or more blocks 2031 2031 */ 2032 - static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 2032 + static int onenand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 2033 2033 { 2034 2034 int ret; 2035 2035 ··· 2047 2047 * 2048 2048 * Unlock one or more blocks 2049 2049 */ 2050 - static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 2050 + static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 2051 2051 { 2052 2052 int ret; 2053 2053
+14 -15
drivers/mtd/rfd_ftl.c
··· 21 21 22 22 #include <asm/types.h> 23 23 24 - #define const_cpu_to_le16 __constant_cpu_to_le16 25 - 26 24 static int block_size = 0; 27 25 module_param(block_size, int, 0); 28 26 MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit size"); ··· 154 156 size_t retlen; 155 157 156 158 sectors_per_block = part->block_size / SECTOR_SIZE; 157 - part->total_blocks = part->mbd.mtd->size / part->block_size; 159 + part->total_blocks = (u32)part->mbd.mtd->size / part->block_size; 158 160 159 161 if (part->total_blocks < 2) 160 162 return -ENOENT; ··· 274 276 275 277 part = (struct partition*)erase->priv; 276 278 277 - i = erase->addr / part->block_size; 278 - if (i >= part->total_blocks || part->blocks[i].offset != erase->addr) { 279 - printk(KERN_ERR PREFIX "erase callback for unknown offset %x " 280 - "on '%s'\n", erase->addr, part->mbd.mtd->name); 279 + i = (u32)erase->addr / part->block_size; 280 + if (i >= part->total_blocks || part->blocks[i].offset != erase->addr || 281 + erase->addr > UINT_MAX) { 282 + printk(KERN_ERR PREFIX "erase callback for unknown offset %llx " 283 + "on '%s'\n", (unsigned long long)erase->addr, part->mbd.mtd->name); 281 284 return; 282 285 } 283 286 284 287 if (erase->state != MTD_ERASE_DONE) { 285 - printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', " 286 - "state %d\n", erase->addr, 288 + printk(KERN_WARNING PREFIX "erase failed at 0x%llx on '%s', " 289 + "state %d\n", (unsigned long long)erase->addr, 287 290 part->mbd.mtd->name, erase->state); 288 291 289 292 part->blocks[i].state = BLOCK_FAILED; ··· 296 297 return; 297 298 } 298 299 299 - magic = const_cpu_to_le16(RFD_MAGIC); 300 + magic = cpu_to_le16(RFD_MAGIC); 300 301 301 302 part->blocks[i].state = BLOCK_ERASED; 302 303 part->blocks[i].free_sectors = part->data_sectors_per_block; ··· 344 345 rc = part->mbd.mtd->erase(part->mbd.mtd, erase); 345 346 346 347 if (rc) { 347 - printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' " 348 - "failed\n", erase->addr, erase->len, 349 - part->mbd.mtd->name); 348 + printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' " 349 + "failed\n", (unsigned long long)erase->addr, 350 + (unsigned long long)erase->len, part->mbd.mtd->name); 350 351 kfree(erase); 351 352 } 352 353 ··· 586 587 int block, offset, rc; 587 588 u_long addr; 588 589 size_t retlen; 589 - u16 del = const_cpu_to_le16(SECTOR_DELETED); 590 + u16 del = cpu_to_le16(SECTOR_DELETED); 590 591 591 592 block = old_addr / part->block_size; 592 593 offset = (old_addr % part->block_size) / SECTOR_SIZE - ··· 762 763 { 763 764 struct partition *part; 764 765 765 - if (mtd->type != MTD_NORFLASH) 766 + if (mtd->type != MTD_NORFLASH || mtd->size > UINT_MAX) 766 767 return; 767 768 768 769 part = kzalloc(sizeof(struct partition), GFP_KERNEL);
+4 -3
drivers/mtd/ssfdc.c
··· 294 294 int cis_sector; 295 295 296 296 /* Check for small page NAND flash */ 297 - if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE) 297 + if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE || 298 + mtd->size > UINT_MAX) 298 299 return; 299 300 300 301 /* Check for SSDFC format by reading CIS/IDI sector */ ··· 317 316 318 317 ssfdc->cis_block = cis_sector / (mtd->erasesize >> SECTOR_SHIFT); 319 318 ssfdc->erase_size = mtd->erasesize; 320 - ssfdc->map_len = mtd->size / mtd->erasesize; 319 + ssfdc->map_len = (u32)mtd->size / mtd->erasesize; 321 320 322 321 DEBUG(MTD_DEBUG_LEVEL1, 323 322 "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n", ··· 328 327 ssfdc->heads = 16; 329 328 ssfdc->sectors = 32; 330 329 get_chs(mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); 331 - ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) / 330 + ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) / 332 331 ((long)ssfdc->sectors * (long)ssfdc->heads)); 333 332 334 333 DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
+7
drivers/mtd/tests/Makefile
··· 1 + obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o 2 + obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o 3 + obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o 4 + obj-$(CONFIG_MTD_TESTS) += mtd_speedtest.o 5 + obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o 6 + obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o 7 + obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
+742
drivers/mtd/tests/mtd_oobtest.c
··· 1 + /* 2 + * Copyright (C) 2006-2008 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Test OOB read and write on MTD device. 18 + * 19 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20 + */ 21 + 22 + #include <asm/div64.h> 23 + #include <linux/init.h> 24 + #include <linux/module.h> 25 + #include <linux/moduleparam.h> 26 + #include <linux/err.h> 27 + #include <linux/mtd/mtd.h> 28 + #include <linux/sched.h> 29 + 30 + #define PRINT_PREF KERN_INFO "mtd_oobtest: " 31 + 32 + static int dev; 33 + module_param(dev, int, S_IRUGO); 34 + MODULE_PARM_DESC(dev, "MTD device number to use"); 35 + 36 + static struct mtd_info *mtd; 37 + static unsigned char *readbuf; 38 + static unsigned char *writebuf; 39 + static unsigned char *bbt; 40 + 41 + static int ebcnt; 42 + static int pgcnt; 43 + static int errcnt; 44 + static int use_offset; 45 + static int use_len; 46 + static int use_len_max; 47 + static int vary_offset; 48 + static unsigned long next = 1; 49 + 50 + static inline unsigned int simple_rand(void) 51 + { 52 + next = next * 1103515245 + 12345; 53 + return (unsigned int)((next / 65536) % 32768); 54 + } 55 + 56 + static inline void simple_srand(unsigned long seed) 57 + { 58 + next = seed; 59 + } 60 + 61 + static void set_random_data(unsigned char *buf, size_t len) 62 + { 63 + size_t i; 64 + 65 + for (i = 0; i < len; ++i) 66 + buf[i] = simple_rand(); 67 + } 68 + 69 + static int erase_eraseblock(int ebnum) 70 + { 71 + int err; 72 + struct erase_info ei; 73 + loff_t addr = ebnum * mtd->erasesize; 74 + 75 + memset(&ei, 0, sizeof(struct erase_info)); 76 + ei.mtd = mtd; 77 + ei.addr = addr; 78 + ei.len = mtd->erasesize; 79 + 80 + err = mtd->erase(mtd, &ei); 81 + if (err) { 82 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 83 + return err; 84 + } 85 + 86 + if (ei.state == MTD_ERASE_FAILED) { 87 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 88 + ebnum); 89 + return -EIO; 90 + } 91 + 92 + return 0; 93 + } 94 + 95 + static int erase_whole_device(void) 96 + { 97 + int err; 98 + unsigned int i; 99 + 100 + printk(PRINT_PREF "erasing whole device\n"); 101 + for (i = 0; i < ebcnt; ++i) { 102 + if (bbt[i]) 103 + continue; 104 + err = erase_eraseblock(i); 105 + if (err) 106 + return err; 107 + cond_resched(); 108 + } 109 + printk(PRINT_PREF "erased %u eraseblocks\n", i); 110 + return 0; 111 + } 112 + 113 + static void do_vary_offset(void) 114 + { 115 + use_len -= 1; 116 + if (use_len < 1) { 117 + use_offset += 1; 118 + if (use_offset >= use_len_max) 119 + use_offset = 0; 120 + use_len = use_len_max - use_offset; 121 + } 122 + } 123 + 124 + static int write_eraseblock(int ebnum) 125 + { 126 + int i; 127 + struct mtd_oob_ops ops; 128 + int err = 0; 129 + loff_t addr = ebnum * mtd->erasesize; 130 + 131 + for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { 132 + set_random_data(writebuf, use_len); 133 + ops.mode = MTD_OOB_AUTO; 134 + ops.len = 0; 135 + ops.retlen = 0; 136 + ops.ooblen = use_len; 137 + ops.oobretlen = 0; 138 + ops.ooboffs = use_offset; 139 + ops.datbuf = 0; 140 + ops.oobbuf = writebuf; 141 + err = mtd->write_oob(mtd, addr, &ops); 142 + if (err || ops.oobretlen != use_len) { 143 + printk(PRINT_PREF "error: writeoob failed at %#llx\n", 144 + (long long)addr); 145 + printk(PRINT_PREF "error: use_len %d, use_offset %d\n", 146 + use_len, use_offset); 147 + errcnt += 1; 148 + return err ? err : -1; 149 + } 150 + if (vary_offset) 151 + do_vary_offset(); 152 + } 153 + 154 + return err; 155 + } 156 + 157 + static int write_whole_device(void) 158 + { 159 + int err; 160 + unsigned int i; 161 + 162 + printk(PRINT_PREF "writing OOBs of whole device\n"); 163 + for (i = 0; i < ebcnt; ++i) { 164 + if (bbt[i]) 165 + continue; 166 + err = write_eraseblock(i); 167 + if (err) 168 + return err; 169 + if (i % 256 == 0) 170 + printk(PRINT_PREF "written up to eraseblock %u\n", i); 171 + cond_resched(); 172 + } 173 + printk(PRINT_PREF "written %u eraseblocks\n", i); 174 + return 0; 175 + } 176 + 177 + static int verify_eraseblock(int ebnum) 178 + { 179 + int i; 180 + struct mtd_oob_ops ops; 181 + int err = 0; 182 + loff_t addr = ebnum * mtd->erasesize; 183 + 184 + for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { 185 + set_random_data(writebuf, use_len); 186 + ops.mode = MTD_OOB_AUTO; 187 + ops.len = 0; 188 + ops.retlen = 0; 189 + ops.ooblen = use_len; 190 + ops.oobretlen = 0; 191 + ops.ooboffs = use_offset; 192 + ops.datbuf = 0; 193 + ops.oobbuf = readbuf; 194 + err = mtd->read_oob(mtd, addr, &ops); 195 + if (err || ops.oobretlen != use_len) { 196 + printk(PRINT_PREF "error: readoob failed at %#llx\n", 197 + (long long)addr); 198 + errcnt += 1; 199 + return err ? err : -1; 200 + } 201 + if (memcmp(readbuf, writebuf, use_len)) { 202 + printk(PRINT_PREF "error: verify failed at %#llx\n", 203 + (long long)addr); 204 + errcnt += 1; 205 + if (errcnt > 1000) { 206 + printk(PRINT_PREF "error: too many errors\n"); 207 + return -1; 208 + } 209 + } 210 + if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { 211 + int k; 212 + 213 + ops.mode = MTD_OOB_AUTO; 214 + ops.len = 0; 215 + ops.retlen = 0; 216 + ops.ooblen = mtd->ecclayout->oobavail; 217 + ops.oobretlen = 0; 218 + ops.ooboffs = 0; 219 + ops.datbuf = 0; 220 + ops.oobbuf = readbuf; 221 + err = mtd->read_oob(mtd, addr, &ops); 222 + if (err || ops.oobretlen != mtd->ecclayout->oobavail) { 223 + printk(PRINT_PREF "error: readoob failed at " 224 + "%#llx\n", (long long)addr); 225 + errcnt += 1; 226 + return err ? err : -1; 227 + } 228 + if (memcmp(readbuf + use_offset, writebuf, use_len)) { 229 + printk(PRINT_PREF "error: verify failed at " 230 + "%#llx\n", (long long)addr); 231 + errcnt += 1; 232 + if (errcnt > 1000) { 233 + printk(PRINT_PREF "error: too many " 234 + "errors\n"); 235 + return -1; 236 + } 237 + } 238 + for (k = 0; k < use_offset; ++k) 239 + if (readbuf[k] != 0xff) { 240 + printk(PRINT_PREF "error: verify 0xff " 241 + "failed at %#llx\n", 242 + (long long)addr); 243 + errcnt += 1; 244 + if (errcnt > 1000) { 245 + printk(PRINT_PREF "error: too " 246 + "many errors\n"); 247 + return -1; 248 + } 249 + } 250 + for (k = use_offset + use_len; 251 + k < mtd->ecclayout->oobavail; ++k) 252 + if (readbuf[k] != 0xff) { 253 + printk(PRINT_PREF "error: verify 0xff " 254 + "failed at %#llx\n", 255 + (long long)addr); 256 + errcnt += 1; 257 + if (errcnt > 1000) { 258 + printk(PRINT_PREF "error: too " 259 + "many errors\n"); 260 + return -1; 261 + } 262 + } 263 + } 264 + if (vary_offset) 265 + do_vary_offset(); 266 + } 267 + return err; 268 + } 269 + 270 + static int verify_eraseblock_in_one_go(int ebnum) 271 + { 272 + struct mtd_oob_ops ops; 273 + int err = 0; 274 + loff_t addr = ebnum * mtd->erasesize; 275 + size_t len = mtd->ecclayout->oobavail * pgcnt; 276 + 277 + set_random_data(writebuf, len); 278 + ops.mode = MTD_OOB_AUTO; 279 + ops.len = 0; 280 + ops.retlen = 0; 281 + ops.ooblen = len; 282 + ops.oobretlen = 0; 283 + ops.ooboffs = 0; 284 + ops.datbuf = 0; 285 + ops.oobbuf = readbuf; 286 + err = mtd->read_oob(mtd, addr, &ops); 287 + if (err || ops.oobretlen != len) { 288 + printk(PRINT_PREF "error: readoob failed at %#llx\n", 289 + (long long)addr); 290 + errcnt += 1; 291 + return err ? err : -1; 292 + } 293 + if (memcmp(readbuf, writebuf, len)) { 294 + printk(PRINT_PREF "error: verify failed at %#llx\n", 295 + (long long)addr); 296 + errcnt += 1; 297 + if (errcnt > 1000) { 298 + printk(PRINT_PREF "error: too many errors\n"); 299 + return -1; 300 + } 301 + } 302 + 303 + return err; 304 + } 305 + 306 + static int verify_all_eraseblocks(void) 307 + { 308 + int err; 309 + unsigned int i; 310 + 311 + printk(PRINT_PREF "verifying all eraseblocks\n"); 312 + for (i = 0; i < ebcnt; ++i) { 313 + if (bbt[i]) 314 + continue; 315 + err = verify_eraseblock(i); 316 + if (err) 317 + return err; 318 + if (i % 256 == 0) 319 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 320 + cond_resched(); 321 + } 322 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 323 + return 0; 324 + } 325 + 326 + static int is_block_bad(int ebnum) 327 + { 328 + int ret; 329 + loff_t addr = ebnum * mtd->erasesize; 330 + 331 + ret = mtd->block_isbad(mtd, addr); 332 + if (ret) 333 + printk(PRINT_PREF "block %d is bad\n", ebnum); 334 + return ret; 335 + } 336 + 337 + static int scan_for_bad_eraseblocks(void) 338 + { 339 + int i, bad = 0; 340 + 341 + bbt = kmalloc(ebcnt, GFP_KERNEL); 342 + if (!bbt) { 343 + printk(PRINT_PREF "error: cannot allocate memory\n"); 344 + return -ENOMEM; 345 + } 346 + memset(bbt, 0 , ebcnt); 347 + 348 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 349 + for (i = 0; i < ebcnt; ++i) { 350 + bbt[i] = is_block_bad(i) ? 1 : 0; 351 + if (bbt[i]) 352 + bad += 1; 353 + cond_resched(); 354 + } 355 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 356 + return 0; 357 + } 358 + 359 + static int __init mtd_oobtest_init(void) 360 + { 361 + int err = 0; 362 + unsigned int i; 363 + uint64_t tmp; 364 + struct mtd_oob_ops ops; 365 + loff_t addr = 0, addr0; 366 + 367 + printk(KERN_INFO "\n"); 368 + printk(KERN_INFO "=================================================\n"); 369 + printk(PRINT_PREF "MTD device: %d\n", dev); 370 + 371 + mtd = get_mtd_device(NULL, dev); 372 + if (IS_ERR(mtd)) { 373 + err = PTR_ERR(mtd); 374 + printk(PRINT_PREF "error: cannot get MTD device\n"); 375 + return err; 376 + } 377 + 378 + if (mtd->type != MTD_NANDFLASH) { 379 + printk(PRINT_PREF "this test requires NAND flash\n"); 380 + goto out; 381 + } 382 + 383 + tmp = mtd->size; 384 + do_div(tmp, mtd->erasesize); 385 + ebcnt = tmp; 386 + pgcnt = mtd->erasesize / mtd->writesize; 387 + 388 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 389 + "page size %u, count of eraseblocks %u, pages per " 390 + "eraseblock %u, OOB size %u\n", 391 + (unsigned long long)mtd->size, mtd->erasesize, 392 + mtd->writesize, ebcnt, pgcnt, mtd->oobsize); 393 + 394 + err = -ENOMEM; 395 + mtd->erasesize = mtd->erasesize; 396 + readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); 397 + if (!readbuf) { 398 + printk(PRINT_PREF "error: cannot allocate memory\n"); 399 + goto out; 400 + } 401 + writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); 402 + if (!writebuf) { 403 + printk(PRINT_PREF "error: cannot allocate memory\n"); 404 + goto out; 405 + } 406 + 407 + err = scan_for_bad_eraseblocks(); 408 + if (err) 409 + goto out; 410 + 411 + use_offset = 0; 412 + use_len = mtd->ecclayout->oobavail; 413 + use_len_max = mtd->ecclayout->oobavail; 414 + vary_offset = 0; 415 + 416 + /* First test: write all OOB, read it back and verify */ 417 + printk(PRINT_PREF "test 1 of 5\n"); 418 + 419 + err = erase_whole_device(); 420 + if (err) 421 + goto out; 422 + 423 + simple_srand(1); 424 + err = write_whole_device(); 425 + if (err) 426 + goto out; 427 + 428 + simple_srand(1); 429 + err = verify_all_eraseblocks(); 430 + if (err) 431 + goto out; 432 + 433 + /* 434 + * Second test: write all OOB, a block at a time, read it back and 435 + * verify. 436 + */ 437 + printk(PRINT_PREF "test 2 of 5\n"); 438 + 439 + err = erase_whole_device(); 440 + if (err) 441 + goto out; 442 + 443 + simple_srand(3); 444 + err = write_whole_device(); 445 + if (err) 446 + goto out; 447 + 448 + /* Check all eraseblocks */ 449 + simple_srand(3); 450 + printk(PRINT_PREF "verifying all eraseblocks\n"); 451 + for (i = 0; i < ebcnt; ++i) { 452 + if (bbt[i]) 453 + continue; 454 + err = verify_eraseblock_in_one_go(i); 455 + if (err) 456 + goto out; 457 + if (i % 256 == 0) 458 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 459 + cond_resched(); 460 + } 461 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 462 + 463 + /* 464 + * Third test: write OOB at varying offsets and lengths, read it back 465 + * and verify. 466 + */ 467 + printk(PRINT_PREF "test 3 of 5\n"); 468 + 469 + err = erase_whole_device(); 470 + if (err) 471 + goto out; 472 + 473 + /* Write all eraseblocks */ 474 + use_offset = 0; 475 + use_len = mtd->ecclayout->oobavail; 476 + use_len_max = mtd->ecclayout->oobavail; 477 + vary_offset = 1; 478 + simple_srand(5); 479 + printk(PRINT_PREF "writing OOBs of whole device\n"); 480 + for (i = 0; i < ebcnt; ++i) { 481 + if (bbt[i]) 482 + continue; 483 + err = write_eraseblock(i); 484 + if (err) 485 + goto out; 486 + if (i % 256 == 0) 487 + printk(PRINT_PREF "written up to eraseblock %u\n", i); 488 + cond_resched(); 489 + } 490 + printk(PRINT_PREF "written %u eraseblocks\n", i); 491 + 492 + /* Check all eraseblocks */ 493 + use_offset = 0; 494 + use_len = mtd->ecclayout->oobavail; 495 + use_len_max = mtd->ecclayout->oobavail; 496 + vary_offset = 1; 497 + simple_srand(5); 498 + err = verify_all_eraseblocks(); 499 + if (err) 500 + goto out; 501 + 502 + use_offset = 0; 503 + use_len = mtd->ecclayout->oobavail; 504 + use_len_max = mtd->ecclayout->oobavail; 505 + vary_offset = 0; 506 + 507 + /* Fourth test: try to write off end of device */ 508 + printk(PRINT_PREF "test 4 of 5\n"); 509 + 510 + err = erase_whole_device(); 511 + if (err) 512 + goto out; 513 + 514 + addr0 = 0; 515 + for (i = 0; bbt[i] && i < ebcnt; ++i) 516 + addr0 += mtd->erasesize; 517 + 518 + /* Attempt to write off end of OOB */ 519 + ops.mode = MTD_OOB_AUTO; 520 + ops.len = 0; 521 + ops.retlen = 0; 522 + ops.ooblen = 1; 523 + ops.oobretlen = 0; 524 + ops.ooboffs = mtd->ecclayout->oobavail; 525 + ops.datbuf = 0; 526 + ops.oobbuf = writebuf; 527 + printk(PRINT_PREF "attempting to start write past end of OOB\n"); 528 + printk(PRINT_PREF "an error is expected...\n"); 529 + err = mtd->write_oob(mtd, addr0, &ops); 530 + if (err) { 531 + printk(PRINT_PREF "error occurred as expected\n"); 532 + err = 0; 533 + } else { 534 + printk(PRINT_PREF "error: can write past end of OOB\n"); 535 + errcnt += 1; 536 + } 537 + 538 + /* Attempt to read off end of OOB */ 539 + ops.mode = MTD_OOB_AUTO; 540 + ops.len = 0; 541 + ops.retlen = 0; 542 + ops.ooblen = 1; 543 + ops.oobretlen = 0; 544 + ops.ooboffs = mtd->ecclayout->oobavail; 545 + ops.datbuf = 0; 546 + ops.oobbuf = readbuf; 547 + printk(PRINT_PREF "attempting to start read past end of OOB\n"); 548 + printk(PRINT_PREF "an error is expected...\n"); 549 + err = mtd->read_oob(mtd, addr0, &ops); 550 + if (err) { 551 + printk(PRINT_PREF "error occurred as expected\n"); 552 + err = 0; 553 + } else { 554 + printk(PRINT_PREF "error: can read past end of OOB\n"); 555 + errcnt += 1; 556 + } 557 + 558 + if (bbt[ebcnt - 1]) 559 + printk(PRINT_PREF "skipping end of device tests because last " 560 + "block is bad\n"); 561 + else { 562 + /* Attempt to write off end of device */ 563 + ops.mode = MTD_OOB_AUTO; 564 + ops.len = 0; 565 + ops.retlen = 0; 566 + ops.ooblen = mtd->ecclayout->oobavail + 1; 567 + ops.oobretlen = 0; 568 + ops.ooboffs = 0; 569 + ops.datbuf = 0; 570 + ops.oobbuf = writebuf; 571 + printk(PRINT_PREF "attempting to write past end of device\n"); 572 + printk(PRINT_PREF "an error is expected...\n"); 573 + err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops); 574 + if (err) { 575 + printk(PRINT_PREF "error occurred as expected\n"); 576 + err = 0; 577 + } else { 578 + printk(PRINT_PREF "error: wrote past end of device\n"); 579 + errcnt += 1; 580 + } 581 + 582 + /* Attempt to read off end of device */ 583 + ops.mode = MTD_OOB_AUTO; 584 + ops.len = 0; 585 + ops.retlen = 0; 586 + ops.ooblen = mtd->ecclayout->oobavail + 1; 587 + ops.oobretlen = 0; 588 + ops.ooboffs = 0; 589 + ops.datbuf = 0; 590 + ops.oobbuf = readbuf; 591 + printk(PRINT_PREF "attempting to read past end of device\n"); 592 + printk(PRINT_PREF "an error is expected...\n"); 593 + err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops); 594 + if (err) { 595 + printk(PRINT_PREF "error occurred as expected\n"); 596 + err = 0; 597 + } else { 598 + printk(PRINT_PREF "error: read past end of device\n"); 599 + errcnt += 1; 600 + } 601 + 602 + err = erase_eraseblock(ebcnt - 1); 603 + if (err) 604 + goto out; 605 + 606 + /* Attempt to write off end of device */ 607 + ops.mode = MTD_OOB_AUTO; 608 + ops.len = 0; 609 + ops.retlen = 0; 610 + ops.ooblen = mtd->ecclayout->oobavail; 611 + ops.oobretlen = 0; 612 + ops.ooboffs = 1; 613 + ops.datbuf = 0; 614 + ops.oobbuf = writebuf; 615 + printk(PRINT_PREF "attempting to write past end of device\n"); 616 + printk(PRINT_PREF "an error is expected...\n"); 617 + err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops); 618 + if (err) { 619 + printk(PRINT_PREF "error occurred as expected\n"); 620 + err = 0; 621 + } else { 622 + printk(PRINT_PREF "error: wrote past end of device\n"); 623 + errcnt += 1; 624 + } 625 + 626 + /* Attempt to read off end of device */ 627 + ops.mode = MTD_OOB_AUTO; 628 + ops.len = 0; 629 + ops.retlen = 0; 630 + ops.ooblen = mtd->ecclayout->oobavail; 631 + ops.oobretlen = 0; 632 + ops.ooboffs = 1; 633 + ops.datbuf = 0; 634 + ops.oobbuf = readbuf; 635 + printk(PRINT_PREF "attempting to read past end of device\n"); 636 + printk(PRINT_PREF "an error is expected...\n"); 637 + err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops); 638 + if (err) { 639 + printk(PRINT_PREF "error occurred as expected\n"); 640 + err = 0; 641 + } else { 642 + printk(PRINT_PREF "error: read past end of device\n"); 643 + errcnt += 1; 644 + } 645 + } 646 + 647 + /* Fifth test: write / read across block boundaries */ 648 + printk(PRINT_PREF "test 5 of 5\n"); 649 + 650 + /* Erase all eraseblocks */ 651 + err = erase_whole_device(); 652 + if (err) 653 + goto out; 654 + 655 + /* Write all eraseblocks */ 656 + simple_srand(11); 657 + printk(PRINT_PREF "writing OOBs of whole device\n"); 658 + for (i = 0; i < ebcnt - 1; ++i) { 659 + int cnt = 2; 660 + int pg; 661 + size_t sz = mtd->ecclayout->oobavail; 662 + if (bbt[i] || bbt[i + 1]) 663 + continue; 664 + addr = (i + 1) * mtd->erasesize - mtd->writesize; 665 + for (pg = 0; pg < cnt; ++pg) { 666 + set_random_data(writebuf, sz); 667 + ops.mode = MTD_OOB_AUTO; 668 + ops.len = 0; 669 + ops.retlen = 0; 670 + ops.ooblen = sz; 671 + ops.oobretlen = 0; 672 + ops.ooboffs = 0; 673 + ops.datbuf = 0; 674 + ops.oobbuf = writebuf; 675 + err = mtd->write_oob(mtd, addr, &ops); 676 + if (err) 677 + goto out; 678 + if (i % 256 == 0) 679 + printk(PRINT_PREF "written up to eraseblock " 680 + "%u\n", i); 681 + cond_resched(); 682 + addr += mtd->writesize; 683 + } 684 + } 685 + printk(PRINT_PREF "written %u eraseblocks\n", i); 686 + 687 + /* Check all eraseblocks */ 688 + simple_srand(11); 689 + printk(PRINT_PREF "verifying all eraseblocks\n"); 690 + for (i = 0; i < ebcnt - 1; ++i) { 691 + if (bbt[i] || bbt[i + 1]) 692 + continue; 693 + set_random_data(writebuf, mtd->ecclayout->oobavail * 2); 694 + addr = (i + 1) * mtd->erasesize - mtd->writesize; 695 + ops.mode = MTD_OOB_AUTO; 696 + ops.len = 0; 697 + ops.retlen = 0; 698 + ops.ooblen = mtd->ecclayout->oobavail * 2; 699 + ops.oobretlen = 0; 700 + ops.ooboffs = 0; 701 + ops.datbuf = 0; 702 + ops.oobbuf = readbuf; 703 + err = mtd->read_oob(mtd, addr, &ops); 704 + if (err) 705 + goto out; 706 + if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { 707 + printk(PRINT_PREF "error: verify failed at %#llx\n", 708 + (long long)addr); 709 + errcnt += 1; 710 + if (errcnt > 1000) { 711 + printk(PRINT_PREF "error: too many errors\n"); 712 + goto out; 713 + } 714 + } 715 + if (i % 256 == 0) 716 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 717 + cond_resched(); 718 + } 719 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 720 + 721 + printk(PRINT_PREF "finished with %d errors\n", errcnt); 722 + out: 723 + kfree(bbt); 724 + kfree(writebuf); 725 + kfree(readbuf); 726 + put_mtd_device(mtd); 727 + if (err) 728 + printk(PRINT_PREF "error %d occurred\n", err); 729 + printk(KERN_INFO "=================================================\n"); 730 + return err; 731 + } 732 + module_init(mtd_oobtest_init); 733 + 734 + static void __exit mtd_oobtest_exit(void) 735 + { 736 + return; 737 + } 738 + module_exit(mtd_oobtest_exit); 739 + 740 + MODULE_DESCRIPTION("Out-of-band test module"); 741 + MODULE_AUTHOR("Adrian Hunter"); 742 + MODULE_LICENSE("GPL");
+632
drivers/mtd/tests/mtd_pagetest.c
··· 1 + /* 2 + * Copyright (C) 2006-2008 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Test page read and write on MTD device. 18 + * 19 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20 + */ 21 + 22 + #include <asm/div64.h> 23 + #include <linux/init.h> 24 + #include <linux/module.h> 25 + #include <linux/moduleparam.h> 26 + #include <linux/err.h> 27 + #include <linux/mtd/mtd.h> 28 + #include <linux/sched.h> 29 + 30 + #define PRINT_PREF KERN_INFO "mtd_pagetest: " 31 + 32 + static int dev; 33 + module_param(dev, int, S_IRUGO); 34 + MODULE_PARM_DESC(dev, "MTD device number to use"); 35 + 36 + static struct mtd_info *mtd; 37 + static unsigned char *twopages; 38 + static unsigned char *writebuf; 39 + static unsigned char *boundary; 40 + static unsigned char *bbt; 41 + 42 + static int pgsize; 43 + static int bufsize; 44 + static int ebcnt; 45 + static int pgcnt; 46 + static int errcnt; 47 + static unsigned long next = 1; 48 + 49 + static inline unsigned int simple_rand(void) 50 + { 51 + next = next * 1103515245 + 12345; 52 + return (unsigned int)((next / 65536) % 32768); 53 + } 54 + 55 + static inline void simple_srand(unsigned long seed) 56 + { 57 + next = seed; 58 + } 59 + 60 + static void set_random_data(unsigned char *buf, size_t len) 61 + { 62 + size_t i; 63 + 64 + for (i = 0; i < len; ++i) 65 + buf[i] = simple_rand(); 66 + } 67 + 68 + static int erase_eraseblock(int ebnum) 69 + { 70 + int err; 71 + struct erase_info ei; 72 + loff_t addr = ebnum * mtd->erasesize; 73 + 74 + memset(&ei, 0, sizeof(struct erase_info)); 75 + ei.mtd = mtd; 76 + ei.addr = addr; 77 + ei.len = mtd->erasesize; 78 + 79 + err = mtd->erase(mtd, &ei); 80 + if (err) { 81 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 82 + return err; 83 + } 84 + 85 + if (ei.state == MTD_ERASE_FAILED) { 86 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 87 + ebnum); 88 + return -EIO; 89 + } 90 + 91 + return 0; 92 + } 93 + 94 + static int write_eraseblock(int ebnum) 95 + { 96 + int err = 0; 97 + size_t written = 0; 98 + loff_t addr = ebnum * mtd->erasesize; 99 + 100 + set_random_data(writebuf, mtd->erasesize); 101 + cond_resched(); 102 + err = mtd->write(mtd, addr, mtd->erasesize, &written, writebuf); 103 + if (err || written != mtd->erasesize) 104 + printk(PRINT_PREF "error: write failed at %#llx\n", 105 + (long long)addr); 106 + 107 + return err; 108 + } 109 + 110 + static int verify_eraseblock(int ebnum) 111 + { 112 + uint32_t j; 113 + size_t read = 0; 114 + int err = 0, i; 115 + loff_t addr0, addrn; 116 + loff_t addr = ebnum * mtd->erasesize; 117 + 118 + addr0 = 0; 119 + for (i = 0; bbt[i] && i < ebcnt; ++i) 120 + addr0 += mtd->erasesize; 121 + 122 + addrn = mtd->size; 123 + for (i = 0; bbt[ebcnt - i - 1] && i < ebcnt; ++i) 124 + addrn -= mtd->erasesize; 125 + 126 + set_random_data(writebuf, mtd->erasesize); 127 + for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { 128 + /* Do a read to set the internal dataRAMs to different data */ 129 + err = mtd->read(mtd, addr0, bufsize, &read, twopages); 130 + if (err == -EUCLEAN) 131 + err = 0; 132 + if (err || read != bufsize) { 133 + printk(PRINT_PREF "error: read failed at %#llx\n", 134 + (long long)addr0); 135 + return err; 136 + } 137 + err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); 138 + if (err == -EUCLEAN) 139 + err = 0; 140 + if (err || read != bufsize) { 141 + printk(PRINT_PREF "error: read failed at %#llx\n", 142 + (long long)(addrn - bufsize)); 143 + return err; 144 + } 145 + memset(twopages, 0, bufsize); 146 + read = 0; 147 + err = mtd->read(mtd, addr, bufsize, &read, twopages); 148 + if (err == -EUCLEAN) 149 + err = 0; 150 + if (err || read != bufsize) { 151 + printk(PRINT_PREF "error: read failed at %#llx\n", 152 + (long long)addr); 153 + break; 154 + } 155 + if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { 156 + printk(PRINT_PREF "error: verify failed at %#llx\n", 157 + (long long)addr); 158 + errcnt += 1; 159 + } 160 + } 161 + /* Check boundary between eraseblocks */ 162 + if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) { 163 + unsigned long oldnext = next; 164 + /* Do a read to set the internal dataRAMs to different data */ 165 + err = mtd->read(mtd, addr0, bufsize, &read, twopages); 166 + if (err == -EUCLEAN) 167 + err = 0; 168 + if (err || read != bufsize) { 169 + printk(PRINT_PREF "error: read failed at %#llx\n", 170 + (long long)addr0); 171 + return err; 172 + } 173 + err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); 174 + if (err == -EUCLEAN) 175 + err = 0; 176 + if (err || read != bufsize) { 177 + printk(PRINT_PREF "error: read failed at %#llx\n", 178 + (long long)(addrn - bufsize)); 179 + return err; 180 + } 181 + memset(twopages, 0, bufsize); 182 + read = 0; 183 + err = mtd->read(mtd, addr, bufsize, &read, twopages); 184 + if (err == -EUCLEAN) 185 + err = 0; 186 + if (err || read != bufsize) { 187 + printk(PRINT_PREF "error: read failed at %#llx\n", 188 + (long long)addr); 189 + return err; 190 + } 191 + memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); 192 + set_random_data(boundary + pgsize, pgsize); 193 + if (memcmp(twopages, boundary, bufsize)) { 194 + printk(PRINT_PREF "error: verify failed at %#llx\n", 195 + (long long)addr); 196 + errcnt += 1; 197 + } 198 + next = oldnext; 199 + } 200 + return err; 201 + } 202 + 203 + static int crosstest(void) 204 + { 205 + size_t read = 0; 206 + int err = 0, i; 207 + loff_t addr, addr0, addrn; 208 + unsigned char *pp1, *pp2, *pp3, *pp4; 209 + 210 + printk(PRINT_PREF "crosstest\n"); 211 + pp1 = kmalloc(pgsize * 4, GFP_KERNEL); 212 + if (!pp1) { 213 + printk(PRINT_PREF "error: cannot allocate memory\n"); 214 + return -ENOMEM; 215 + } 216 + pp2 = pp1 + pgsize; 217 + pp3 = pp2 + pgsize; 218 + pp4 = pp3 + pgsize; 219 + memset(pp1, 0, pgsize * 4); 220 + 221 + addr0 = 0; 222 + for (i = 0; bbt[i] && i < ebcnt; ++i) 223 + addr0 += mtd->erasesize; 224 + 225 + addrn = mtd->size; 226 + for (i = 0; bbt[ebcnt - i - 1] && i < ebcnt; ++i) 227 + addrn -= mtd->erasesize; 228 + 229 + /* Read 2nd-to-last page to pp1 */ 230 + read = 0; 231 + addr = addrn - pgsize - pgsize; 232 + err = mtd->read(mtd, addr, pgsize, &read, pp1); 233 + if (err == -EUCLEAN) 234 + err = 0; 235 + if (err || read != pgsize) { 236 + printk(PRINT_PREF "error: read failed at %#llx\n", 237 + (long long)addr); 238 + kfree(pp1); 239 + return err; 240 + } 241 + 242 + /* Read 3rd-to-last page to pp1 */ 243 + read = 0; 244 + addr = addrn - pgsize - pgsize - pgsize; 245 + err = mtd->read(mtd, addr, pgsize, &read, pp1); 246 + if (err == -EUCLEAN) 247 + err = 0; 248 + if (err || read != pgsize) { 249 + printk(PRINT_PREF "error: read failed at %#llx\n", 250 + (long long)addr); 251 + kfree(pp1); 252 + return err; 253 + } 254 + 255 + /* Read first page to pp2 */ 256 + read = 0; 257 + addr = addr0; 258 + printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 259 + err = mtd->read(mtd, addr, pgsize, &read, pp2); 260 + if (err == -EUCLEAN) 261 + err = 0; 262 + if (err || read != pgsize) { 263 + printk(PRINT_PREF "error: read failed at %#llx\n", 264 + (long long)addr); 265 + kfree(pp1); 266 + return err; 267 + } 268 + 269 + /* Read last page to pp3 */ 270 + read = 0; 271 + addr = addrn - pgsize; 272 + printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 273 + err = mtd->read(mtd, addr, pgsize, &read, pp3); 274 + if (err == -EUCLEAN) 275 + err = 0; 276 + if (err || read != pgsize) { 277 + printk(PRINT_PREF "error: read failed at %#llx\n", 278 + (long long)addr); 279 + kfree(pp1); 280 + return err; 281 + } 282 + 283 + /* Read first page again to pp4 */ 284 + read = 0; 285 + addr = addr0; 286 + printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 287 + err = mtd->read(mtd, addr, pgsize, &read, pp4); 288 + if (err == -EUCLEAN) 289 + err = 0; 290 + if (err || read != pgsize) { 291 + printk(PRINT_PREF "error: read failed at %#llx\n", 292 + (long long)addr); 293 + kfree(pp1); 294 + return err; 295 + } 296 + 297 + /* pp2 and pp4 should be the same */ 298 + printk(PRINT_PREF "verifying pages read at %#llx match\n", 299 + (long long)addr0); 300 + if (memcmp(pp2, pp4, pgsize)) { 301 + printk(PRINT_PREF "verify failed!\n"); 302 + errcnt += 1; 303 + } else if (!err) 304 + printk(PRINT_PREF "crosstest ok\n"); 305 + kfree(pp1); 306 + return err; 307 + } 308 + 309 + static int erasecrosstest(void) 310 + { 311 + size_t read = 0, written = 0; 312 + int err = 0, i, ebnum, ok = 1, ebnum2; 313 + loff_t addr0; 314 + char *readbuf = twopages; 315 + 316 + printk(PRINT_PREF "erasecrosstest\n"); 317 + 318 + ebnum = 0; 319 + addr0 = 0; 320 + for (i = 0; bbt[i] && i < ebcnt; ++i) { 321 + addr0 += mtd->erasesize; 322 + ebnum += 1; 323 + } 324 + 325 + ebnum2 = ebcnt - 1; 326 + while (ebnum2 && bbt[ebnum2]) 327 + ebnum2 -= 1; 328 + 329 + printk(PRINT_PREF "erasing block %d\n", ebnum); 330 + err = erase_eraseblock(ebnum); 331 + if (err) 332 + return err; 333 + 334 + printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 335 + set_random_data(writebuf, pgsize); 336 + strcpy(writebuf, "There is no data like this!"); 337 + err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 338 + if (err || written != pgsize) { 339 + printk(PRINT_PREF "error: write failed at %#llx\n", 340 + (long long)addr0); 341 + return err ? err : -1; 342 + } 343 + 344 + printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 345 + memset(readbuf, 0, pgsize); 346 + err = mtd->read(mtd, addr0, pgsize, &read, readbuf); 347 + if (err == -EUCLEAN) 348 + err = 0; 349 + if (err || read != pgsize) { 350 + printk(PRINT_PREF "error: read failed at %#llx\n", 351 + (long long)addr0); 352 + return err ? err : -1; 353 + } 354 + 355 + printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); 356 + if (memcmp(writebuf, readbuf, pgsize)) { 357 + printk(PRINT_PREF "verify failed!\n"); 358 + errcnt += 1; 359 + ok = 0; 360 + return err; 361 + } 362 + 363 + printk(PRINT_PREF "erasing block %d\n", ebnum); 364 + err = erase_eraseblock(ebnum); 365 + if (err) 366 + return err; 367 + 368 + printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 369 + set_random_data(writebuf, pgsize); 370 + strcpy(writebuf, "There is no data like this!"); 371 + err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 372 + if (err || written != pgsize) { 373 + printk(PRINT_PREF "error: write failed at %#llx\n", 374 + (long long)addr0); 375 + return err ? err : -1; 376 + } 377 + 378 + printk(PRINT_PREF "erasing block %d\n", ebnum2); 379 + err = erase_eraseblock(ebnum2); 380 + if (err) 381 + return err; 382 + 383 + printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 384 + memset(readbuf, 0, pgsize); 385 + err = mtd->read(mtd, addr0, pgsize, &read, readbuf); 386 + if (err == -EUCLEAN) 387 + err = 0; 388 + if (err || read != pgsize) { 389 + printk(PRINT_PREF "error: read failed at %#llx\n", 390 + (long long)addr0); 391 + return err ? err : -1; 392 + } 393 + 394 + printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); 395 + if (memcmp(writebuf, readbuf, pgsize)) { 396 + printk(PRINT_PREF "verify failed!\n"); 397 + errcnt += 1; 398 + ok = 0; 399 + } 400 + 401 + if (ok && !err) 402 + printk(PRINT_PREF "erasecrosstest ok\n"); 403 + return err; 404 + } 405 + 406 + static int erasetest(void) 407 + { 408 + size_t read = 0, written = 0; 409 + int err = 0, i, ebnum, ok = 1; 410 + loff_t addr0; 411 + 412 + printk(PRINT_PREF "erasetest\n"); 413 + 414 + ebnum = 0; 415 + addr0 = 0; 416 + for (i = 0; bbt[i] && i < ebcnt; ++i) { 417 + addr0 += mtd->erasesize; 418 + ebnum += 1; 419 + } 420 + 421 + printk(PRINT_PREF "erasing block %d\n", ebnum); 422 + err = erase_eraseblock(ebnum); 423 + if (err) 424 + return err; 425 + 426 + printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 427 + set_random_data(writebuf, pgsize); 428 + err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 429 + if (err || written != pgsize) { 430 + printk(PRINT_PREF "error: write failed at %#llx\n", 431 + (long long)addr0); 432 + return err ? err : -1; 433 + } 434 + 435 + printk(PRINT_PREF "erasing block %d\n", ebnum); 436 + err = erase_eraseblock(ebnum); 437 + if (err) 438 + return err; 439 + 440 + printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 441 + err = mtd->read(mtd, addr0, pgsize, &read, twopages); 442 + if (err == -EUCLEAN) 443 + err = 0; 444 + if (err || read != pgsize) { 445 + printk(PRINT_PREF "error: read failed at %#llx\n", 446 + (long long)addr0); 447 + return err ? err : -1; 448 + } 449 + 450 + printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n", 451 + ebnum); 452 + for (i = 0; i < pgsize; ++i) 453 + if (twopages[i] != 0xff) { 454 + printk(PRINT_PREF "verifying all 0xff failed at %d\n", 455 + i); 456 + errcnt += 1; 457 + ok = 0; 458 + break; 459 + } 460 + 461 + if (ok && !err) 462 + printk(PRINT_PREF "erasetest ok\n"); 463 + 464 + return err; 465 + } 466 + 467 + static int is_block_bad(int ebnum) 468 + { 469 + loff_t addr = ebnum * mtd->erasesize; 470 + int ret; 471 + 472 + ret = mtd->block_isbad(mtd, addr); 473 + if (ret) 474 + printk(PRINT_PREF "block %d is bad\n", ebnum); 475 + return ret; 476 + } 477 + 478 + static int scan_for_bad_eraseblocks(void) 479 + { 480 + int i, bad = 0; 481 + 482 + bbt = kmalloc(ebcnt, GFP_KERNEL); 483 + if (!bbt) { 484 + printk(PRINT_PREF "error: cannot allocate memory\n"); 485 + return -ENOMEM; 486 + } 487 + memset(bbt, 0 , ebcnt); 488 + 489 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 490 + for (i = 0; i < ebcnt; ++i) { 491 + bbt[i] = is_block_bad(i) ? 1 : 0; 492 + if (bbt[i]) 493 + bad += 1; 494 + cond_resched(); 495 + } 496 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 497 + return 0; 498 + } 499 + 500 + static int __init mtd_pagetest_init(void) 501 + { 502 + int err = 0; 503 + uint64_t tmp; 504 + uint32_t i; 505 + 506 + printk(KERN_INFO "\n"); 507 + printk(KERN_INFO "=================================================\n"); 508 + printk(PRINT_PREF "MTD device: %d\n", dev); 509 + 510 + mtd = get_mtd_device(NULL, dev); 511 + if (IS_ERR(mtd)) { 512 + err = PTR_ERR(mtd); 513 + printk(PRINT_PREF "error: cannot get MTD device\n"); 514 + return err; 515 + } 516 + 517 + if (mtd->type != MTD_NANDFLASH) { 518 + printk(PRINT_PREF "this test requires NAND flash\n"); 519 + goto out; 520 + } 521 + 522 + tmp = mtd->size; 523 + do_div(tmp, mtd->erasesize); 524 + ebcnt = tmp; 525 + pgcnt = mtd->erasesize / mtd->writesize; 526 + 527 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 528 + "page size %u, count of eraseblocks %u, pages per " 529 + "eraseblock %u, OOB size %u\n", 530 + (unsigned long long)mtd->size, mtd->erasesize, 531 + pgsize, ebcnt, pgcnt, mtd->oobsize); 532 + 533 + err = -ENOMEM; 534 + bufsize = pgsize * 2; 535 + writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); 536 + if (!writebuf) { 537 + printk(PRINT_PREF "error: cannot allocate memory\n"); 538 + goto out; 539 + } 540 + twopages = kmalloc(bufsize, GFP_KERNEL); 541 + if (!twopages) { 542 + printk(PRINT_PREF "error: cannot allocate memory\n"); 543 + goto out; 544 + } 545 + boundary = kmalloc(bufsize, GFP_KERNEL); 546 + if (!boundary) { 547 + printk(PRINT_PREF "error: cannot allocate memory\n"); 548 + goto out; 549 + } 550 + 551 + err = scan_for_bad_eraseblocks(); 552 + if (err) 553 + goto out; 554 + 555 + /* Erase all eraseblocks */ 556 + printk(PRINT_PREF "erasing whole device\n"); 557 + for (i = 0; i < ebcnt; ++i) { 558 + if (bbt[i]) 559 + continue; 560 + err = erase_eraseblock(i); 561 + if (err) 562 + goto out; 563 + cond_resched(); 564 + } 565 + printk(PRINT_PREF "erased %u eraseblocks\n", i); 566 + 567 + /* Write all eraseblocks */ 568 + simple_srand(1); 569 + printk(PRINT_PREF "writing whole device\n"); 570 + for (i = 0; i < ebcnt; ++i) { 571 + if (bbt[i]) 572 + continue; 573 + err = write_eraseblock(i); 574 + if (err) 575 + goto out; 576 + if (i % 256 == 0) 577 + printk(PRINT_PREF "written up to eraseblock %u\n", i); 578 + cond_resched(); 579 + } 580 + printk(PRINT_PREF "written %u eraseblocks\n", i); 581 + 582 + /* Check all eraseblocks */ 583 + simple_srand(1); 584 + printk(PRINT_PREF "verifying all eraseblocks\n"); 585 + for (i = 0; i < ebcnt; ++i) { 586 + if (bbt[i]) 587 + continue; 588 + err = verify_eraseblock(i); 589 + if (err) 590 + goto out; 591 + if (i % 256 == 0) 592 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 593 + cond_resched(); 594 + } 595 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 596 + 597 + err = crosstest(); 598 + if (err) 599 + goto out; 600 + 601 + err = erasecrosstest(); 602 + if (err) 603 + goto out; 604 + 605 + err = erasetest(); 606 + if (err) 607 + goto out; 608 + 609 + printk(PRINT_PREF "finished with %d errors\n", errcnt); 610 + out: 611 + 612 + kfree(bbt); 613 + kfree(boundary); 614 + kfree(twopages); 615 + kfree(writebuf); 616 + put_mtd_device(mtd); 617 + if (err) 618 + printk(PRINT_PREF "error %d occurred\n", err); 619 + printk(KERN_INFO "=================================================\n"); 620 + return err; 621 + } 622 + module_init(mtd_pagetest_init); 623 + 624 + static void __exit mtd_pagetest_exit(void) 625 + { 626 + return; 627 + } 628 + module_exit(mtd_pagetest_exit); 629 + 630 + MODULE_DESCRIPTION("NAND page test"); 631 + MODULE_AUTHOR("Adrian Hunter"); 632 + MODULE_LICENSE("GPL");
+253
drivers/mtd/tests/mtd_readtest.c
··· 1 + /* 2 + * Copyright (C) 2006-2008 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Check MTD device read. 18 + * 19 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20 + */ 21 + 22 + #include <linux/init.h> 23 + #include <linux/module.h> 24 + #include <linux/moduleparam.h> 25 + #include <linux/err.h> 26 + #include <linux/mtd/mtd.h> 27 + #include <linux/sched.h> 28 + 29 + #define PRINT_PREF KERN_INFO "mtd_readtest: " 30 + 31 + static int dev; 32 + module_param(dev, int, S_IRUGO); 33 + MODULE_PARM_DESC(dev, "MTD device number to use"); 34 + 35 + static struct mtd_info *mtd; 36 + static unsigned char *iobuf; 37 + static unsigned char *iobuf1; 38 + static unsigned char *bbt; 39 + 40 + static int pgsize; 41 + static int ebcnt; 42 + static int pgcnt; 43 + 44 + static int read_eraseblock_by_page(int ebnum) 45 + { 46 + size_t read = 0; 47 + int i, ret, err = 0; 48 + loff_t addr = ebnum * mtd->erasesize; 49 + void *buf = iobuf; 50 + void *oobbuf = iobuf1; 51 + 52 + for (i = 0; i < pgcnt; i++) { 53 + memset(buf, 0 , pgcnt); 54 + ret = mtd->read(mtd, addr, pgsize, &read, buf); 55 + if (ret == -EUCLEAN) 56 + ret = 0; 57 + if (ret || read != pgsize) { 58 + printk(PRINT_PREF "error: read failed at %#llx\n", 59 + (long long)addr); 60 + if (!err) 61 + err = ret; 62 + if (!err) 63 + err = -EINVAL; 64 + } 65 + if (mtd->oobsize) { 66 + struct mtd_oob_ops ops; 67 + 68 + ops.mode = MTD_OOB_PLACE; 69 + ops.len = 0; 70 + ops.retlen = 0; 71 + ops.ooblen = mtd->oobsize; 72 + ops.oobretlen = 0; 73 + ops.ooboffs = 0; 74 + ops.datbuf = 0; 75 + ops.oobbuf = oobbuf; 76 + ret = mtd->read_oob(mtd, addr, &ops); 77 + if (ret || ops.oobretlen != mtd->oobsize) { 78 + printk(PRINT_PREF "error: read oob failed at " 79 + "%#llx\n", (long long)addr); 80 + if (!err) 81 + err = ret; 82 + if (!err) 83 + err = -EINVAL; 84 + } 85 + oobbuf += mtd->oobsize; 86 + } 87 + addr += pgsize; 88 + buf += pgsize; 89 + } 90 + 91 + return err; 92 + } 93 + 94 + static void dump_eraseblock(int ebnum) 95 + { 96 + int i, j, n; 97 + char line[128]; 98 + int pg, oob; 99 + 100 + printk(PRINT_PREF "dumping eraseblock %d\n", ebnum); 101 + n = mtd->erasesize; 102 + for (i = 0; i < n;) { 103 + char *p = line; 104 + 105 + p += sprintf(p, "%05x: ", i); 106 + for (j = 0; j < 32 && i < n; j++, i++) 107 + p += sprintf(p, "%02x", (unsigned int)iobuf[i]); 108 + printk(KERN_CRIT "%s\n", line); 109 + cond_resched(); 110 + } 111 + if (!mtd->oobsize) 112 + return; 113 + printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum); 114 + n = mtd->oobsize; 115 + for (pg = 0, i = 0; pg < pgcnt; pg++) 116 + for (oob = 0; oob < n;) { 117 + char *p = line; 118 + 119 + p += sprintf(p, "%05x: ", i); 120 + for (j = 0; j < 32 && oob < n; j++, oob++, i++) 121 + p += sprintf(p, "%02x", 122 + (unsigned int)iobuf1[i]); 123 + printk(KERN_CRIT "%s\n", line); 124 + cond_resched(); 125 + } 126 + } 127 + 128 + static int is_block_bad(int ebnum) 129 + { 130 + loff_t addr = ebnum * mtd->erasesize; 131 + int ret; 132 + 133 + ret = mtd->block_isbad(mtd, addr); 134 + if (ret) 135 + printk(PRINT_PREF "block %d is bad\n", ebnum); 136 + return ret; 137 + } 138 + 139 + static int scan_for_bad_eraseblocks(void) 140 + { 141 + int i, bad = 0; 142 + 143 + bbt = kmalloc(ebcnt, GFP_KERNEL); 144 + if (!bbt) { 145 + printk(PRINT_PREF "error: cannot allocate memory\n"); 146 + return -ENOMEM; 147 + } 148 + memset(bbt, 0 , ebcnt); 149 + 150 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 151 + for (i = 0; i < ebcnt; ++i) { 152 + bbt[i] = is_block_bad(i) ? 1 : 0; 153 + if (bbt[i]) 154 + bad += 1; 155 + cond_resched(); 156 + } 157 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 158 + return 0; 159 + } 160 + 161 + static int __init mtd_readtest_init(void) 162 + { 163 + uint64_t tmp; 164 + int err, i; 165 + 166 + printk(KERN_INFO "\n"); 167 + printk(KERN_INFO "=================================================\n"); 168 + printk(PRINT_PREF "MTD device: %d\n", dev); 169 + 170 + mtd = get_mtd_device(NULL, dev); 171 + if (IS_ERR(mtd)) { 172 + err = PTR_ERR(mtd); 173 + printk(PRINT_PREF "error: Cannot get MTD device\n"); 174 + return err; 175 + } 176 + 177 + if (mtd->writesize == 1) { 178 + printk(PRINT_PREF "not NAND flash, assume page size is 512 " 179 + "bytes.\n"); 180 + pgsize = 512; 181 + } else 182 + pgsize = mtd->writesize; 183 + 184 + tmp = mtd->size; 185 + do_div(tmp, mtd->erasesize); 186 + ebcnt = tmp; 187 + pgcnt = mtd->erasesize / mtd->writesize; 188 + 189 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 190 + "page size %u, count of eraseblocks %u, pages per " 191 + "eraseblock %u, OOB size %u\n", 192 + (unsigned long long)mtd->size, mtd->erasesize, 193 + pgsize, ebcnt, pgcnt, mtd->oobsize); 194 + 195 + err = -ENOMEM; 196 + iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); 197 + if (!iobuf) { 198 + printk(PRINT_PREF "error: cannot allocate memory\n"); 199 + goto out; 200 + } 201 + iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); 202 + if (!iobuf1) { 203 + printk(PRINT_PREF "error: cannot allocate memory\n"); 204 + goto out; 205 + } 206 + 207 + err = scan_for_bad_eraseblocks(); 208 + if (err) 209 + goto out; 210 + 211 + /* Read all eraseblocks 1 page at a time */ 212 + printk(PRINT_PREF "testing page read\n"); 213 + for (i = 0; i < ebcnt; ++i) { 214 + int ret; 215 + 216 + if (bbt[i]) 217 + continue; 218 + ret = read_eraseblock_by_page(i); 219 + if (ret) { 220 + dump_eraseblock(i); 221 + if (!err) 222 + err = ret; 223 + } 224 + cond_resched(); 225 + } 226 + 227 + if (err) 228 + printk(PRINT_PREF "finished with errors\n"); 229 + else 230 + printk(PRINT_PREF "finished\n"); 231 + 232 + out: 233 + 234 + kfree(iobuf); 235 + kfree(iobuf1); 236 + kfree(bbt); 237 + put_mtd_device(mtd); 238 + if (err) 239 + printk(PRINT_PREF "error %d occurred\n", err); 240 + printk(KERN_INFO "=================================================\n"); 241 + return err; 242 + } 243 + module_init(mtd_readtest_init); 244 + 245 + static void __exit mtd_readtest_exit(void) 246 + { 247 + return; 248 + } 249 + module_exit(mtd_readtest_exit); 250 + 251 + MODULE_DESCRIPTION("Read test module"); 252 + MODULE_AUTHOR("Adrian Hunter"); 253 + MODULE_LICENSE("GPL");
+502
drivers/mtd/tests/mtd_speedtest.c
··· 1 + /* 2 + * Copyright (C) 2007 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Test read and write speed of a MTD device. 18 + * 19 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20 + */ 21 + 22 + #include <linux/init.h> 23 + #include <linux/module.h> 24 + #include <linux/moduleparam.h> 25 + #include <linux/err.h> 26 + #include <linux/mtd/mtd.h> 27 + #include <linux/sched.h> 28 + 29 + #define PRINT_PREF KERN_INFO "mtd_speedtest: " 30 + 31 + static int dev; 32 + module_param(dev, int, S_IRUGO); 33 + MODULE_PARM_DESC(dev, "MTD device number to use"); 34 + 35 + static struct mtd_info *mtd; 36 + static unsigned char *iobuf; 37 + static unsigned char *bbt; 38 + 39 + static int pgsize; 40 + static int ebcnt; 41 + static int pgcnt; 42 + static int goodebcnt; 43 + static struct timeval start, finish; 44 + static unsigned long next = 1; 45 + 46 + static inline unsigned int simple_rand(void) 47 + { 48 + next = next * 1103515245 + 12345; 49 + return (unsigned int)((next / 65536) % 32768); 50 + } 51 + 52 + static inline void simple_srand(unsigned long seed) 53 + { 54 + next = seed; 55 + } 56 + 57 + static void set_random_data(unsigned char *buf, size_t len) 58 + { 59 + size_t i; 60 + 61 + for (i = 0; i < len; ++i) 62 + buf[i] = simple_rand(); 63 + } 64 + 65 + static int erase_eraseblock(int ebnum) 66 + { 67 + int err; 68 + struct erase_info ei; 69 + loff_t addr = ebnum * mtd->erasesize; 70 + 71 + memset(&ei, 0, sizeof(struct erase_info)); 72 + ei.mtd = mtd; 73 + ei.addr = addr; 74 + ei.len = mtd->erasesize; 75 + 76 + err = mtd->erase(mtd, &ei); 77 + if (err) { 78 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 79 + return err; 80 + } 81 + 82 + if (ei.state == MTD_ERASE_FAILED) { 83 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 84 + ebnum); 85 + return -EIO; 86 + } 87 + 88 + return 0; 89 + } 90 + 91 + static int erase_whole_device(void) 92 + { 93 + int err; 94 + unsigned int i; 95 + 96 + for (i = 0; i < ebcnt; ++i) { 97 + if (bbt[i]) 98 + continue; 99 + err = erase_eraseblock(i); 100 + if (err) 101 + return err; 102 + cond_resched(); 103 + } 104 + return 0; 105 + } 106 + 107 + static int write_eraseblock(int ebnum) 108 + { 109 + size_t written = 0; 110 + int err = 0; 111 + loff_t addr = ebnum * mtd->erasesize; 112 + 113 + err = mtd->write(mtd, addr, mtd->erasesize, &written, iobuf); 114 + if (err || written != mtd->erasesize) { 115 + printk(PRINT_PREF "error: write failed at %#llx\n", addr); 116 + if (!err) 117 + err = -EINVAL; 118 + } 119 + 120 + return err; 121 + } 122 + 123 + static int write_eraseblock_by_page(int ebnum) 124 + { 125 + size_t written = 0; 126 + int i, err = 0; 127 + loff_t addr = ebnum * mtd->erasesize; 128 + void *buf = iobuf; 129 + 130 + for (i = 0; i < pgcnt; i++) { 131 + err = mtd->write(mtd, addr, pgsize, &written, buf); 132 + if (err || written != pgsize) { 133 + printk(PRINT_PREF "error: write failed at %#llx\n", 134 + addr); 135 + if (!err) 136 + err = -EINVAL; 137 + break; 138 + } 139 + addr += pgsize; 140 + buf += pgsize; 141 + } 142 + 143 + return err; 144 + } 145 + 146 + static int write_eraseblock_by_2pages(int ebnum) 147 + { 148 + size_t written = 0, sz = pgsize * 2; 149 + int i, n = pgcnt / 2, err = 0; 150 + loff_t addr = ebnum * mtd->erasesize; 151 + void *buf = iobuf; 152 + 153 + for (i = 0; i < n; i++) { 154 + err = mtd->write(mtd, addr, sz, &written, buf); 155 + if (err || written != sz) { 156 + printk(PRINT_PREF "error: write failed at %#llx\n", 157 + addr); 158 + if (!err) 159 + err = -EINVAL; 160 + return err; 161 + } 162 + addr += sz; 163 + buf += sz; 164 + } 165 + if (pgcnt % 2) { 166 + err = mtd->write(mtd, addr, pgsize, &written, buf); 167 + if (err || written != pgsize) { 168 + printk(PRINT_PREF "error: write failed at %#llx\n", 169 + addr); 170 + if (!err) 171 + err = -EINVAL; 172 + } 173 + } 174 + 175 + return err; 176 + } 177 + 178 + static int read_eraseblock(int ebnum) 179 + { 180 + size_t read = 0; 181 + int err = 0; 182 + loff_t addr = ebnum * mtd->erasesize; 183 + 184 + err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf); 185 + /* Ignore corrected ECC errors */ 186 + if (err == -EUCLEAN) 187 + err = 0; 188 + if (err || read != mtd->erasesize) { 189 + printk(PRINT_PREF "error: read failed at %#llx\n", addr); 190 + if (!err) 191 + err = -EINVAL; 192 + } 193 + 194 + return err; 195 + } 196 + 197 + static int read_eraseblock_by_page(int ebnum) 198 + { 199 + size_t read = 0; 200 + int i, err = 0; 201 + loff_t addr = ebnum * mtd->erasesize; 202 + void *buf = iobuf; 203 + 204 + for (i = 0; i < pgcnt; i++) { 205 + err = mtd->read(mtd, addr, pgsize, &read, buf); 206 + /* Ignore corrected ECC errors */ 207 + if (err == -EUCLEAN) 208 + err = 0; 209 + if (err || read != pgsize) { 210 + printk(PRINT_PREF "error: read failed at %#llx\n", 211 + addr); 212 + if (!err) 213 + err = -EINVAL; 214 + break; 215 + } 216 + addr += pgsize; 217 + buf += pgsize; 218 + } 219 + 220 + return err; 221 + } 222 + 223 + static int read_eraseblock_by_2pages(int ebnum) 224 + { 225 + size_t read = 0, sz = pgsize * 2; 226 + int i, n = pgcnt / 2, err = 0; 227 + loff_t addr = ebnum * mtd->erasesize; 228 + void *buf = iobuf; 229 + 230 + for (i = 0; i < n; i++) { 231 + err = mtd->read(mtd, addr, sz, &read, buf); 232 + /* Ignore corrected ECC errors */ 233 + if (err == -EUCLEAN) 234 + err = 0; 235 + if (err || read != sz) { 236 + printk(PRINT_PREF "error: read failed at %#llx\n", 237 + addr); 238 + if (!err) 239 + err = -EINVAL; 240 + return err; 241 + } 242 + addr += sz; 243 + buf += sz; 244 + } 245 + if (pgcnt % 2) { 246 + err = mtd->read(mtd, addr, pgsize, &read, buf); 247 + /* Ignore corrected ECC errors */ 248 + if (err == -EUCLEAN) 249 + err = 0; 250 + if (err || read != pgsize) { 251 + printk(PRINT_PREF "error: read failed at %#llx\n", 252 + addr); 253 + if (!err) 254 + err = -EINVAL; 255 + } 256 + } 257 + 258 + return err; 259 + } 260 + 261 + static int is_block_bad(int ebnum) 262 + { 263 + loff_t addr = ebnum * mtd->erasesize; 264 + int ret; 265 + 266 + ret = mtd->block_isbad(mtd, addr); 267 + if (ret) 268 + printk(PRINT_PREF "block %d is bad\n", ebnum); 269 + return ret; 270 + } 271 + 272 + static inline void start_timing(void) 273 + { 274 + do_gettimeofday(&start); 275 + } 276 + 277 + static inline void stop_timing(void) 278 + { 279 + do_gettimeofday(&finish); 280 + } 281 + 282 + static long calc_speed(void) 283 + { 284 + long ms, k, speed; 285 + 286 + ms = (finish.tv_sec - start.tv_sec) * 1000 + 287 + (finish.tv_usec - start.tv_usec) / 1000; 288 + k = goodebcnt * mtd->erasesize / 1024; 289 + speed = (k * 1000) / ms; 290 + return speed; 291 + } 292 + 293 + static int scan_for_bad_eraseblocks(void) 294 + { 295 + int i, bad = 0; 296 + 297 + bbt = kmalloc(ebcnt, GFP_KERNEL); 298 + if (!bbt) { 299 + printk(PRINT_PREF "error: cannot allocate memory\n"); 300 + return -ENOMEM; 301 + } 302 + memset(bbt, 0 , ebcnt); 303 + 304 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 305 + for (i = 0; i < ebcnt; ++i) { 306 + bbt[i] = is_block_bad(i) ? 1 : 0; 307 + if (bbt[i]) 308 + bad += 1; 309 + cond_resched(); 310 + } 311 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 312 + goodebcnt = ebcnt - bad; 313 + return 0; 314 + } 315 + 316 + static int __init mtd_speedtest_init(void) 317 + { 318 + int err, i; 319 + long speed; 320 + uint64_t tmp; 321 + 322 + printk(KERN_INFO "\n"); 323 + printk(KERN_INFO "=================================================\n"); 324 + printk(PRINT_PREF "MTD device: %d\n", dev); 325 + 326 + mtd = get_mtd_device(NULL, dev); 327 + if (IS_ERR(mtd)) { 328 + err = PTR_ERR(mtd); 329 + printk(PRINT_PREF "error: cannot get MTD device\n"); 330 + return err; 331 + } 332 + 333 + if (mtd->writesize == 1) { 334 + printk(PRINT_PREF "not NAND flash, assume page size is 512 " 335 + "bytes.\n"); 336 + pgsize = 512; 337 + } else 338 + pgsize = mtd->writesize; 339 + 340 + tmp = mtd->size; 341 + do_div(tmp, mtd->erasesize); 342 + ebcnt = tmp; 343 + pgcnt = mtd->erasesize / mtd->writesize; 344 + 345 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 346 + "page size %u, count of eraseblocks %u, pages per " 347 + "eraseblock %u, OOB size %u\n", 348 + (unsigned long long)mtd->size, mtd->erasesize, 349 + pgsize, ebcnt, pgcnt, mtd->oobsize); 350 + 351 + err = -ENOMEM; 352 + iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); 353 + if (!iobuf) { 354 + printk(PRINT_PREF "error: cannot allocate memory\n"); 355 + goto out; 356 + } 357 + 358 + simple_srand(1); 359 + set_random_data(iobuf, mtd->erasesize); 360 + 361 + err = scan_for_bad_eraseblocks(); 362 + if (err) 363 + goto out; 364 + 365 + err = erase_whole_device(); 366 + if (err) 367 + goto out; 368 + 369 + /* Write all eraseblocks, 1 eraseblock at a time */ 370 + printk(PRINT_PREF "testing eraseblock write speed\n"); 371 + start_timing(); 372 + for (i = 0; i < ebcnt; ++i) { 373 + if (bbt[i]) 374 + continue; 375 + err = write_eraseblock(i); 376 + if (err) 377 + goto out; 378 + cond_resched(); 379 + } 380 + stop_timing(); 381 + speed = calc_speed(); 382 + printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed); 383 + 384 + /* Read all eraseblocks, 1 eraseblock at a time */ 385 + printk(PRINT_PREF "testing eraseblock read speed\n"); 386 + start_timing(); 387 + for (i = 0; i < ebcnt; ++i) { 388 + if (bbt[i]) 389 + continue; 390 + err = read_eraseblock(i); 391 + if (err) 392 + goto out; 393 + cond_resched(); 394 + } 395 + stop_timing(); 396 + speed = calc_speed(); 397 + printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed); 398 + 399 + err = erase_whole_device(); 400 + if (err) 401 + goto out; 402 + 403 + /* Write all eraseblocks, 1 page at a time */ 404 + printk(PRINT_PREF "testing page write speed\n"); 405 + start_timing(); 406 + for (i = 0; i < ebcnt; ++i) { 407 + if (bbt[i]) 408 + continue; 409 + err = write_eraseblock_by_page(i); 410 + if (err) 411 + goto out; 412 + cond_resched(); 413 + } 414 + stop_timing(); 415 + speed = calc_speed(); 416 + printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed); 417 + 418 + /* Read all eraseblocks, 1 page at a time */ 419 + printk(PRINT_PREF "testing page read speed\n"); 420 + start_timing(); 421 + for (i = 0; i < ebcnt; ++i) { 422 + if (bbt[i]) 423 + continue; 424 + err = read_eraseblock_by_page(i); 425 + if (err) 426 + goto out; 427 + cond_resched(); 428 + } 429 + stop_timing(); 430 + speed = calc_speed(); 431 + printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed); 432 + 433 + err = erase_whole_device(); 434 + if (err) 435 + goto out; 436 + 437 + /* Write all eraseblocks, 2 pages at a time */ 438 + printk(PRINT_PREF "testing 2 page write speed\n"); 439 + start_timing(); 440 + for (i = 0; i < ebcnt; ++i) { 441 + if (bbt[i]) 442 + continue; 443 + err = write_eraseblock_by_2pages(i); 444 + if (err) 445 + goto out; 446 + cond_resched(); 447 + } 448 + stop_timing(); 449 + speed = calc_speed(); 450 + printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed); 451 + 452 + /* Read all eraseblocks, 2 pages at a time */ 453 + printk(PRINT_PREF "testing 2 page read speed\n"); 454 + start_timing(); 455 + for (i = 0; i < ebcnt; ++i) { 456 + if (bbt[i]) 457 + continue; 458 + err = read_eraseblock_by_2pages(i); 459 + if (err) 460 + goto out; 461 + cond_resched(); 462 + } 463 + stop_timing(); 464 + speed = calc_speed(); 465 + printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed); 466 + 467 + /* Erase all eraseblocks */ 468 + printk(PRINT_PREF "Testing erase speed\n"); 469 + start_timing(); 470 + for (i = 0; i < ebcnt; ++i) { 471 + if (bbt[i]) 472 + continue; 473 + err = erase_eraseblock(i); 474 + if (err) 475 + goto out; 476 + cond_resched(); 477 + } 478 + stop_timing(); 479 + speed = calc_speed(); 480 + printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed); 481 + 482 + printk(PRINT_PREF "finished\n"); 483 + out: 484 + kfree(iobuf); 485 + kfree(bbt); 486 + put_mtd_device(mtd); 487 + if (err) 488 + printk(PRINT_PREF "error %d occurred\n", err); 489 + printk(KERN_INFO "=================================================\n"); 490 + return err; 491 + } 492 + module_init(mtd_speedtest_init); 493 + 494 + static void __exit mtd_speedtest_exit(void) 495 + { 496 + return; 497 + } 498 + module_exit(mtd_speedtest_exit); 499 + 500 + MODULE_DESCRIPTION("Speed test module"); 501 + MODULE_AUTHOR("Adrian Hunter"); 502 + MODULE_LICENSE("GPL");
+330
drivers/mtd/tests/mtd_stresstest.c
··· 1 + /* 2 + * Copyright (C) 2006-2008 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Test random reads, writes and erases on MTD device. 18 + * 19 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20 + */ 21 + 22 + #include <linux/init.h> 23 + #include <linux/module.h> 24 + #include <linux/moduleparam.h> 25 + #include <linux/err.h> 26 + #include <linux/mtd/mtd.h> 27 + #include <linux/sched.h> 28 + #include <linux/vmalloc.h> 29 + 30 + #define PRINT_PREF KERN_INFO "mtd_stresstest: " 31 + 32 + static int dev; 33 + module_param(dev, int, S_IRUGO); 34 + MODULE_PARM_DESC(dev, "MTD device number to use"); 35 + 36 + static int count = 10000; 37 + module_param(count, int, S_IRUGO); 38 + MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)"); 39 + 40 + static struct mtd_info *mtd; 41 + static unsigned char *writebuf; 42 + static unsigned char *readbuf; 43 + static unsigned char *bbt; 44 + static int *offsets; 45 + 46 + static int pgsize; 47 + static int bufsize; 48 + static int ebcnt; 49 + static int pgcnt; 50 + static unsigned long next = 1; 51 + 52 + static inline unsigned int simple_rand(void) 53 + { 54 + next = next * 1103515245 + 12345; 55 + return (unsigned int)((next / 65536) % 32768); 56 + } 57 + 58 + static inline void simple_srand(unsigned long seed) 59 + { 60 + next = seed; 61 + } 62 + 63 + static int rand_eb(void) 64 + { 65 + int eb; 66 + 67 + again: 68 + if (ebcnt < 32768) 69 + eb = simple_rand(); 70 + else 71 + eb = (simple_rand() << 15) | simple_rand(); 72 + /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */ 73 + eb %= (ebcnt - 1); 74 + if (bbt[eb]) 75 + goto again; 76 + return eb; 77 + } 78 + 79 + static int rand_offs(void) 80 + { 81 + int offs; 82 + 83 + if (bufsize < 32768) 84 + offs = simple_rand(); 85 + else 86 + offs = (simple_rand() << 15) | simple_rand(); 87 + offs %= bufsize; 88 + return offs; 89 + } 90 + 91 + static int rand_len(int offs) 92 + { 93 + int len; 94 + 95 + if (bufsize < 32768) 96 + len = simple_rand(); 97 + else 98 + len = (simple_rand() << 15) | simple_rand(); 99 + len %= (bufsize - offs); 100 + return len; 101 + } 102 + 103 + static int erase_eraseblock(int ebnum) 104 + { 105 + int err; 106 + struct erase_info ei; 107 + loff_t addr = ebnum * mtd->erasesize; 108 + 109 + memset(&ei, 0, sizeof(struct erase_info)); 110 + ei.mtd = mtd; 111 + ei.addr = addr; 112 + ei.len = mtd->erasesize; 113 + 114 + err = mtd->erase(mtd, &ei); 115 + if (unlikely(err)) { 116 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 117 + return err; 118 + } 119 + 120 + if (unlikely(ei.state == MTD_ERASE_FAILED)) { 121 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 122 + ebnum); 123 + return -EIO; 124 + } 125 + 126 + return 0; 127 + } 128 + 129 + static int is_block_bad(int ebnum) 130 + { 131 + loff_t addr = ebnum * mtd->erasesize; 132 + int ret; 133 + 134 + ret = mtd->block_isbad(mtd, addr); 135 + if (ret) 136 + printk(PRINT_PREF "block %d is bad\n", ebnum); 137 + return ret; 138 + } 139 + 140 + static int do_read(void) 141 + { 142 + size_t read = 0; 143 + int eb = rand_eb(); 144 + int offs = rand_offs(); 145 + int len = rand_len(offs), err; 146 + loff_t addr; 147 + 148 + if (bbt[eb + 1]) { 149 + if (offs >= mtd->erasesize) 150 + offs -= mtd->erasesize; 151 + if (offs + len > mtd->erasesize) 152 + len = mtd->erasesize - offs; 153 + } 154 + addr = eb * mtd->erasesize + offs; 155 + err = mtd->read(mtd, addr, len, &read, readbuf); 156 + if (err == -EUCLEAN) 157 + err = 0; 158 + if (unlikely(err || read != len)) { 159 + printk(PRINT_PREF "error: read failed at 0x%llx\n", 160 + (long long)addr); 161 + if (!err) 162 + err = -EINVAL; 163 + return err; 164 + } 165 + return 0; 166 + } 167 + 168 + static int do_write(void) 169 + { 170 + int eb = rand_eb(), offs, err, len; 171 + size_t written = 0; 172 + loff_t addr; 173 + 174 + offs = offsets[eb]; 175 + if (offs >= mtd->erasesize) { 176 + err = erase_eraseblock(eb); 177 + if (err) 178 + return err; 179 + offs = offsets[eb] = 0; 180 + } 181 + len = rand_len(offs); 182 + len = ((len + pgsize - 1) / pgsize) * pgsize; 183 + if (offs + len > mtd->erasesize) { 184 + if (bbt[eb + 1]) 185 + len = mtd->erasesize - offs; 186 + else { 187 + err = erase_eraseblock(eb + 1); 188 + if (err) 189 + return err; 190 + offsets[eb + 1] = 0; 191 + } 192 + } 193 + addr = eb * mtd->erasesize + offs; 194 + err = mtd->write(mtd, addr, len, &written, writebuf); 195 + if (unlikely(err || written != len)) { 196 + printk(PRINT_PREF "error: write failed at 0x%llx\n", 197 + (long long)addr); 198 + if (!err) 199 + err = -EINVAL; 200 + return err; 201 + } 202 + offs += len; 203 + while (offs > mtd->erasesize) { 204 + offsets[eb++] = mtd->erasesize; 205 + offs -= mtd->erasesize; 206 + } 207 + offsets[eb] = offs; 208 + return 0; 209 + } 210 + 211 + static int do_operation(void) 212 + { 213 + if (simple_rand() & 1) 214 + return do_read(); 215 + else 216 + return do_write(); 217 + } 218 + 219 + static int scan_for_bad_eraseblocks(void) 220 + { 221 + int i, bad = 0; 222 + 223 + bbt = kmalloc(ebcnt, GFP_KERNEL); 224 + if (!bbt) { 225 + printk(PRINT_PREF "error: cannot allocate memory\n"); 226 + return -ENOMEM; 227 + } 228 + memset(bbt, 0 , ebcnt); 229 + 230 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 231 + for (i = 0; i < ebcnt; ++i) { 232 + bbt[i] = is_block_bad(i) ? 1 : 0; 233 + if (bbt[i]) 234 + bad += 1; 235 + cond_resched(); 236 + } 237 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 238 + return 0; 239 + } 240 + 241 + static int __init mtd_stresstest_init(void) 242 + { 243 + int err; 244 + int i, op; 245 + uint64_t tmp; 246 + 247 + printk(KERN_INFO "\n"); 248 + printk(KERN_INFO "=================================================\n"); 249 + printk(PRINT_PREF "MTD device: %d\n", dev); 250 + 251 + mtd = get_mtd_device(NULL, dev); 252 + if (IS_ERR(mtd)) { 253 + err = PTR_ERR(mtd); 254 + printk(PRINT_PREF "error: cannot get MTD device\n"); 255 + return err; 256 + } 257 + 258 + if (mtd->writesize == 1) { 259 + printk(PRINT_PREF "not NAND flash, assume page size is 512 " 260 + "bytes.\n"); 261 + pgsize = 512; 262 + } else 263 + pgsize = mtd->writesize; 264 + 265 + tmp = mtd->size; 266 + do_div(tmp, mtd->erasesize); 267 + ebcnt = tmp; 268 + pgcnt = mtd->erasesize / mtd->writesize; 269 + 270 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 271 + "page size %u, count of eraseblocks %u, pages per " 272 + "eraseblock %u, OOB size %u\n", 273 + (unsigned long long)mtd->size, mtd->erasesize, 274 + pgsize, ebcnt, pgcnt, mtd->oobsize); 275 + 276 + /* Read or write up 2 eraseblocks at a time */ 277 + bufsize = mtd->erasesize * 2; 278 + 279 + err = -ENOMEM; 280 + readbuf = vmalloc(bufsize); 281 + writebuf = vmalloc(bufsize); 282 + offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); 283 + if (!readbuf || !writebuf || !offsets) { 284 + printk(PRINT_PREF "error: cannot allocate memory\n"); 285 + goto out; 286 + } 287 + for (i = 0; i < ebcnt; i++) 288 + offsets[i] = mtd->erasesize; 289 + simple_srand(current->pid); 290 + for (i = 0; i < bufsize; i++) 291 + writebuf[i] = simple_rand(); 292 + 293 + err = scan_for_bad_eraseblocks(); 294 + if (err) 295 + goto out; 296 + 297 + /* Do operations */ 298 + printk(PRINT_PREF "doing operations\n"); 299 + for (op = 0; op < count; op++) { 300 + if ((op & 1023) == 0) 301 + printk(PRINT_PREF "%d operations done\n", op); 302 + err = do_operation(); 303 + if (err) 304 + goto out; 305 + cond_resched(); 306 + } 307 + printk(PRINT_PREF "finished, %d operations done\n", op); 308 + 309 + out: 310 + kfree(offsets); 311 + kfree(bbt); 312 + vfree(writebuf); 313 + vfree(readbuf); 314 + put_mtd_device(mtd); 315 + if (err) 316 + printk(PRINT_PREF "error %d occurred\n", err); 317 + printk(KERN_INFO "=================================================\n"); 318 + return err; 319 + } 320 + module_init(mtd_stresstest_init); 321 + 322 + static void __exit mtd_stresstest_exit(void) 323 + { 324 + return; 325 + } 326 + module_exit(mtd_stresstest_exit); 327 + 328 + MODULE_DESCRIPTION("Stress test module"); 329 + MODULE_AUTHOR("Adrian Hunter"); 330 + MODULE_LICENSE("GPL");
+525
drivers/mtd/tests/mtd_subpagetest.c
··· 1 + /* 2 + * Copyright (C) 2006-2007 Nokia Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; see the file COPYING. If not, write to the Free Software 15 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 + * 17 + * Test sub-page read and write on MTD device. 18 + * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 19 + * 20 + */ 21 + 22 + #include <linux/init.h> 23 + #include <linux/module.h> 24 + #include <linux/moduleparam.h> 25 + #include <linux/err.h> 26 + #include <linux/mtd/mtd.h> 27 + #include <linux/sched.h> 28 + 29 + #define PRINT_PREF KERN_INFO "mtd_subpagetest: " 30 + 31 + static int dev; 32 + module_param(dev, int, S_IRUGO); 33 + MODULE_PARM_DESC(dev, "MTD device number to use"); 34 + 35 + static struct mtd_info *mtd; 36 + static unsigned char *writebuf; 37 + static unsigned char *readbuf; 38 + static unsigned char *bbt; 39 + 40 + static int subpgsize; 41 + static int bufsize; 42 + static int ebcnt; 43 + static int pgcnt; 44 + static int errcnt; 45 + static unsigned long next = 1; 46 + 47 + static inline unsigned int simple_rand(void) 48 + { 49 + next = next * 1103515245 + 12345; 50 + return (unsigned int)((next / 65536) % 32768); 51 + } 52 + 53 + static inline void simple_srand(unsigned long seed) 54 + { 55 + next = seed; 56 + } 57 + 58 + static void set_random_data(unsigned char *buf, size_t len) 59 + { 60 + size_t i; 61 + 62 + for (i = 0; i < len; ++i) 63 + buf[i] = simple_rand(); 64 + } 65 + 66 + static inline void clear_data(unsigned char *buf, size_t len) 67 + { 68 + memset(buf, 0, len); 69 + } 70 + 71 + static int erase_eraseblock(int ebnum) 72 + { 73 + int err; 74 + struct erase_info ei; 75 + loff_t addr = ebnum * mtd->erasesize; 76 + 77 + memset(&ei, 0, sizeof(struct erase_info)); 78 + ei.mtd = mtd; 79 + ei.addr = addr; 80 + ei.len = mtd->erasesize; 81 + 82 + err = mtd->erase(mtd, &ei); 83 + if (err) { 84 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 85 + return err; 86 + } 87 + 88 + if (ei.state == MTD_ERASE_FAILED) { 89 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 90 + ebnum); 91 + return -EIO; 92 + } 93 + 94 + return 0; 95 + } 96 + 97 + static int erase_whole_device(void) 98 + { 99 + int err; 100 + unsigned int i; 101 + 102 + printk(PRINT_PREF "erasing whole device\n"); 103 + for (i = 0; i < ebcnt; ++i) { 104 + if (bbt[i]) 105 + continue; 106 + err = erase_eraseblock(i); 107 + if (err) 108 + return err; 109 + cond_resched(); 110 + } 111 + printk(PRINT_PREF "erased %u eraseblocks\n", i); 112 + return 0; 113 + } 114 + 115 + static int write_eraseblock(int ebnum) 116 + { 117 + size_t written = 0; 118 + int err = 0; 119 + loff_t addr = ebnum * mtd->erasesize; 120 + 121 + set_random_data(writebuf, subpgsize); 122 + err = mtd->write(mtd, addr, subpgsize, &written, writebuf); 123 + if (unlikely(err || written != subpgsize)) { 124 + printk(PRINT_PREF "error: write failed at %#llx\n", 125 + (long long)addr); 126 + if (written != subpgsize) { 127 + printk(PRINT_PREF " write size: %#x\n", subpgsize); 128 + printk(PRINT_PREF " written: %#zx\n", written); 129 + } 130 + return err ? err : -1; 131 + } 132 + 133 + addr += subpgsize; 134 + 135 + set_random_data(writebuf, subpgsize); 136 + err = mtd->write(mtd, addr, subpgsize, &written, writebuf); 137 + if (unlikely(err || written != subpgsize)) { 138 + printk(PRINT_PREF "error: write failed at %#llx\n", 139 + (long long)addr); 140 + if (written != subpgsize) { 141 + printk(PRINT_PREF " write size: %#x\n", subpgsize); 142 + printk(PRINT_PREF " written: %#zx\n", written); 143 + } 144 + return err ? err : -1; 145 + } 146 + 147 + return err; 148 + } 149 + 150 + static int write_eraseblock2(int ebnum) 151 + { 152 + size_t written = 0; 153 + int err = 0, k; 154 + loff_t addr = ebnum * mtd->erasesize; 155 + 156 + for (k = 1; k < 33; ++k) { 157 + if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize) 158 + break; 159 + set_random_data(writebuf, subpgsize * k); 160 + err = mtd->write(mtd, addr, subpgsize * k, &written, writebuf); 161 + if (unlikely(err || written != subpgsize * k)) { 162 + printk(PRINT_PREF "error: write failed at %#llx\n", 163 + (long long)addr); 164 + if (written != subpgsize) { 165 + printk(PRINT_PREF " write size: %#x\n", 166 + subpgsize * k); 167 + printk(PRINT_PREF " written: %#08zx\n", 168 + written); 169 + } 170 + return err ? err : -1; 171 + } 172 + addr += subpgsize * k; 173 + } 174 + 175 + return err; 176 + } 177 + 178 + static void print_subpage(unsigned char *p) 179 + { 180 + int i, j; 181 + 182 + for (i = 0; i < subpgsize; ) { 183 + for (j = 0; i < subpgsize && j < 32; ++i, ++j) 184 + printk("%02x", *p++); 185 + printk("\n"); 186 + } 187 + } 188 + 189 + static int verify_eraseblock(int ebnum) 190 + { 191 + size_t read = 0; 192 + int err = 0; 193 + loff_t addr = ebnum * mtd->erasesize; 194 + 195 + set_random_data(writebuf, subpgsize); 196 + clear_data(readbuf, subpgsize); 197 + read = 0; 198 + err = mtd->read(mtd, addr, subpgsize, &read, readbuf); 199 + if (unlikely(err || read != subpgsize)) { 200 + if (err == -EUCLEAN && read == subpgsize) { 201 + printk(PRINT_PREF "ECC correction at %#llx\n", 202 + (long long)addr); 203 + err = 0; 204 + } else { 205 + printk(PRINT_PREF "error: read failed at %#llx\n", 206 + (long long)addr); 207 + return err ? err : -1; 208 + } 209 + } 210 + if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 211 + printk(PRINT_PREF "error: verify failed at %#llx\n", 212 + (long long)addr); 213 + printk(PRINT_PREF "------------- written----------------\n"); 214 + print_subpage(writebuf); 215 + printk(PRINT_PREF "------------- read ------------------\n"); 216 + print_subpage(readbuf); 217 + printk(PRINT_PREF "-------------------------------------\n"); 218 + errcnt += 1; 219 + } 220 + 221 + addr += subpgsize; 222 + 223 + set_random_data(writebuf, subpgsize); 224 + clear_data(readbuf, subpgsize); 225 + read = 0; 226 + err = mtd->read(mtd, addr, subpgsize, &read, readbuf); 227 + if (unlikely(err || read != subpgsize)) { 228 + if (err == -EUCLEAN && read == subpgsize) { 229 + printk(PRINT_PREF "ECC correction at %#llx\n", 230 + (long long)addr); 231 + err = 0; 232 + } else { 233 + printk(PRINT_PREF "error: read failed at %#llx\n", 234 + (long long)addr); 235 + return err ? err : -1; 236 + } 237 + } 238 + if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 239 + printk(PRINT_PREF "error: verify failed at %#llx\n", 240 + (long long)addr); 241 + printk(PRINT_PREF "------------- written----------------\n"); 242 + print_subpage(writebuf); 243 + printk(PRINT_PREF "------------- read ------------------\n"); 244 + print_subpage(readbuf); 245 + printk(PRINT_PREF "-------------------------------------\n"); 246 + errcnt += 1; 247 + } 248 + 249 + return err; 250 + } 251 + 252 + static int verify_eraseblock2(int ebnum) 253 + { 254 + size_t read = 0; 255 + int err = 0, k; 256 + loff_t addr = ebnum * mtd->erasesize; 257 + 258 + for (k = 1; k < 33; ++k) { 259 + if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize) 260 + break; 261 + set_random_data(writebuf, subpgsize * k); 262 + clear_data(readbuf, subpgsize * k); 263 + read = 0; 264 + err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf); 265 + if (unlikely(err || read != subpgsize * k)) { 266 + if (err == -EUCLEAN && read == subpgsize * k) { 267 + printk(PRINT_PREF "ECC correction at %#llx\n", 268 + (long long)addr); 269 + err = 0; 270 + } else { 271 + printk(PRINT_PREF "error: read failed at " 272 + "%#llx\n", (long long)addr); 273 + return err ? err : -1; 274 + } 275 + } 276 + if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { 277 + printk(PRINT_PREF "error: verify failed at %#llx\n", 278 + (long long)addr); 279 + errcnt += 1; 280 + } 281 + addr += subpgsize * k; 282 + } 283 + 284 + return err; 285 + } 286 + 287 + static int verify_eraseblock_ff(int ebnum) 288 + { 289 + uint32_t j; 290 + size_t read = 0; 291 + int err = 0; 292 + loff_t addr = ebnum * mtd->erasesize; 293 + 294 + memset(writebuf, 0xff, subpgsize); 295 + for (j = 0; j < mtd->erasesize / subpgsize; ++j) { 296 + clear_data(readbuf, subpgsize); 297 + read = 0; 298 + err = mtd->read(mtd, addr, subpgsize, &read, readbuf); 299 + if (unlikely(err || read != subpgsize)) { 300 + if (err == -EUCLEAN && read == subpgsize) { 301 + printk(PRINT_PREF "ECC correction at %#llx\n", 302 + (long long)addr); 303 + err = 0; 304 + } else { 305 + printk(PRINT_PREF "error: read failed at " 306 + "%#llx\n", (long long)addr); 307 + return err ? err : -1; 308 + } 309 + } 310 + if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { 311 + printk(PRINT_PREF "error: verify 0xff failed at " 312 + "%#llx\n", (long long)addr); 313 + errcnt += 1; 314 + } 315 + addr += subpgsize; 316 + } 317 + 318 + return err; 319 + } 320 + 321 + static int verify_all_eraseblocks_ff(void) 322 + { 323 + int err; 324 + unsigned int i; 325 + 326 + printk(PRINT_PREF "verifying all eraseblocks for 0xff\n"); 327 + for (i = 0; i < ebcnt; ++i) { 328 + if (bbt[i]) 329 + continue; 330 + err = verify_eraseblock_ff(i); 331 + if (err) 332 + return err; 333 + if (i % 256 == 0) 334 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 335 + cond_resched(); 336 + } 337 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 338 + return 0; 339 + } 340 + 341 + static int is_block_bad(int ebnum) 342 + { 343 + loff_t addr = ebnum * mtd->erasesize; 344 + int ret; 345 + 346 + ret = mtd->block_isbad(mtd, addr); 347 + if (ret) 348 + printk(PRINT_PREF "block %d is bad\n", ebnum); 349 + return ret; 350 + } 351 + 352 + static int scan_for_bad_eraseblocks(void) 353 + { 354 + int i, bad = 0; 355 + 356 + bbt = kmalloc(ebcnt, GFP_KERNEL); 357 + if (!bbt) { 358 + printk(PRINT_PREF "error: cannot allocate memory\n"); 359 + return -ENOMEM; 360 + } 361 + memset(bbt, 0 , ebcnt); 362 + 363 + printk(PRINT_PREF "scanning for bad eraseblocks\n"); 364 + for (i = 0; i < ebcnt; ++i) { 365 + bbt[i] = is_block_bad(i) ? 1 : 0; 366 + if (bbt[i]) 367 + bad += 1; 368 + cond_resched(); 369 + } 370 + printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); 371 + return 0; 372 + } 373 + 374 + static int __init mtd_subpagetest_init(void) 375 + { 376 + int err = 0; 377 + uint32_t i; 378 + uint64_t tmp; 379 + 380 + printk(KERN_INFO "\n"); 381 + printk(KERN_INFO "=================================================\n"); 382 + printk(PRINT_PREF "MTD device: %d\n", dev); 383 + 384 + mtd = get_mtd_device(NULL, dev); 385 + if (IS_ERR(mtd)) { 386 + err = PTR_ERR(mtd); 387 + printk(PRINT_PREF "error: cannot get MTD device\n"); 388 + return err; 389 + } 390 + 391 + if (mtd->type != MTD_NANDFLASH) { 392 + printk(PRINT_PREF "this test requires NAND flash\n"); 393 + goto out; 394 + } 395 + 396 + subpgsize = mtd->writesize >> mtd->subpage_sft; 397 + printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " 398 + "page size %u, subpage size %u, count of eraseblocks %u, " 399 + "pages per eraseblock %u, OOB size %u\n", 400 + (unsigned long long)mtd->size, mtd->erasesize, 401 + mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize); 402 + 403 + err = -ENOMEM; 404 + bufsize = subpgsize * 32; 405 + writebuf = kmalloc(bufsize, GFP_KERNEL); 406 + if (!writebuf) { 407 + printk(PRINT_PREF "error: cannot allocate memory\n"); 408 + goto out; 409 + } 410 + readbuf = kmalloc(bufsize, GFP_KERNEL); 411 + if (!readbuf) { 412 + printk(PRINT_PREF "error: cannot allocate memory\n"); 413 + goto out; 414 + } 415 + 416 + tmp = mtd->size; 417 + do_div(tmp, mtd->erasesize); 418 + ebcnt = tmp; 419 + pgcnt = mtd->erasesize / mtd->writesize; 420 + 421 + err = scan_for_bad_eraseblocks(); 422 + if (err) 423 + goto out; 424 + 425 + err = erase_whole_device(); 426 + if (err) 427 + goto out; 428 + 429 + printk(PRINT_PREF "writing whole device\n"); 430 + simple_srand(1); 431 + for (i = 0; i < ebcnt; ++i) { 432 + if (bbt[i]) 433 + continue; 434 + err = write_eraseblock(i); 435 + if (unlikely(err)) 436 + goto out; 437 + if (i % 256 == 0) 438 + printk(PRINT_PREF "written up to eraseblock %u\n", i); 439 + cond_resched(); 440 + } 441 + printk(PRINT_PREF "written %u eraseblocks\n", i); 442 + 443 + simple_srand(1); 444 + printk(PRINT_PREF "verifying all eraseblocks\n"); 445 + for (i = 0; i < ebcnt; ++i) { 446 + if (bbt[i]) 447 + continue; 448 + err = verify_eraseblock(i); 449 + if (unlikely(err)) 450 + goto out; 451 + if (i % 256 == 0) 452 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 453 + cond_resched(); 454 + } 455 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 456 + 457 + err = erase_whole_device(); 458 + if (err) 459 + goto out; 460 + 461 + err = verify_all_eraseblocks_ff(); 462 + if (err) 463 + goto out; 464 + 465 + /* Write all eraseblocks */ 466 + simple_srand(3); 467 + printk(PRINT_PREF "writing whole device\n"); 468 + for (i = 0; i < ebcnt; ++i) { 469 + if (bbt[i]) 470 + continue; 471 + err = write_eraseblock2(i); 472 + if (unlikely(err)) 473 + goto out; 474 + if (i % 256 == 0) 475 + printk(PRINT_PREF "written up to eraseblock %u\n", i); 476 + cond_resched(); 477 + } 478 + printk(PRINT_PREF "written %u eraseblocks\n", i); 479 + 480 + /* Check all eraseblocks */ 481 + simple_srand(3); 482 + printk(PRINT_PREF "verifying all eraseblocks\n"); 483 + for (i = 0; i < ebcnt; ++i) { 484 + if (bbt[i]) 485 + continue; 486 + err = verify_eraseblock2(i); 487 + if (unlikely(err)) 488 + goto out; 489 + if (i % 256 == 0) 490 + printk(PRINT_PREF "verified up to eraseblock %u\n", i); 491 + cond_resched(); 492 + } 493 + printk(PRINT_PREF "verified %u eraseblocks\n", i); 494 + 495 + err = erase_whole_device(); 496 + if (err) 497 + goto out; 498 + 499 + err = verify_all_eraseblocks_ff(); 500 + if (err) 501 + goto out; 502 + 503 + printk(PRINT_PREF "finished with %d errors\n", errcnt); 504 + 505 + out: 506 + kfree(bbt); 507 + kfree(readbuf); 508 + kfree(writebuf); 509 + put_mtd_device(mtd); 510 + if (err) 511 + printk(PRINT_PREF "error %d occurred\n", err); 512 + printk(KERN_INFO "=================================================\n"); 513 + return err; 514 + } 515 + module_init(mtd_subpagetest_init); 516 + 517 + static void __exit mtd_subpagetest_exit(void) 518 + { 519 + return; 520 + } 521 + module_exit(mtd_subpagetest_exit); 522 + 523 + MODULE_DESCRIPTION("Subpage test module"); 524 + MODULE_AUTHOR("Adrian Hunter"); 525 + MODULE_LICENSE("GPL");
+530
drivers/mtd/tests/mtd_torturetest.c
··· 1 + /* 2 + * Copyright (C) 2006-2008 Artem Bityutskiy 3 + * Copyright (C) 2006-2008 Jarkko Lavinen 4 + * Copyright (C) 2006-2008 Adrian Hunter 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published by 8 + * the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + * You should have received a copy of the GNU General Public License along with 16 + * this program; see the file COPYING. If not, write to the Free Software 17 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 + * 19 + * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter 20 + * 21 + * WARNING: this test program may kill your flash and your device. Do not 22 + * use it unless you know what you do. Authors are not responsible for any 23 + * damage caused by this program. 24 + */ 25 + 26 + #include <linux/init.h> 27 + #include <linux/module.h> 28 + #include <linux/moduleparam.h> 29 + #include <linux/err.h> 30 + #include <linux/mtd/mtd.h> 31 + #include <linux/sched.h> 32 + 33 + #define PRINT_PREF KERN_INFO "mtd_torturetest: " 34 + #define RETRIES 3 35 + 36 + static int eb = 8; 37 + module_param(eb, int, S_IRUGO); 38 + MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device"); 39 + 40 + static int ebcnt = 32; 41 + module_param(ebcnt, int, S_IRUGO); 42 + MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture"); 43 + 44 + static int pgcnt; 45 + module_param(pgcnt, int, S_IRUGO); 46 + MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)"); 47 + 48 + static int dev; 49 + module_param(dev, int, S_IRUGO); 50 + MODULE_PARM_DESC(dev, "MTD device number to use"); 51 + 52 + static int gran = 512; 53 + module_param(gran, int, S_IRUGO); 54 + MODULE_PARM_DESC(gran, "how often the status information should be printed"); 55 + 56 + static int check = 1; 57 + module_param(check, int, S_IRUGO); 58 + MODULE_PARM_DESC(check, "if the written data should be checked"); 59 + 60 + static unsigned int cycles_count; 61 + module_param(cycles_count, uint, S_IRUGO); 62 + MODULE_PARM_DESC(cycles_count, "how many erase cycles to do " 63 + "(infinite by default)"); 64 + 65 + static struct mtd_info *mtd; 66 + 67 + /* This buffer contains 0x555555...0xAAAAAA... pattern */ 68 + static unsigned char *patt_5A5; 69 + /* This buffer contains 0xAAAAAA...0x555555... pattern */ 70 + static unsigned char *patt_A5A; 71 + /* This buffer contains all 0xFF bytes */ 72 + static unsigned char *patt_FF; 73 + /* This a temporary buffer is use when checking data */ 74 + static unsigned char *check_buf; 75 + /* How many erase cycles were done */ 76 + static unsigned int erase_cycles; 77 + 78 + static int pgsize; 79 + static struct timeval start, finish; 80 + 81 + static void report_corrupt(unsigned char *read, unsigned char *written); 82 + 83 + static inline void start_timing(void) 84 + { 85 + do_gettimeofday(&start); 86 + } 87 + 88 + static inline void stop_timing(void) 89 + { 90 + do_gettimeofday(&finish); 91 + } 92 + 93 + /* 94 + * Erase eraseblock number @ebnum. 95 + */ 96 + static inline int erase_eraseblock(int ebnum) 97 + { 98 + int err; 99 + struct erase_info ei; 100 + loff_t addr = ebnum * mtd->erasesize; 101 + 102 + memset(&ei, 0, sizeof(struct erase_info)); 103 + ei.mtd = mtd; 104 + ei.addr = addr; 105 + ei.len = mtd->erasesize; 106 + 107 + err = mtd->erase(mtd, &ei); 108 + if (err) { 109 + printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 110 + return err; 111 + } 112 + 113 + if (ei.state == MTD_ERASE_FAILED) { 114 + printk(PRINT_PREF "some erase error occurred at EB %d\n", 115 + ebnum); 116 + return -EIO; 117 + } 118 + 119 + return 0; 120 + } 121 + 122 + /* 123 + * Check that the contents of eraseblock number @enbum is equivalent to the 124 + * @buf buffer. 125 + */ 126 + static inline int check_eraseblock(int ebnum, unsigned char *buf) 127 + { 128 + int err, retries = 0; 129 + size_t read = 0; 130 + loff_t addr = ebnum * mtd->erasesize; 131 + size_t len = mtd->erasesize; 132 + 133 + if (pgcnt) { 134 + addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; 135 + len = pgcnt * pgsize; 136 + } 137 + 138 + retry: 139 + err = mtd->read(mtd, addr, len, &read, check_buf); 140 + if (err == -EUCLEAN) 141 + printk(PRINT_PREF "single bit flip occurred at EB %d " 142 + "MTD reported that it was fixed.\n", ebnum); 143 + else if (err) { 144 + printk(PRINT_PREF "error %d while reading EB %d, " 145 + "read %zd\n", err, ebnum, read); 146 + return err; 147 + } 148 + 149 + if (read != len) { 150 + printk(PRINT_PREF "failed to read %zd bytes from EB %d, " 151 + "read only %zd, but no error reported\n", 152 + len, ebnum, read); 153 + return -EIO; 154 + } 155 + 156 + if (memcmp(buf, check_buf, len)) { 157 + printk(PRINT_PREF "read wrong data from EB %d\n", ebnum); 158 + report_corrupt(check_buf, buf); 159 + 160 + if (retries++ < RETRIES) { 161 + /* Try read again */ 162 + yield(); 163 + printk(PRINT_PREF "re-try reading data from EB %d\n", 164 + ebnum); 165 + goto retry; 166 + } else { 167 + printk(PRINT_PREF "retried %d times, still errors, " 168 + "give-up\n", RETRIES); 169 + return -EINVAL; 170 + } 171 + } 172 + 173 + if (retries != 0) 174 + printk(PRINT_PREF "only attempt number %d was OK (!!!)\n", 175 + retries); 176 + 177 + return 0; 178 + } 179 + 180 + static inline int write_pattern(int ebnum, void *buf) 181 + { 182 + int err; 183 + size_t written = 0; 184 + loff_t addr = ebnum * mtd->erasesize; 185 + size_t len = mtd->erasesize; 186 + 187 + if (pgcnt) { 188 + addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; 189 + len = pgcnt * pgsize; 190 + } 191 + err = mtd->write(mtd, addr, len, &written, buf); 192 + if (err) { 193 + printk(PRINT_PREF "error %d while writing EB %d, written %zd" 194 + " bytes\n", err, ebnum, written); 195 + return err; 196 + } 197 + if (written != len) { 198 + printk(PRINT_PREF "written only %zd bytes of %zd, but no error" 199 + " reported\n", written, len); 200 + return -EIO; 201 + } 202 + 203 + return 0; 204 + } 205 + 206 + static int __init tort_init(void) 207 + { 208 + int err = 0, i, infinite = !cycles_count; 209 + int bad_ebs[ebcnt]; 210 + 211 + printk(KERN_INFO "\n"); 212 + printk(KERN_INFO "=================================================\n"); 213 + printk(PRINT_PREF "Warning: this program is trying to wear out your " 214 + "flash, stop it if this is not wanted.\n"); 215 + printk(PRINT_PREF "MTD device: %d\n", dev); 216 + printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", 217 + ebcnt, eb, eb + ebcnt - 1, dev); 218 + if (pgcnt) 219 + printk(PRINT_PREF "torturing just %d pages per eraseblock\n", 220 + pgcnt); 221 + printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled"); 222 + 223 + mtd = get_mtd_device(NULL, dev); 224 + if (IS_ERR(mtd)) { 225 + err = PTR_ERR(mtd); 226 + printk(PRINT_PREF "error: cannot get MTD device\n"); 227 + return err; 228 + } 229 + 230 + if (mtd->writesize == 1) { 231 + printk(PRINT_PREF "not NAND flash, assume page size is 512 " 232 + "bytes.\n"); 233 + pgsize = 512; 234 + } else 235 + pgsize = mtd->writesize; 236 + 237 + if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { 238 + printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt); 239 + goto out_mtd; 240 + } 241 + 242 + err = -ENOMEM; 243 + patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); 244 + if (!patt_5A5) { 245 + printk(PRINT_PREF "error: cannot allocate memory\n"); 246 + goto out_mtd; 247 + } 248 + 249 + patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); 250 + if (!patt_A5A) { 251 + printk(PRINT_PREF "error: cannot allocate memory\n"); 252 + goto out_patt_5A5; 253 + } 254 + 255 + patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); 256 + if (!patt_FF) { 257 + printk(PRINT_PREF "error: cannot allocate memory\n"); 258 + goto out_patt_A5A; 259 + } 260 + 261 + check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); 262 + if (!check_buf) { 263 + printk(PRINT_PREF "error: cannot allocate memory\n"); 264 + goto out_patt_FF; 265 + } 266 + 267 + err = 0; 268 + 269 + /* Initialize patterns */ 270 + memset(patt_FF, 0xFF, mtd->erasesize); 271 + for (i = 0; i < mtd->erasesize / pgsize; i++) { 272 + if (!(i & 1)) { 273 + memset(patt_5A5 + i * pgsize, 0x55, pgsize); 274 + memset(patt_A5A + i * pgsize, 0xAA, pgsize); 275 + } else { 276 + memset(patt_5A5 + i * pgsize, 0xAA, pgsize); 277 + memset(patt_A5A + i * pgsize, 0x55, pgsize); 278 + } 279 + } 280 + 281 + /* 282 + * Check if there is a bad eraseblock among those we are going to test. 283 + */ 284 + memset(&bad_ebs[0], 0, sizeof(int) * ebcnt); 285 + if (mtd->block_isbad) { 286 + for (i = eb; i < eb + ebcnt; i++) { 287 + err = mtd->block_isbad(mtd, 288 + (loff_t)i * mtd->erasesize); 289 + 290 + if (err < 0) { 291 + printk(PRINT_PREF "block_isbad() returned %d " 292 + "for EB %d\n", err, i); 293 + goto out; 294 + } 295 + 296 + if (err) { 297 + printk("EB %d is bad. Skip it.\n", i); 298 + bad_ebs[i - eb] = 1; 299 + } 300 + } 301 + } 302 + 303 + start_timing(); 304 + while (1) { 305 + int i; 306 + void *patt; 307 + 308 + /* Erase all eraseblocks */ 309 + for (i = eb; i < eb + ebcnt; i++) { 310 + if (bad_ebs[i - eb]) 311 + continue; 312 + err = erase_eraseblock(i); 313 + if (err) 314 + goto out; 315 + cond_resched(); 316 + } 317 + 318 + /* Check if the eraseblocks contain only 0xFF bytes */ 319 + if (check) { 320 + for (i = eb; i < eb + ebcnt; i++) { 321 + if (bad_ebs[i - eb]) 322 + continue; 323 + err = check_eraseblock(i, patt_FF); 324 + if (err) { 325 + printk(PRINT_PREF "verify failed" 326 + " for 0xFF... pattern\n"); 327 + goto out; 328 + } 329 + cond_resched(); 330 + } 331 + } 332 + 333 + /* Write the pattern */ 334 + for (i = eb; i < eb + ebcnt; i++) { 335 + if (bad_ebs[i - eb]) 336 + continue; 337 + if ((eb + erase_cycles) & 1) 338 + patt = patt_5A5; 339 + else 340 + patt = patt_A5A; 341 + err = write_pattern(i, patt); 342 + if (err) 343 + goto out; 344 + cond_resched(); 345 + } 346 + 347 + /* Verify what we wrote */ 348 + if (check) { 349 + for (i = eb; i < eb + ebcnt; i++) { 350 + if (bad_ebs[i - eb]) 351 + continue; 352 + if ((eb + erase_cycles) & 1) 353 + patt = patt_5A5; 354 + else 355 + patt = patt_A5A; 356 + err = check_eraseblock(i, patt); 357 + if (err) { 358 + printk(PRINT_PREF "verify failed for %s" 359 + " pattern\n", 360 + ((eb + erase_cycles) & 1) ? 361 + "0x55AA55..." : "0xAA55AA..."); 362 + goto out; 363 + } 364 + cond_resched(); 365 + } 366 + } 367 + 368 + erase_cycles += 1; 369 + 370 + if (erase_cycles % gran == 0) { 371 + long ms; 372 + 373 + stop_timing(); 374 + ms = (finish.tv_sec - start.tv_sec) * 1000 + 375 + (finish.tv_usec - start.tv_usec) / 1000; 376 + printk(PRINT_PREF "%08u erase cycles done, took %lu " 377 + "milliseconds (%lu seconds)\n", 378 + erase_cycles, ms, ms / 1000); 379 + start_timing(); 380 + } 381 + 382 + if (!infinite && --cycles_count == 0) 383 + break; 384 + } 385 + out: 386 + 387 + printk(PRINT_PREF "finished after %u erase cycles\n", 388 + erase_cycles); 389 + kfree(check_buf); 390 + out_patt_FF: 391 + kfree(patt_FF); 392 + out_patt_A5A: 393 + kfree(patt_A5A); 394 + out_patt_5A5: 395 + kfree(patt_5A5); 396 + out_mtd: 397 + put_mtd_device(mtd); 398 + if (err) 399 + printk(PRINT_PREF "error %d occurred during torturing\n", err); 400 + printk(KERN_INFO "=================================================\n"); 401 + return err; 402 + } 403 + module_init(tort_init); 404 + 405 + static void __exit tort_exit(void) 406 + { 407 + return; 408 + } 409 + module_exit(tort_exit); 410 + 411 + static int countdiffs(unsigned char *buf, unsigned char *check_buf, 412 + unsigned offset, unsigned len, unsigned *bytesp, 413 + unsigned *bitsp); 414 + static void print_bufs(unsigned char *read, unsigned char *written, int start, 415 + int len); 416 + 417 + /* 418 + * Report the detailed information about how the read EB differs from what was 419 + * written. 420 + */ 421 + static void report_corrupt(unsigned char *read, unsigned char *written) 422 + { 423 + int i; 424 + int bytes, bits, pages, first; 425 + int offset, len; 426 + size_t check_len = mtd->erasesize; 427 + 428 + if (pgcnt) 429 + check_len = pgcnt * pgsize; 430 + 431 + bytes = bits = pages = 0; 432 + for (i = 0; i < check_len; i += pgsize) 433 + if (countdiffs(written, read, i, pgsize, &bytes, 434 + &bits) >= 0) 435 + pages++; 436 + 437 + printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n", 438 + pages, bytes, bits); 439 + printk(PRINT_PREF "The following is a list of all differences between" 440 + " what was read from flash and what was expected\n"); 441 + 442 + for (i = 0; i < check_len; i += pgsize) { 443 + cond_resched(); 444 + bytes = bits = 0; 445 + first = countdiffs(written, read, i, pgsize, &bytes, 446 + &bits); 447 + if (first < 0) 448 + continue; 449 + 450 + printk("-------------------------------------------------------" 451 + "----------------------------------\n"); 452 + 453 + printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify," 454 + " starting at offset 0x%x\n", 455 + (mtd->erasesize - check_len + i) / pgsize, 456 + bytes, bits, first); 457 + 458 + offset = first & ~0x7; 459 + len = ((first + bytes) | 0x7) + 1 - offset; 460 + 461 + print_bufs(read, written, offset, len); 462 + } 463 + } 464 + 465 + static void print_bufs(unsigned char *read, unsigned char *written, int start, 466 + int len) 467 + { 468 + int i = 0, j1, j2; 469 + char *diff; 470 + 471 + printk("Offset Read Written\n"); 472 + while (i < len) { 473 + printk("0x%08x: ", start + i); 474 + diff = " "; 475 + for (j1 = 0; j1 < 8 && i + j1 < len; j1++) { 476 + printk(" %02x", read[start + i + j1]); 477 + if (read[start + i + j1] != written[start + i + j1]) 478 + diff = "***"; 479 + } 480 + 481 + while (j1 < 8) { 482 + printk(" "); 483 + j1 += 1; 484 + } 485 + 486 + printk(" %s ", diff); 487 + 488 + for (j2 = 0; j2 < 8 && i + j2 < len; j2++) 489 + printk(" %02x", written[start + i + j2]); 490 + printk("\n"); 491 + i += 8; 492 + } 493 + } 494 + 495 + /* 496 + * Count the number of differing bytes and bits and return the first differing 497 + * offset. 498 + */ 499 + static int countdiffs(unsigned char *buf, unsigned char *check_buf, 500 + unsigned offset, unsigned len, unsigned *bytesp, 501 + unsigned *bitsp) 502 + { 503 + unsigned i, bit; 504 + int first = -1; 505 + 506 + for (i = offset; i < offset + len; i++) 507 + if (buf[i] != check_buf[i]) { 508 + first = i; 509 + break; 510 + } 511 + 512 + while (i < offset + len) { 513 + if (buf[i] != check_buf[i]) { 514 + (*bytesp)++; 515 + bit = 1; 516 + while (bit < 256) { 517 + if ((buf[i] & bit) != (check_buf[i] & bit)) 518 + (*bitsp)++; 519 + bit <<= 1; 520 + } 521 + } 522 + i++; 523 + } 524 + 525 + return first; 526 + } 527 + 528 + MODULE_DESCRIPTION("Eraseblock torturing module"); 529 + MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter"); 530 + MODULE_LICENSE("GPL");
+1 -1
drivers/mtd/ubi/build.c
··· 561 561 */ 562 562 563 563 ubi->peb_size = ubi->mtd->erasesize; 564 - ubi->peb_count = ubi->mtd->size / ubi->mtd->erasesize; 564 + ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd); 565 565 ubi->flash_size = ubi->mtd->size; 566 566 567 567 if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
+9 -8
drivers/mtd/ubi/gluebi.c
··· 215 215 struct ubi_volume *vol; 216 216 struct ubi_device *ubi; 217 217 218 - dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr); 218 + dbg_gen("erase %llu bytes at offset %llu", (unsigned long long)instr->len, 219 + (unsigned long long)instr->addr); 219 220 220 221 if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) 221 222 return -EINVAL; ··· 224 223 if (instr->len < 0 || instr->addr + instr->len > mtd->size) 225 224 return -EINVAL; 226 225 227 - if (instr->addr % mtd->writesize || instr->len % mtd->writesize) 226 + if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd)) 228 227 return -EINVAL; 229 228 230 - lnum = instr->addr / mtd->erasesize; 231 - count = instr->len / mtd->erasesize; 229 + lnum = mtd_div_by_eb(instr->addr, mtd); 230 + count = mtd_div_by_eb(instr->len, mtd); 232 231 233 232 vol = container_of(mtd, struct ubi_volume, gluebi_mtd); 234 233 ubi = vol->ubi; ··· 256 255 257 256 out_err: 258 257 instr->state = MTD_ERASE_FAILED; 259 - instr->fail_addr = lnum * mtd->erasesize; 258 + instr->fail_addr = (long long)lnum * mtd->erasesize; 260 259 return err; 261 260 } 262 261 ··· 295 294 * bytes. 296 295 */ 297 296 if (vol->vol_type == UBI_DYNAMIC_VOLUME) 298 - mtd->size = vol->usable_leb_size * vol->reserved_pebs; 297 + mtd->size = (long long)vol->usable_leb_size * vol->reserved_pebs; 299 298 else 300 299 mtd->size = vol->used_bytes; 301 300 ··· 305 304 return -ENFILE; 306 305 } 307 306 308 - dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u", 309 - mtd->index, mtd->name, mtd->size, mtd->erasesize); 307 + dbg_gen("added mtd%d (\"%s\"), size %llu, EB size %u", 308 + mtd->index, mtd->name, (unsigned long long)mtd->size, mtd->erasesize); 310 309 return 0; 311 310 } 312 311
+64 -56
fs/jffs2/compr_rubin.c
··· 22 22 23 23 24 24 #define BIT_DIVIDER_MIPS 1043 25 - static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ 26 - 27 - #include <linux/errno.h> 25 + static int bits_mips[8] = { 277, 249, 290, 267, 229, 341, 212, 241}; 28 26 29 27 struct pushpull { 30 28 unsigned char *buf; ··· 41 43 int bits[8]; 42 44 }; 43 45 44 - static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) 46 + static inline void init_pushpull(struct pushpull *pp, char *buf, 47 + unsigned buflen, unsigned ofs, 48 + unsigned reserve) 45 49 { 46 50 pp->buf = buf; 47 51 pp->buflen = buflen; ··· 53 53 54 54 static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) 55 55 { 56 - if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { 56 + if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) 57 57 return -ENOSPC; 58 - } 59 58 60 - if (bit) { 61 - pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); 62 - } 63 - else { 64 - pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); 65 - } 59 + if (bit) 60 + pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs & 7))); 61 + else 62 + pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs & 7))); 63 + 66 64 pp->ofs++; 67 65 68 66 return 0; ··· 95 97 rs->p = (long) (2 * UPPER_BIT_RUBIN); 96 98 rs->bit_number = (long) 0; 97 99 rs->bit_divider = div; 100 + 98 101 for (c=0; c<8; c++) 99 102 rs->bits[c] = bits[c]; 100 103 } ··· 107 108 long i0, i1; 108 109 int ret; 109 110 110 - while ((rs->q >= UPPER_BIT_RUBIN) || ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { 111 + while ((rs->q >= UPPER_BIT_RUBIN) || 112 + ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { 111 113 rs->bit_number++; 112 114 113 115 ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0); ··· 119 119 rs->p <<= 1; 120 120 } 121 121 i0 = A * rs->p / (A + B); 122 - if (i0 <= 0) { 122 + if (i0 <= 0) 123 123 i0 = 1; 124 - } 125 - if (i0 >= rs->p) { 124 + 125 + if (i0 >= rs->p) 126 126 i0 = rs->p - 1; 127 - } 127 + 128 128 i1 = rs->p - i0; 129 129 130 130 if (symbol == 0) ··· 157 157 /* behalve lower */ 158 158 rs->rec_q = 0; 159 159 160 - for (rs->bit_number = 0; rs->bit_number++ < RUBIN_REG_SIZE; rs->rec_q = rs->rec_q * 2 + (long) (pullbit(&rs->pp))) 160 + for (rs->bit_number = 0; rs->bit_number++ < RUBIN_REG_SIZE; 161 + rs->rec_q = rs->rec_q * 2 + (long) (pullbit(&rs->pp))) 161 162 ; 162 163 } 163 164 164 - static void __do_decode(struct rubin_state *rs, unsigned long p, unsigned long q) 165 + static void __do_decode(struct rubin_state *rs, unsigned long p, 166 + unsigned long q) 165 167 { 166 168 register unsigned long lower_bits_rubin = LOWER_BITS_RUBIN; 167 169 unsigned long rec_q; ··· 209 207 __do_decode(rs, p, q); 210 208 211 209 i0 = A * rs->p / (A + B); 212 - if (i0 <= 0) { 210 + if (i0 <= 0) 213 211 i0 = 1; 214 - } 215 - if (i0 >= rs->p) { 212 + 213 + if (i0 >= rs->p) 216 214 i0 = rs->p - 1; 217 - } 218 215 219 216 threshold = rs->q + i0; 220 217 symbol = rs->rec_q >= threshold; ··· 235 234 struct rubin_state rs_copy; 236 235 rs_copy = *rs; 237 236 238 - for (i=0;i<8;i++) { 239 - ret = encode(rs, rs->bit_divider-rs->bits[i],rs->bits[i],byte&1); 237 + for (i=0; i<8; i++) { 238 + ret = encode(rs, rs->bit_divider-rs->bits[i], 239 + rs->bits[i], byte & 1); 240 240 if (ret) { 241 241 /* Failed. Restore old state */ 242 242 *rs = rs_copy; 243 243 return ret; 244 244 } 245 - byte=byte>>1; 245 + byte >>= 1 ; 246 246 } 247 247 return 0; 248 248 } ··· 253 251 int i, result = 0, bit_divider = rs->bit_divider; 254 252 255 253 for (i = 0; i < 8; i++) 256 - result |= decode(rs, bit_divider - rs->bits[i], rs->bits[i]) << i; 254 + result |= decode(rs, bit_divider - rs->bits[i], 255 + rs->bits[i]) << i; 257 256 258 257 return result; 259 258 } ··· 262 259 263 260 264 261 static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, 265 - unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) 262 + unsigned char *cpage_out, uint32_t *sourcelen, 263 + uint32_t *dstlen) 266 264 { 267 265 int outpos = 0; 268 266 int pos=0; ··· 299 295 int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, 300 296 uint32_t *sourcelen, uint32_t *dstlen, void *model) 301 297 { 302 - return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); 298 + return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, 299 + cpage_out, sourcelen, dstlen); 303 300 } 304 301 #endif 305 302 static int jffs2_dynrubin_compress(unsigned char *data_in, ··· 321 316 return -1; 322 317 323 318 memset(histo, 0, 256); 324 - for (i=0; i<mysrclen; i++) { 319 + for (i=0; i<mysrclen; i++) 325 320 histo[data_in[i]]++; 326 - } 327 321 memset(bits, 0, sizeof(int)*8); 328 322 for (i=0; i<256; i++) { 329 323 if (i&128) ··· 350 346 cpage_out[i] = bits[i]; 351 347 } 352 348 353 - ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, &mydstlen); 349 + ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, 350 + &mydstlen); 354 351 if (ret) 355 352 return ret; 356 353 ··· 368 363 return 0; 369 364 } 370 365 371 - static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, 372 - unsigned char *page_out, uint32_t srclen, uint32_t destlen) 366 + static void rubin_do_decompress(int bit_divider, int *bits, 367 + unsigned char *cdata_in, 368 + unsigned char *page_out, uint32_t srclen, 369 + uint32_t destlen) 373 370 { 374 371 int outpos = 0; 375 372 struct rubin_state rs; ··· 379 372 init_pushpull(&rs.pp, cdata_in, srclen, 0, 0); 380 373 init_decode(&rs, bit_divider, bits); 381 374 382 - while (outpos < destlen) { 375 + while (outpos < destlen) 383 376 page_out[outpos++] = in_byte(&rs); 384 - } 385 377 } 386 378 387 379 ··· 389 383 uint32_t sourcelen, uint32_t dstlen, 390 384 void *model) 391 385 { 392 - rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); 386 + rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, 387 + cpage_out, sourcelen, dstlen); 393 388 return 0; 394 389 } 395 390 ··· 405 398 for (c=0; c<8; c++) 406 399 bits[c] = data_in[c]; 407 400 408 - rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen); 401 + rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, 402 + dstlen); 409 403 return 0; 410 404 } 411 405 412 406 static struct jffs2_compressor jffs2_rubinmips_comp = { 413 - .priority = JFFS2_RUBINMIPS_PRIORITY, 414 - .name = "rubinmips", 415 - .compr = JFFS2_COMPR_DYNRUBIN, 416 - .compress = NULL, /*&jffs2_rubinmips_compress,*/ 417 - .decompress = &jffs2_rubinmips_decompress, 407 + .priority = JFFS2_RUBINMIPS_PRIORITY, 408 + .name = "rubinmips", 409 + .compr = JFFS2_COMPR_DYNRUBIN, 410 + .compress = NULL, /*&jffs2_rubinmips_compress,*/ 411 + .decompress = &jffs2_rubinmips_decompress, 418 412 #ifdef JFFS2_RUBINMIPS_DISABLED 419 - .disabled = 1, 413 + .disabled = 1, 420 414 #else 421 - .disabled = 0, 415 + .disabled = 0, 422 416 #endif 423 417 }; 424 418 425 419 int jffs2_rubinmips_init(void) 426 420 { 427 - return jffs2_register_compressor(&jffs2_rubinmips_comp); 421 + return jffs2_register_compressor(&jffs2_rubinmips_comp); 428 422 } 429 423 430 424 void jffs2_rubinmips_exit(void) 431 425 { 432 - jffs2_unregister_compressor(&jffs2_rubinmips_comp); 426 + jffs2_unregister_compressor(&jffs2_rubinmips_comp); 433 427 } 434 428 435 429 static struct jffs2_compressor jffs2_dynrubin_comp = { 436 - .priority = JFFS2_DYNRUBIN_PRIORITY, 437 - .name = "dynrubin", 438 - .compr = JFFS2_COMPR_RUBINMIPS, 439 - .compress = jffs2_dynrubin_compress, 440 - .decompress = &jffs2_dynrubin_decompress, 430 + .priority = JFFS2_DYNRUBIN_PRIORITY, 431 + .name = "dynrubin", 432 + .compr = JFFS2_COMPR_RUBINMIPS, 433 + .compress = jffs2_dynrubin_compress, 434 + .decompress = &jffs2_dynrubin_decompress, 441 435 #ifdef JFFS2_DYNRUBIN_DISABLED 442 - .disabled = 1, 436 + .disabled = 1, 443 437 #else 444 - .disabled = 0, 438 + .disabled = 0, 445 439 #endif 446 440 }; 447 441 448 442 int jffs2_dynrubin_init(void) 449 443 { 450 - return jffs2_register_compressor(&jffs2_dynrubin_comp); 444 + return jffs2_register_compressor(&jffs2_dynrubin_comp); 451 445 } 452 446 453 447 void jffs2_dynrubin_exit(void) 454 448 { 455 - jffs2_unregister_compressor(&jffs2_dynrubin_comp); 449 + jffs2_unregister_compressor(&jffs2_dynrubin_comp); 456 450 }
+3 -2
fs/jffs2/erase.c
··· 175 175 { 176 176 /* For NAND, if the failure did not occur at the device level for a 177 177 specific physical page, don't bother updating the bad block table. */ 178 - if (jffs2_cleanmarker_oob(c) && (bad_offset != MTD_FAIL_ADDR_UNKNOWN)) { 178 + if (jffs2_cleanmarker_oob(c) && (bad_offset != (uint32_t)MTD_FAIL_ADDR_UNKNOWN)) { 179 179 /* We had a device-level failure to erase. Let's see if we've 180 180 failed too many times. */ 181 181 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { ··· 209 209 struct erase_priv_struct *priv = (void *)instr->priv; 210 210 211 211 if(instr->state != MTD_ERASE_DONE) { 212 - printk(KERN_WARNING "Erase at 0x%08x finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", instr->addr, instr->state); 212 + printk(KERN_WARNING "Erase at 0x%08llx finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", 213 + (unsigned long long)instr->addr, instr->state); 213 214 jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr); 214 215 } else { 215 216 jffs2_erase_succeeded(priv->c, priv->jeb);
+1
include/linux/mtd/cfi.h
··· 520 520 521 521 #define CFI_MFR_AMD 0x0001 522 522 #define CFI_MFR_ATMEL 0x001F 523 + #define CFI_MFR_SAMSUNG 0x00EC 523 524 #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ 524 525 525 526 void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
+19 -19
include/linux/mtd/ftl.h
··· 32 32 #define _LINUX_FTL_H 33 33 34 34 typedef struct erase_unit_header_t { 35 - u_int8_t LinkTargetTuple[5]; 36 - u_int8_t DataOrgTuple[10]; 37 - u_int8_t NumTransferUnits; 38 - u_int32_t EraseCount; 39 - u_int16_t LogicalEUN; 40 - u_int8_t BlockSize; 41 - u_int8_t EraseUnitSize; 42 - u_int16_t FirstPhysicalEUN; 43 - u_int16_t NumEraseUnits; 44 - u_int32_t FormattedSize; 45 - u_int32_t FirstVMAddress; 46 - u_int16_t NumVMPages; 47 - u_int8_t Flags; 48 - u_int8_t Code; 49 - u_int32_t SerialNumber; 50 - u_int32_t AltEUHOffset; 51 - u_int32_t BAMOffset; 52 - u_int8_t Reserved[12]; 53 - u_int8_t EndTuple[2]; 35 + uint8_t LinkTargetTuple[5]; 36 + uint8_t DataOrgTuple[10]; 37 + uint8_t NumTransferUnits; 38 + uint32_t EraseCount; 39 + uint16_t LogicalEUN; 40 + uint8_t BlockSize; 41 + uint8_t EraseUnitSize; 42 + uint16_t FirstPhysicalEUN; 43 + uint16_t NumEraseUnits; 44 + uint32_t FormattedSize; 45 + uint32_t FirstVMAddress; 46 + uint16_t NumVMPages; 47 + uint8_t Flags; 48 + uint8_t Code; 49 + uint32_t SerialNumber; 50 + uint32_t AltEUHOffset; 51 + uint32_t BAMOffset; 52 + uint8_t Reserved[12]; 53 + uint8_t EndTuple[2]; 54 54 } erase_unit_header_t; 55 55 56 56 /* Flags in erase_unit_header_t */
+1
include/linux/mtd/map.h
··· 223 223 must leave it enabled. */ 224 224 void (*set_vpp)(struct map_info *, int); 225 225 226 + unsigned long pfow_base; 226 227 unsigned long map_priv_1; 227 228 unsigned long map_priv_2; 228 229 void *fldrv_priv;
+58 -17
include/linux/mtd/mtd.h
··· 15 15 #include <linux/mtd/compatmac.h> 16 16 #include <mtd/mtd-abi.h> 17 17 18 + #include <asm/div64.h> 19 + 18 20 #define MTD_CHAR_MAJOR 90 19 21 #define MTD_BLOCK_MAJOR 31 20 22 #define MAX_MTD_DEVICES 32 ··· 27 25 #define MTD_ERASE_DONE 0x08 28 26 #define MTD_ERASE_FAILED 0x10 29 27 30 - #define MTD_FAIL_ADDR_UNKNOWN 0xffffffff 28 + #define MTD_FAIL_ADDR_UNKNOWN -1LL 31 29 32 30 /* If the erase fails, fail_addr might indicate exactly which block failed. If 33 31 fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not 34 32 specific to any particular block. */ 35 33 struct erase_info { 36 34 struct mtd_info *mtd; 37 - u_int32_t addr; 38 - u_int32_t len; 39 - u_int32_t fail_addr; 35 + uint64_t addr; 36 + uint64_t len; 37 + uint64_t fail_addr; 40 38 u_long time; 41 39 u_long retries; 42 - u_int dev; 43 - u_int cell; 40 + unsigned dev; 41 + unsigned cell; 44 42 void (*callback) (struct erase_info *self); 45 43 u_long priv; 46 44 u_char state; ··· 48 46 }; 49 47 50 48 struct mtd_erase_region_info { 51 - u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ 52 - u_int32_t erasesize; /* For this region */ 53 - u_int32_t numblocks; /* Number of blocks of erasesize in this region */ 49 + uint64_t offset; /* At which this region starts, from the beginning of the MTD */ 50 + uint32_t erasesize; /* For this region */ 51 + uint32_t numblocks; /* Number of blocks of erasesize in this region */ 54 52 unsigned long *lockmap; /* If keeping bitmap of locks */ 55 53 }; 56 54 ··· 102 100 103 101 struct mtd_info { 104 102 u_char type; 105 - u_int32_t flags; 106 - u_int32_t size; // Total size of the MTD 103 + uint32_t flags; 104 + uint64_t size; // Total size of the MTD 107 105 108 106 /* "Major" erase size for the device. Naïve users may take this 109 107 * to be the only erase size available, or may use the more detailed 110 108 * information below if they desire 111 109 */ 112 - u_int32_t erasesize; 110 + uint32_t erasesize; 113 111 /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 114 112 * though individual bits can be cleared), in case of NAND flash it is 115 113 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR ··· 117 115 * Any driver registering a struct mtd_info must ensure a writesize of 118 116 * 1 or larger. 119 117 */ 120 - u_int32_t writesize; 118 + uint32_t writesize; 121 119 122 - u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) 123 - u_int32_t oobavail; // Available OOB bytes per block 120 + uint32_t oobsize; // Amount of OOB data per block (e.g. 16) 121 + uint32_t oobavail; // Available OOB bytes per block 122 + 123 + /* 124 + * If erasesize is a power of 2 then the shift is stored in 125 + * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. 126 + */ 127 + unsigned int erasesize_shift; 128 + unsigned int writesize_shift; 129 + /* Masks based on erasesize_shift and writesize_shift */ 130 + unsigned int erasesize_mask; 131 + unsigned int writesize_mask; 124 132 125 133 // Kernel-only stuff starts here. 126 134 const char *name; ··· 202 190 void (*sync) (struct mtd_info *mtd); 203 191 204 192 /* Chip-supported device locking */ 205 - int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); 206 - int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); 193 + int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 194 + int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 207 195 208 196 /* Power Management functions */ 209 197 int (*suspend) (struct mtd_info *mtd); ··· 233 221 void (*put_device) (struct mtd_info *mtd); 234 222 }; 235 223 224 + static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) 225 + { 226 + if (mtd->erasesize_shift) 227 + return sz >> mtd->erasesize_shift; 228 + do_div(sz, mtd->erasesize); 229 + return sz; 230 + } 231 + 232 + static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) 233 + { 234 + if (mtd->erasesize_shift) 235 + return sz & mtd->erasesize_mask; 236 + return do_div(sz, mtd->erasesize); 237 + } 238 + 239 + static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) 240 + { 241 + if (mtd->writesize_shift) 242 + return sz >> mtd->writesize_shift; 243 + do_div(sz, mtd->writesize); 244 + return sz; 245 + } 246 + 247 + static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) 248 + { 249 + if (mtd->writesize_shift) 250 + return sz & mtd->writesize_mask; 251 + return do_div(sz, mtd->writesize); 252 + } 236 253 237 254 /* Kernel-side ioctl definitions */ 238 255
+1 -6
include/linux/mtd/nand.h
··· 335 335 * @erase_cmd: [INTERN] erase command write function, selectable due to AND support 336 336 * @scan_bbt: [REPLACEABLE] function to scan bad block table 337 337 * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) 338 - * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress 339 338 * @state: [INTERN] the current state of the NAND device 340 339 * @oob_poi: poison value buffer 341 340 * @page_shift: [INTERN] number of address bits in a page (column address bits) 342 341 * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock 343 342 * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry 344 343 * @chip_shift: [INTERN] number of address bits in one chip 345 - * @datbuf: [INTERN] internal buffer for one page + oob 346 - * @oobbuf: [INTERN] oob buffer for one eraseblock 347 - * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized 348 - * @data_poi: [INTERN] pointer to a data buffer 349 344 * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about 350 345 * special functionality. See the defines for further explanation 351 346 * @badblockpos: [INTERN] position of the bad block marker in the oob area ··· 394 399 int bbt_erase_shift; 395 400 int chip_shift; 396 401 int numchips; 397 - unsigned long chipsize; 402 + uint64_t chipsize; 398 403 int pagemask; 399 404 int pagebuf; 400 405 int subpagesize;
+3 -3
include/linux/mtd/partitions.h
··· 36 36 37 37 struct mtd_partition { 38 38 char *name; /* identifier string */ 39 - u_int32_t size; /* partition size */ 40 - u_int32_t offset; /* offset within the master MTD space */ 41 - u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ 39 + uint64_t size; /* partition size */ 40 + uint64_t offset; /* offset within the master MTD space */ 41 + uint32_t mask_flags; /* master MTD flags to mask out for this partition */ 42 42 struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ 43 43 struct mtd_info **mtdp; /* pointer to store the MTD object */ 44 44 };
+159
include/linux/mtd/pfow.h
··· 1 + /* Primary function overlay window definitions 2 + * and service functions used by LPDDR chips 3 + */ 4 + #ifndef __LINUX_MTD_PFOW_H 5 + #define __LINUX_MTD_PFOW_H 6 + 7 + #include <linux/mtd/qinfo.h> 8 + 9 + /* PFOW registers addressing */ 10 + /* Address of symbol "P" */ 11 + #define PFOW_QUERY_STRING_P 0x0000 12 + /* Address of symbol "F" */ 13 + #define PFOW_QUERY_STRING_F 0x0002 14 + /* Address of symbol "O" */ 15 + #define PFOW_QUERY_STRING_O 0x0004 16 + /* Address of symbol "W" */ 17 + #define PFOW_QUERY_STRING_W 0x0006 18 + /* Identification info for LPDDR chip */ 19 + #define PFOW_MANUFACTURER_ID 0x0020 20 + #define PFOW_DEVICE_ID 0x0022 21 + /* Address in PFOW where prog buffer can can be found */ 22 + #define PFOW_PROGRAM_BUFFER_OFFSET 0x0040 23 + /* Size of program buffer in words */ 24 + #define PFOW_PROGRAM_BUFFER_SIZE 0x0042 25 + /* Address command code register */ 26 + #define PFOW_COMMAND_CODE 0x0080 27 + /* command data register */ 28 + #define PFOW_COMMAND_DATA 0x0084 29 + /* command address register lower address bits */ 30 + #define PFOW_COMMAND_ADDRESS_L 0x0088 31 + /* command address register upper address bits */ 32 + #define PFOW_COMMAND_ADDRESS_H 0x008a 33 + /* number of bytes to be proggrammed lower address bits */ 34 + #define PFOW_DATA_COUNT_L 0x0090 35 + /* number of bytes to be proggrammed higher address bits */ 36 + #define PFOW_DATA_COUNT_H 0x0092 37 + /* command execution register, the only possible value is 0x01 */ 38 + #define PFOW_COMMAND_EXECUTE 0x00c0 39 + /* 0x01 should be written at this address to clear buffer */ 40 + #define PFOW_CLEAR_PROGRAM_BUFFER 0x00c4 41 + /* device program/erase suspend register */ 42 + #define PFOW_PROGRAM_ERASE_SUSPEND 0x00c8 43 + /* device status register */ 44 + #define PFOW_DSR 0x00cc 45 + 46 + /* LPDDR memory device command codes */ 47 + /* They are possible values of PFOW command code register */ 48 + #define LPDDR_WORD_PROGRAM 0x0041 49 + #define LPDDR_BUFF_PROGRAM 0x00E9 50 + #define LPDDR_BLOCK_ERASE 0x0020 51 + #define LPDDR_LOCK_BLOCK 0x0061 52 + #define LPDDR_UNLOCK_BLOCK 0x0062 53 + #define LPDDR_READ_BLOCK_LOCK_STATUS 0x0065 54 + #define LPDDR_INFO_QUERY 0x0098 55 + #define LPDDR_READ_OTP 0x0097 56 + #define LPDDR_PROG_OTP 0x00C0 57 + #define LPDDR_RESUME 0x00D0 58 + 59 + /* Defines possible value of PFOW command execution register */ 60 + #define LPDDR_START_EXECUTION 0x0001 61 + 62 + /* Defines possible value of PFOW program/erase suspend register */ 63 + #define LPDDR_SUSPEND 0x0001 64 + 65 + /* Possible values of PFOW device status register */ 66 + /* access R - read; RC read & clearable */ 67 + #define DSR_DPS (1<<1) /* RC; device protect status 68 + * 0 - not protected 1 - locked */ 69 + #define DSR_PSS (1<<2) /* R; program suspend status; 70 + * 0-prog in progress/completed, 71 + * 1- prog suspended */ 72 + #define DSR_VPPS (1<<3) /* RC; 0-Vpp OK, * 1-Vpp low */ 73 + #define DSR_PROGRAM_STATUS (1<<4) /* RC; 0-successful, 1-error */ 74 + #define DSR_ERASE_STATUS (1<<5) /* RC; erase or blank check status; 75 + * 0-success erase/blank check, 76 + * 1 blank check error */ 77 + #define DSR_ESS (1<<6) /* R; erase suspend status; 78 + * 0-erase in progress/complete, 79 + * 1 erase suspended */ 80 + #define DSR_READY_STATUS (1<<7) /* R; Device status 81 + * 0-busy, 82 + * 1-ready */ 83 + #define DSR_RPS (0x3<<8) /* RC; region program status 84 + * 00 - Success, 85 + * 01-re-program attempt in region with 86 + * object mode data, 87 + * 10-object mode program w attempt in 88 + * region with control mode data 89 + * 11-attempt to program invalid half 90 + * with 0x41 command */ 91 + #define DSR_AOS (1<<12) /* RC; 1- AO related failure */ 92 + #define DSR_AVAILABLE (1<<15) /* R; Device availbility 93 + * 1 - Device available 94 + * 0 - not available */ 95 + 96 + /* The superset of all possible error bits in DSR */ 97 + #define DSR_ERR 0x133A 98 + 99 + static inline void send_pfow_command(struct map_info *map, 100 + unsigned long cmd_code, unsigned long adr, 101 + unsigned long len, map_word *datum) 102 + { 103 + int bits_per_chip = map_bankwidth(map) * 8; 104 + int chipnum; 105 + struct lpddr_private *lpddr = map->fldrv_priv; 106 + chipnum = adr >> lpddr->chipshift; 107 + 108 + map_write(map, CMD(cmd_code), map->pfow_base + PFOW_COMMAND_CODE); 109 + map_write(map, CMD(adr & ((1<<bits_per_chip) - 1)), 110 + map->pfow_base + PFOW_COMMAND_ADDRESS_L); 111 + map_write(map, CMD(adr>>bits_per_chip), 112 + map->pfow_base + PFOW_COMMAND_ADDRESS_H); 113 + if (len) { 114 + map_write(map, CMD(len & ((1<<bits_per_chip) - 1)), 115 + map->pfow_base + PFOW_DATA_COUNT_L); 116 + map_write(map, CMD(len>>bits_per_chip), 117 + map->pfow_base + PFOW_DATA_COUNT_H); 118 + } 119 + if (datum) 120 + map_write(map, *datum, map->pfow_base + PFOW_COMMAND_DATA); 121 + 122 + /* Command execution start */ 123 + map_write(map, CMD(LPDDR_START_EXECUTION), 124 + map->pfow_base + PFOW_COMMAND_EXECUTE); 125 + } 126 + 127 + static inline void print_drs_error(unsigned dsr) 128 + { 129 + int prog_status = (dsr & DSR_RPS) >> 8; 130 + 131 + if (!(dsr & DSR_AVAILABLE)) 132 + printk(KERN_NOTICE"DSR.15: (0) Device not Available\n"); 133 + if (prog_status & 0x03) 134 + printk(KERN_NOTICE"DSR.9,8: (11) Attempt to program invalid " 135 + "half with 41h command\n"); 136 + else if (prog_status & 0x02) 137 + printk(KERN_NOTICE"DSR.9,8: (10) Object Mode Program attempt " 138 + "in region with Control Mode data\n"); 139 + else if (prog_status & 0x01) 140 + printk(KERN_NOTICE"DSR.9,8: (01) Program attempt in region " 141 + "with Object Mode data\n"); 142 + if (!(dsr & DSR_READY_STATUS)) 143 + printk(KERN_NOTICE"DSR.7: (0) Device is Busy\n"); 144 + if (dsr & DSR_ESS) 145 + printk(KERN_NOTICE"DSR.6: (1) Erase Suspended\n"); 146 + if (dsr & DSR_ERASE_STATUS) 147 + printk(KERN_NOTICE"DSR.5: (1) Erase/Blank check error\n"); 148 + if (dsr & DSR_PROGRAM_STATUS) 149 + printk(KERN_NOTICE"DSR.4: (1) Program Error\n"); 150 + if (dsr & DSR_VPPS) 151 + printk(KERN_NOTICE"DSR.3: (1) Vpp low detect, operation " 152 + "aborted\n"); 153 + if (dsr & DSR_PSS) 154 + printk(KERN_NOTICE"DSR.2: (1) Program suspended\n"); 155 + if (dsr & DSR_DPS) 156 + printk(KERN_NOTICE"DSR.1: (1) Aborted Erase/Program attempt " 157 + "on locked block\n"); 158 + } 159 + #endif /* __LINUX_MTD_PFOW_H */
+1
include/linux/mtd/physmap.h
··· 24 24 unsigned int width; 25 25 void (*set_vpp)(struct map_info *, int); 26 26 unsigned int nr_parts; 27 + unsigned int pfow_base; 27 28 struct mtd_partition *parts; 28 29 }; 29 30
+91
include/linux/mtd/qinfo.h
··· 1 + #ifndef __LINUX_MTD_QINFO_H 2 + #define __LINUX_MTD_QINFO_H 3 + 4 + #include <linux/mtd/map.h> 5 + #include <linux/wait.h> 6 + #include <linux/spinlock.h> 7 + #include <linux/delay.h> 8 + #include <linux/mtd/mtd.h> 9 + #include <linux/mtd/flashchip.h> 10 + #include <linux/mtd/partitions.h> 11 + 12 + /* lpddr_private describes lpddr flash chip in memory map 13 + * @ManufactId - Chip Manufacture ID 14 + * @DevId - Chip Device ID 15 + * @qinfo - pointer to qinfo records describing the chip 16 + * @numchips - number of chips including virual RWW partitions 17 + * @chipshift - Chip/partiton size 2^chipshift 18 + * @chips - per-chip data structure 19 + */ 20 + struct lpddr_private { 21 + uint16_t ManufactId; 22 + uint16_t DevId; 23 + struct qinfo_chip *qinfo; 24 + int numchips; 25 + unsigned long chipshift; 26 + struct flchip chips[0]; 27 + }; 28 + 29 + /* qinfo_query_info structure contains request information for 30 + * each qinfo record 31 + * @major - major number of qinfo record 32 + * @major - minor number of qinfo record 33 + * @id_str - descriptive string to access the record 34 + * @desc - detailed description for the qinfo record 35 + */ 36 + struct qinfo_query_info { 37 + uint8_t major; 38 + uint8_t minor; 39 + char *id_str; 40 + char *desc; 41 + }; 42 + 43 + /* 44 + * qinfo_chip structure contains necessary qinfo records data 45 + * @DevSizeShift - Device size 2^n bytes 46 + * @BufSizeShift - Program buffer size 2^n bytes 47 + * @TotalBlocksNum - Total number of blocks 48 + * @UniformBlockSizeShift - Uniform block size 2^UniformBlockSizeShift bytes 49 + * @HWPartsNum - Number of hardware partitions 50 + * @SuspEraseSupp - Suspend erase supported 51 + * @SingleWordProgTime - Single word program 2^SingleWordProgTime u-sec 52 + * @ProgBufferTime - Program buffer write 2^ProgBufferTime u-sec 53 + * @BlockEraseTime - Block erase 2^BlockEraseTime m-sec 54 + */ 55 + struct qinfo_chip { 56 + /* General device info */ 57 + uint16_t DevSizeShift; 58 + uint16_t BufSizeShift; 59 + /* Erase block information */ 60 + uint16_t TotalBlocksNum; 61 + uint16_t UniformBlockSizeShift; 62 + /* Partition information */ 63 + uint16_t HWPartsNum; 64 + /* Optional features */ 65 + uint16_t SuspEraseSupp; 66 + /* Operation typical time */ 67 + uint16_t SingleWordProgTime; 68 + uint16_t ProgBufferTime; 69 + uint16_t BlockEraseTime; 70 + }; 71 + 72 + /* defines for fixup usage */ 73 + #define LPDDR_MFR_ANY 0xffff 74 + #define LPDDR_ID_ANY 0xffff 75 + #define NUMONYX_MFGR_ID 0x0089 76 + #define R18_DEVICE_ID_1G 0x893c 77 + 78 + static inline map_word lpddr_build_cmd(u_long cmd, struct map_info *map) 79 + { 80 + map_word val = { {0} }; 81 + val.x[0] = cmd; 82 + return val; 83 + } 84 + 85 + #define CMD(x) lpddr_build_cmd(x, map) 86 + #define CMDVAL(cmd) cmd.x[0] 87 + 88 + struct mtd_info *lpddr_cmdset(struct map_info *); 89 + 90 + #endif 91 +
+20
include/linux/mtd/sharpsl.h
··· 1 + /* 2 + * SharpSL NAND support 3 + * 4 + * Copyright (C) 2008 Dmitry Baryshkov 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/mtd/nand.h> 12 + #include <linux/mtd/nand_ecc.h> 13 + #include <linux/mtd/partitions.h> 14 + 15 + struct sharpsl_nand_platform_data { 16 + struct nand_bbt_descr *badblock_pattern; 17 + struct nand_ecclayout *ecc_layout; 18 + struct mtd_partition *partitions; 19 + unsigned int nr_partitions; 20 + };