aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nandsim.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 23:30:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 23:30:56 -0400
commit9ee08c2df47c10ba624ff05a6c0f2500748bcb69 (patch)
tree0a2788abb3b5547b83965e0b3132eec8b196bd81 /drivers/mtd/nand/nandsim.c
parenteaf0ba5ef69538b6913525294a3a0fcb0e0992e0 (diff)
parent3d45955962496879dead8d4dd70bb9a23b07154b (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (57 commits) [MTD] [NAND] subpage read feature as a way to increase performance. CPUFREQ: S3C24XX NAND driver frequency scaling support. [MTD][NAND] au1550nd: remove unused variable [MTD] jedec_probe: Fix SST 16-bit chip detection [MTD][MTDPART] Fix a division by zero bug [MTD][MTDPART] Cleanup and document the erase region handling [MTD][MTDPART] Handle most checkpatch findings [MTD][MTDPART] Seperate main loop from per-partition code in add_mtd_partition [MTD] physmap: resume already suspended chips on failure to suspend [MTD] physmap: Fix suspend/resume/shutdown bugs. [MTD] [NOR] Fix -ETIMEO errors in CFI driver [MTD] [NAND] fsl_elbc_nand: fix section mismatch with CONFIG_MTD_OF_PARTS=y [JFFS2] Use .unlocked_ioctl [MTD] Fix const assignment in the MTD command line partitioning driver [MTD] [NOR] gen_probe: No debug message when debugging is disabled [MTD] [NAND] remove __PPC__ hardcoded address from DiskOnChip drivers [MTD] [MAPS] Remove the bast-flash driver. [MTD] [NAND] fsl_elbc_nand: ecclayout cleanups [MTD] [NAND] fsl_elbc_nand: implement support for flash-based BBT [MTD] [NAND] fsl_elbc_nand: fix OOB workability for large page NAND chips ...
Diffstat (limited to 'drivers/mtd/nand/nandsim.c')
-rw-r--r--drivers/mtd/nand/nandsim.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index bb885d1fcab5..ecd70e2504f6 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -21,8 +21,6 @@
21 * You should have received a copy of the GNU General Public License 21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software 22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
25 * $Id: nandsim.c,v 1.8 2005/03/19 15:33:56 dedekind Exp $
26 */ 24 */
27 25
28#include <linux/init.h> 26#include <linux/init.h>
@@ -39,6 +37,7 @@
39#include <linux/delay.h> 37#include <linux/delay.h>
40#include <linux/list.h> 38#include <linux/list.h>
41#include <linux/random.h> 39#include <linux/random.h>
40#include <asm/div64.h>
42 41
43/* Default simulator parameters values */ 42/* Default simulator parameters values */
44#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ 43#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -298,11 +297,11 @@ struct nandsim {
298 297
299 /* NAND flash "geometry" */ 298 /* NAND flash "geometry" */
300 struct nandsin_geometry { 299 struct nandsin_geometry {
301 uint32_t totsz; /* total flash size, bytes */ 300 uint64_t totsz; /* total flash size, bytes */
302 uint32_t secsz; /* flash sector (erase block) size, bytes */ 301 uint32_t secsz; /* flash sector (erase block) size, bytes */
303 uint pgsz; /* NAND flash page size, bytes */ 302 uint pgsz; /* NAND flash page size, bytes */
304 uint oobsz; /* page OOB area size, bytes */ 303 uint oobsz; /* page OOB area size, bytes */
305 uint32_t totszoob; /* total flash size including OOB, bytes */ 304 uint64_t totszoob; /* total flash size including OOB, bytes */
306 uint pgszoob; /* page size including OOB , bytes*/ 305 uint pgszoob; /* page size including OOB , bytes*/
307 uint secszoob; /* sector size including OOB, bytes */ 306 uint secszoob; /* sector size including OOB, bytes */
308 uint pgnum; /* total number of pages */ 307 uint pgnum; /* total number of pages */
@@ -459,6 +458,12 @@ static char *get_partition_name(int i)
459 return kstrdup(buf, GFP_KERNEL); 458 return kstrdup(buf, GFP_KERNEL);
460} 459}
461 460
461static u_int64_t divide(u_int64_t n, u_int32_t d)
462{
463 do_div(n, d);
464 return n;
465}
466
462/* 467/*
463 * Initialize the nandsim structure. 468 * Initialize the nandsim structure.
464 * 469 *
@@ -469,8 +474,8 @@ static int init_nandsim(struct mtd_info *mtd)
469 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 474 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
470 struct nandsim *ns = (struct nandsim *)(chip->priv); 475 struct nandsim *ns = (struct nandsim *)(chip->priv);
471 int i, ret = 0; 476 int i, ret = 0;
472 u_int32_t remains; 477 u_int64_t remains;
473 u_int32_t next_offset; 478 u_int64_t next_offset;
474 479
475 if (NS_IS_INITIALIZED(ns)) { 480 if (NS_IS_INITIALIZED(ns)) {
476 NS_ERR("init_nandsim: nandsim is already initialized\n"); 481 NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -487,8 +492,8 @@ static int init_nandsim(struct mtd_info *mtd)
487 ns->geom.oobsz = mtd->oobsize; 492 ns->geom.oobsz = mtd->oobsize;
488 ns->geom.secsz = mtd->erasesize; 493 ns->geom.secsz = mtd->erasesize;
489 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; 494 ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
490 ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz; 495 ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz);
491 ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz; 496 ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
492 ns->geom.secshift = ffs(ns->geom.secsz) - 1; 497 ns->geom.secshift = ffs(ns->geom.secsz) - 1;
493 ns->geom.pgshift = chip->page_shift; 498 ns->geom.pgshift = chip->page_shift;
494 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; 499 ns->geom.oobshift = ffs(ns->geom.oobsz) - 1;
@@ -511,7 +516,7 @@ static int init_nandsim(struct mtd_info *mtd)
511 } 516 }
512 517
513 if (ns->options & OPT_SMALLPAGE) { 518 if (ns->options & OPT_SMALLPAGE) {
514 if (ns->geom.totsz < (32 << 20)) { 519 if (ns->geom.totsz <= (32 << 20)) {
515 ns->geom.pgaddrbytes = 3; 520 ns->geom.pgaddrbytes = 3;
516 ns->geom.secaddrbytes = 2; 521 ns->geom.secaddrbytes = 2;
517 } else { 522 } else {
@@ -537,15 +542,16 @@ static int init_nandsim(struct mtd_info *mtd)
537 remains = ns->geom.totsz; 542 remains = ns->geom.totsz;
538 next_offset = 0; 543 next_offset = 0;
539 for (i = 0; i < parts_num; ++i) { 544 for (i = 0; i < parts_num; ++i) {
540 unsigned long part = parts[i]; 545 u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz;
541 if (!part || part > remains / ns->geom.secsz) { 546
547 if (!part_sz || part_sz > remains) {
542 NS_ERR("bad partition size.\n"); 548 NS_ERR("bad partition size.\n");
543 ret = -EINVAL; 549 ret = -EINVAL;
544 goto error; 550 goto error;
545 } 551 }
546 ns->partitions[i].name = get_partition_name(i); 552 ns->partitions[i].name = get_partition_name(i);
547 ns->partitions[i].offset = next_offset; 553 ns->partitions[i].offset = next_offset;
548 ns->partitions[i].size = part * ns->geom.secsz; 554 ns->partitions[i].size = part_sz;
549 next_offset += ns->partitions[i].size; 555 next_offset += ns->partitions[i].size;
550 remains -= ns->partitions[i].size; 556 remains -= ns->partitions[i].size;
551 } 557 }
@@ -573,7 +579,7 @@ static int init_nandsim(struct mtd_info *mtd)
573 if (ns->busw == 16) 579 if (ns->busw == 16)
574 NS_WARN("16-bit flashes support wasn't tested\n"); 580 NS_WARN("16-bit flashes support wasn't tested\n");
575 581
576 printk("flash size: %u MiB\n", ns->geom.totsz >> 20); 582 printk("flash size: %llu MiB\n", ns->geom.totsz >> 20);
577 printk("page size: %u bytes\n", ns->geom.pgsz); 583 printk("page size: %u bytes\n", ns->geom.pgsz);
578 printk("OOB area size: %u bytes\n", ns->geom.oobsz); 584 printk("OOB area size: %u bytes\n", ns->geom.oobsz);
579 printk("sector size: %u KiB\n", ns->geom.secsz >> 10); 585 printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
@@ -583,7 +589,7 @@ static int init_nandsim(struct mtd_info *mtd)
583 printk("bits in sector size: %u\n", ns->geom.secshift); 589 printk("bits in sector size: %u\n", ns->geom.secshift);
584 printk("bits in page size: %u\n", ns->geom.pgshift); 590 printk("bits in page size: %u\n", ns->geom.pgshift);
585 printk("bits in OOB size: %u\n", ns->geom.oobshift); 591 printk("bits in OOB size: %u\n", ns->geom.oobshift);
586 printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10); 592 printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10);
587 printk("page address bytes: %u\n", ns->geom.pgaddrbytes); 593 printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
588 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 594 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
589 printk("options: %#x\n", ns->options); 595 printk("options: %#x\n", ns->options);
@@ -825,7 +831,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
825 831
826 if (!rptwear) 832 if (!rptwear)
827 return 0; 833 return 0;
828 wear_eb_count = mtd->size / mtd->erasesize; 834 wear_eb_count = divide(mtd->size, mtd->erasesize);
829 mem = wear_eb_count * sizeof(unsigned long); 835 mem = wear_eb_count * sizeof(unsigned long);
830 if (mem / sizeof(unsigned long) != wear_eb_count) { 836 if (mem / sizeof(unsigned long) != wear_eb_count) {
831 NS_ERR("Too many erase blocks for wear reporting\n"); 837 NS_ERR("Too many erase blocks for wear reporting\n");
@@ -2013,7 +2019,7 @@ static int __init ns_init_module(void)
2013 } 2019 }
2014 2020
2015 if (overridesize) { 2021 if (overridesize) {
2016 u_int32_t new_size = nsmtd->erasesize << overridesize; 2022 u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize;
2017 if (new_size >> overridesize != nsmtd->erasesize) { 2023 if (new_size >> overridesize != nsmtd->erasesize) {
2018 NS_ERR("overridesize is too big\n"); 2024 NS_ERR("overridesize is too big\n");
2019 goto err_exit; 2025 goto err_exit;
@@ -2021,7 +2027,8 @@ 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 */ 2027 /* N.B. This relies on nand_scan not doing anything with the size before we change it */
2022 nsmtd->size = new_size; 2028 nsmtd->size = new_size;
2023 chip->chipsize = new_size; 2029 chip->chipsize = new_size;
2024 chip->chip_shift = ffs(new_size) - 1; 2030 chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1;
2031 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
2025 } 2032 }
2026 2033
2027 if ((retval = setup_wear_reporting(nsmtd)) != 0) 2034 if ((retval = setup_wear_reporting(nsmtd)) != 0)