aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <ext-adrian.hunter@nokia.com>2007-03-19 06:46:43 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-04-17 13:54:50 -0400
commit2b77a0ed54eeea61937e7f71b0487b815edfbcdf (patch)
tree195b15275e8072841151025fd1729218cf689224
parentb0afbbec4981417f79e05865a36e57abfc289002 (diff)
[MTD] nandsim: add partition capability to nandsim
Enhance nandsim to be able to create more than 1 partition. A new module parameter 'parts' may be used to specify partition sizes. Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--drivers/mtd/nand/nandsim.c97
1 files changed, 73 insertions, 24 deletions
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index c3bca9590ad2..638e6c256d3e 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,6 +37,7 @@
37#include <linux/mtd/nand.h> 37#include <linux/mtd/nand.h>
38#include <linux/mtd/partitions.h> 38#include <linux/mtd/partitions.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/list.h>
40 41
41/* Default simulator parameters values */ 42/* Default simulator parameters values */
42#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ 43#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -90,6 +91,8 @@ static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH;
90static uint do_delays = CONFIG_NANDSIM_DO_DELAYS; 91static uint do_delays = CONFIG_NANDSIM_DO_DELAYS;
91static uint log = CONFIG_NANDSIM_LOG; 92static uint log = CONFIG_NANDSIM_LOG;
92static uint dbg = CONFIG_NANDSIM_DBG; 93static uint dbg = CONFIG_NANDSIM_DBG;
94static unsigned long parts[MAX_MTD_DEVICES];
95static unsigned int parts_num;
93 96
94module_param(first_id_byte, uint, 0400); 97module_param(first_id_byte, uint, 0400);
95module_param(second_id_byte, uint, 0400); 98module_param(second_id_byte, uint, 0400);
@@ -104,6 +107,7 @@ module_param(bus_width, uint, 0400);
104module_param(do_delays, uint, 0400); 107module_param(do_delays, uint, 0400);
105module_param(log, uint, 0400); 108module_param(log, uint, 0400);
106module_param(dbg, uint, 0400); 109module_param(dbg, uint, 0400);
110module_param_array(parts, ulong, &parts_num, 0400);
107 111
108MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)"); 112MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)");
109MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); 113MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
@@ -118,6 +122,7 @@ MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
118MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero"); 122MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero");
119MODULE_PARM_DESC(log, "Perform logging if not zero"); 123MODULE_PARM_DESC(log, "Perform logging if not zero");
120MODULE_PARM_DESC(dbg, "Output debug information if not zero"); 124MODULE_PARM_DESC(dbg, "Output debug information if not zero");
125MODULE_PARM_DESC(parts, "Partition sizes (in erase blocks) separated by commas");
121 126
122/* The largest possible page size */ 127/* The largest possible page size */
123#define NS_LARGEST_PAGE_SIZE 2048 128#define NS_LARGEST_PAGE_SIZE 2048
@@ -131,9 +136,9 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
131#define NS_DBG(args...) \ 136#define NS_DBG(args...) \
132 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0) 137 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0)
133#define NS_WARN(args...) \ 138#define NS_WARN(args...) \
134 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0) 139 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warning: " args); } while(0)
135#define NS_ERR(args...) \ 140#define NS_ERR(args...) \
136 do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0) 141 do { printk(KERN_ERR NS_OUTPUT_PREFIX " error: " args); } while(0)
137 142
138/* Busy-wait delay macros (microseconds, milliseconds) */ 143/* Busy-wait delay macros (microseconds, milliseconds) */
139#define NS_UDELAY(us) \ 144#define NS_UDELAY(us) \
@@ -238,7 +243,8 @@ union ns_mem {
238 * The structure which describes all the internal simulator data. 243 * The structure which describes all the internal simulator data.
239 */ 244 */
240struct nandsim { 245struct nandsim {
241 struct mtd_partition part; 246 struct mtd_partition partitions[MAX_MTD_DEVICES];
247 unsigned int nbparts;
242 248
243 uint busw; /* flash chip bus width (8 or 16) */ 249 uint busw; /* flash chip bus width (8 or 16) */
244 u_char ids[4]; /* chip's ID bytes */ 250 u_char ids[4]; /* chip's ID bytes */
@@ -381,6 +387,13 @@ static void free_device(struct nandsim *ns)
381 } 387 }
382} 388}
383 389
390static char *get_partition_name(int i)
391{
392 char buf[64];
393 sprintf(buf, "NAND simulator partition %d", i);
394 return kstrdup(buf, GFP_KERNEL);
395}
396
384/* 397/*
385 * Initialize the nandsim structure. 398 * Initialize the nandsim structure.
386 * 399 *
@@ -390,7 +403,9 @@ static int init_nandsim(struct mtd_info *mtd)
390{ 403{
391 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 404 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
392 struct nandsim *ns = (struct nandsim *)(chip->priv); 405 struct nandsim *ns = (struct nandsim *)(chip->priv);
393 int i; 406 int i, ret = 0;
407 u_int32_t remains;
408 u_int32_t next_offset;
394 409
395 if (NS_IS_INITIALIZED(ns)) { 410 if (NS_IS_INITIALIZED(ns)) {
396 NS_ERR("init_nandsim: nandsim is already initialized\n"); 411 NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -448,6 +463,40 @@ static int init_nandsim(struct mtd_info *mtd)
448 } 463 }
449 } 464 }
450 465
466 /* Fill the partition_info structure */
467 if (parts_num > ARRAY_SIZE(ns->partitions)) {
468 NS_ERR("too many partitions.\n");
469 ret = -EINVAL;
470 goto error;
471 }
472 remains = ns->geom.totsz;
473 next_offset = 0;
474 for (i = 0; i < parts_num; ++i) {
475 unsigned long part = parts[i];
476 if (!part || part > remains / ns->geom.secsz) {
477 NS_ERR("bad partition size.\n");
478 ret = -EINVAL;
479 goto error;
480 }
481 ns->partitions[i].name = get_partition_name(i);
482 ns->partitions[i].offset = next_offset;
483 ns->partitions[i].size = part * ns->geom.secsz;
484 next_offset += ns->partitions[i].size;
485 remains -= ns->partitions[i].size;
486 }
487 ns->nbparts = parts_num;
488 if (remains) {
489 if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) {
490 NS_ERR("too many partitions.\n");
491 ret = -EINVAL;
492 goto error;
493 }
494 ns->partitions[i].name = get_partition_name(i);
495 ns->partitions[i].offset = next_offset;
496 ns->partitions[i].size = remains;
497 ns->nbparts += 1;
498 }
499
451 /* Detect how many ID bytes the NAND chip outputs */ 500 /* Detect how many ID bytes the NAND chip outputs */
452 for (i = 0; nand_flash_ids[i].name != NULL; i++) { 501 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
453 if (second_id_byte != nand_flash_ids[i].id) 502 if (second_id_byte != nand_flash_ids[i].id)
@@ -474,7 +523,7 @@ static int init_nandsim(struct mtd_info *mtd)
474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 523 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
475 printk("options: %#x\n", ns->options); 524 printk("options: %#x\n", ns->options);
476 525
477 if (alloc_device(ns) != 0) 526 if ((ret = alloc_device(ns)) != 0)
478 goto error; 527 goto error;
479 528
480 /* Allocate / initialize the internal buffer */ 529 /* Allocate / initialize the internal buffer */
@@ -482,21 +531,17 @@ static int init_nandsim(struct mtd_info *mtd)
482 if (!ns->buf.byte) { 531 if (!ns->buf.byte) {
483 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", 532 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n",
484 ns->geom.pgszoob); 533 ns->geom.pgszoob);
534 ret = -ENOMEM;
485 goto error; 535 goto error;
486 } 536 }
487 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); 537 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
488 538
489 /* Fill the partition_info structure */
490 ns->part.name = "NAND simulator partition";
491 ns->part.offset = 0;
492 ns->part.size = ns->geom.totsz;
493
494 return 0; 539 return 0;
495 540
496error: 541error:
497 free_device(ns); 542 free_device(ns);
498 543
499 return -ENOMEM; 544 return ret;
500} 545}
501 546
502/* 547/*
@@ -1503,7 +1548,7 @@ static int __init ns_init_module(void)
1503{ 1548{
1504 struct nand_chip *chip; 1549 struct nand_chip *chip;
1505 struct nandsim *nand; 1550 struct nandsim *nand;
1506 int retval = -ENOMEM; 1551 int retval = -ENOMEM, i;
1507 1552
1508 if (bus_width != 8 && bus_width != 16) { 1553 if (bus_width != 8 && bus_width != 16) {
1509 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); 1554 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
@@ -1564,21 +1609,23 @@ static int __init ns_init_module(void)
1564 goto error; 1609 goto error;
1565 } 1610 }
1566 1611
1567 if ((retval = init_nandsim(nsmtd)) != 0) { 1612 if ((retval = init_nandsim(nsmtd)) != 0)
1568 NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); 1613 goto err_exit;
1569 goto error;
1570 }
1571 1614
1572 if ((retval = nand_default_bbt(nsmtd)) != 0) { 1615 if ((retval = nand_default_bbt(nsmtd)) != 0)
1573 free_nandsim(nand); 1616 goto err_exit;
1574 goto error;
1575 }
1576 1617
1577 /* Register NAND as one big partition */ 1618 /* Register NAND partitions */
1578 add_mtd_partitions(nsmtd, &nand->part, 1); 1619 if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0)
1620 goto err_exit;
1579 1621
1580 return 0; 1622 return 0;
1581 1623
1624err_exit:
1625 free_nandsim(nand);
1626 nand_release(nsmtd);
1627 for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
1628 kfree(nand->partitions[i].name);
1582error: 1629error:
1583 kfree(nsmtd); 1630 kfree(nsmtd);
1584 1631
@@ -1593,9 +1640,12 @@ module_init(ns_init_module);
1593static void __exit ns_cleanup_module(void) 1640static void __exit ns_cleanup_module(void)
1594{ 1641{
1595 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); 1642 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
1643 int i;
1596 1644
1597 free_nandsim(ns); /* Free nandsim private resources */ 1645 free_nandsim(ns); /* Free nandsim private resources */
1598 nand_release(nsmtd); /* Unregisterd drived */ 1646 nand_release(nsmtd); /* Unregister driver */
1647 for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
1648 kfree(ns->partitions[i].name);
1599 kfree(nsmtd); /* Free other structures */ 1649 kfree(nsmtd); /* Free other structures */
1600} 1650}
1601 1651
@@ -1604,4 +1654,3 @@ module_exit(ns_cleanup_module);
1604MODULE_LICENSE ("GPL"); 1654MODULE_LICENSE ("GPL");
1605MODULE_AUTHOR ("Artem B. Bityuckiy"); 1655MODULE_AUTHOR ("Artem B. Bityuckiy");
1606MODULE_DESCRIPTION ("The NAND flash simulator"); 1656MODULE_DESCRIPTION ("The NAND flash simulator");
1607