diff options
author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2008-05-30 08:56:26 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2008-06-04 12:47:52 -0400 |
commit | 6eda7a55f786b75e7d3d636a9431e6c850b20d72 (patch) | |
tree | 04d762f049315d0173230ecf89d86f912d9adce9 /drivers/mtd/nand/nandsim.c | |
parent | 07293b20083cb66df35bf2041f0c554eaac43e8c (diff) |
[MTD] [NAND] nandsim: allow for 64-bit size
Amend nandsim so that it does not assume 32-bit flash size.
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand/nandsim.c')
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index b48051684733..68c150c8ff9d 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -298,11 +298,11 @@ struct nandsim { | |||
298 | 298 | ||
299 | /* NAND flash "geometry" */ | 299 | /* NAND flash "geometry" */ |
300 | struct nandsin_geometry { | 300 | struct nandsin_geometry { |
301 | uint32_t totsz; /* total flash size, bytes */ | 301 | uint64_t totsz; /* total flash size, bytes */ |
302 | uint32_t secsz; /* flash sector (erase block) size, bytes */ | 302 | uint32_t secsz; /* flash sector (erase block) size, bytes */ |
303 | uint pgsz; /* NAND flash page size, bytes */ | 303 | uint pgsz; /* NAND flash page size, bytes */ |
304 | uint oobsz; /* page OOB area size, bytes */ | 304 | uint oobsz; /* page OOB area size, bytes */ |
305 | uint32_t totszoob; /* total flash size including OOB, bytes */ | 305 | uint64_t totszoob; /* total flash size including OOB, bytes */ |
306 | uint pgszoob; /* page size including OOB , bytes*/ | 306 | uint pgszoob; /* page size including OOB , bytes*/ |
307 | uint secszoob; /* sector size including OOB, bytes */ | 307 | uint secszoob; /* sector size including OOB, bytes */ |
308 | uint pgnum; /* total number of pages */ | 308 | uint pgnum; /* total number of pages */ |
@@ -459,6 +459,12 @@ static char *get_partition_name(int i) | |||
459 | return kstrdup(buf, GFP_KERNEL); | 459 | return kstrdup(buf, GFP_KERNEL); |
460 | } | 460 | } |
461 | 461 | ||
462 | static u_int64_t divide(u_int64_t n, u_int32_t d) | ||
463 | { | ||
464 | do_div(n, d); | ||
465 | return n; | ||
466 | } | ||
467 | |||
462 | /* | 468 | /* |
463 | * Initialize the nandsim structure. | 469 | * Initialize the nandsim structure. |
464 | * | 470 | * |
@@ -469,8 +475,8 @@ static int init_nandsim(struct mtd_info *mtd) | |||
469 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 475 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; |
470 | struct nandsim *ns = (struct nandsim *)(chip->priv); | 476 | struct nandsim *ns = (struct nandsim *)(chip->priv); |
471 | int i, ret = 0; | 477 | int i, ret = 0; |
472 | u_int32_t remains; | 478 | u_int64_t remains; |
473 | u_int32_t next_offset; | 479 | u_int64_t next_offset; |
474 | 480 | ||
475 | if (NS_IS_INITIALIZED(ns)) { | 481 | if (NS_IS_INITIALIZED(ns)) { |
476 | NS_ERR("init_nandsim: nandsim is already initialized\n"); | 482 | NS_ERR("init_nandsim: nandsim is already initialized\n"); |
@@ -487,8 +493,8 @@ static int init_nandsim(struct mtd_info *mtd) | |||
487 | ns->geom.oobsz = mtd->oobsize; | 493 | ns->geom.oobsz = mtd->oobsize; |
488 | ns->geom.secsz = mtd->erasesize; | 494 | ns->geom.secsz = mtd->erasesize; |
489 | ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; | 495 | ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; |
490 | ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz; | 496 | ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz); |
491 | ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz; | 497 | ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; |
492 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; | 498 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; |
493 | ns->geom.pgshift = chip->page_shift; | 499 | ns->geom.pgshift = chip->page_shift; |
494 | ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; | 500 | ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; |
@@ -537,15 +543,16 @@ static int init_nandsim(struct mtd_info *mtd) | |||
537 | remains = ns->geom.totsz; | 543 | remains = ns->geom.totsz; |
538 | next_offset = 0; | 544 | next_offset = 0; |
539 | for (i = 0; i < parts_num; ++i) { | 545 | for (i = 0; i < parts_num; ++i) { |
540 | unsigned long part = parts[i]; | 546 | u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz; |
541 | if (!part || part > remains / ns->geom.secsz) { | 547 | |
548 | if (!part_sz || part_sz > remains) { | ||
542 | NS_ERR("bad partition size.\n"); | 549 | NS_ERR("bad partition size.\n"); |
543 | ret = -EINVAL; | 550 | ret = -EINVAL; |
544 | goto error; | 551 | goto error; |
545 | } | 552 | } |
546 | ns->partitions[i].name = get_partition_name(i); | 553 | ns->partitions[i].name = get_partition_name(i); |
547 | ns->partitions[i].offset = next_offset; | 554 | ns->partitions[i].offset = next_offset; |
548 | ns->partitions[i].size = part * ns->geom.secsz; | 555 | ns->partitions[i].size = part_sz; |
549 | next_offset += ns->partitions[i].size; | 556 | next_offset += ns->partitions[i].size; |
550 | remains -= ns->partitions[i].size; | 557 | remains -= ns->partitions[i].size; |
551 | } | 558 | } |
@@ -573,7 +580,7 @@ static int init_nandsim(struct mtd_info *mtd) | |||
573 | if (ns->busw == 16) | 580 | if (ns->busw == 16) |
574 | NS_WARN("16-bit flashes support wasn't tested\n"); | 581 | NS_WARN("16-bit flashes support wasn't tested\n"); |
575 | 582 | ||
576 | printk("flash size: %u MiB\n", ns->geom.totsz >> 20); | 583 | printk("flash size: %llu MiB\n", ns->geom.totsz >> 20); |
577 | printk("page size: %u bytes\n", ns->geom.pgsz); | 584 | printk("page size: %u bytes\n", ns->geom.pgsz); |
578 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); | 585 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); |
579 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); | 586 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); |
@@ -583,7 +590,7 @@ static int init_nandsim(struct mtd_info *mtd) | |||
583 | printk("bits in sector size: %u\n", ns->geom.secshift); | 590 | printk("bits in sector size: %u\n", ns->geom.secshift); |
584 | printk("bits in page size: %u\n", ns->geom.pgshift); | 591 | printk("bits in page size: %u\n", ns->geom.pgshift); |
585 | printk("bits in OOB size: %u\n", ns->geom.oobshift); | 592 | printk("bits in OOB size: %u\n", ns->geom.oobshift); |
586 | printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10); | 593 | printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10); |
587 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); | 594 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); |
588 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); | 595 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); |
589 | printk("options: %#x\n", ns->options); | 596 | printk("options: %#x\n", ns->options); |
@@ -825,7 +832,7 @@ static int setup_wear_reporting(struct mtd_info *mtd) | |||
825 | 832 | ||
826 | if (!rptwear) | 833 | if (!rptwear) |
827 | return 0; | 834 | return 0; |
828 | wear_eb_count = mtd->size / mtd->erasesize; | 835 | wear_eb_count = divide(mtd->size, mtd->erasesize); |
829 | mem = wear_eb_count * sizeof(unsigned long); | 836 | mem = wear_eb_count * sizeof(unsigned long); |
830 | if (mem / sizeof(unsigned long) != wear_eb_count) { | 837 | if (mem / sizeof(unsigned long) != wear_eb_count) { |
831 | NS_ERR("Too many erase blocks for wear reporting\n"); | 838 | NS_ERR("Too many erase blocks for wear reporting\n"); |
@@ -2013,7 +2020,7 @@ static int __init ns_init_module(void) | |||
2013 | } | 2020 | } |
2014 | 2021 | ||
2015 | if (overridesize) { | 2022 | if (overridesize) { |
2016 | u_int32_t new_size = nsmtd->erasesize << overridesize; | 2023 | u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize; |
2017 | if (new_size >> overridesize != nsmtd->erasesize) { | 2024 | if (new_size >> overridesize != nsmtd->erasesize) { |
2018 | NS_ERR("overridesize is too big\n"); | 2025 | NS_ERR("overridesize is too big\n"); |
2019 | goto err_exit; | 2026 | goto err_exit; |
@@ -2021,7 +2028,7 @@ static int __init ns_init_module(void) | |||
2021 | /* N.B. This relies on nand_scan not doing anything with the size before we change it */ | 2028 | /* N.B. This relies on nand_scan not doing anything with the size before we change it */ |
2022 | nsmtd->size = new_size; | 2029 | nsmtd->size = new_size; |
2023 | chip->chipsize = new_size; | 2030 | chip->chipsize = new_size; |
2024 | chip->chip_shift = ffs(new_size) - 1; | 2031 | chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1; |
2025 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; | 2032 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; |
2026 | } | 2033 | } |
2027 | 2034 | ||