diff options
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 21 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/at91_nand.c | 220 | ||||
-rw-r--r-- | drivers/mtd/nand/cs553x_nand.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/edb7312.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 27 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 235 |
7 files changed, 403 insertions, 105 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 5e97e63e127..564f79d1665 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -21,7 +21,7 @@ config MTD_NAND_VERIFY_WRITE NAND flash device internally checks only bits transitioning from 1 to 0. There is a rare possibility that even though the device thinks the write was successful, a bit could have been - flipped accidentaly due to device wear or something else. + flipped accidentally due to device wear or something else. config MTD_NAND_ECC_SMC bool "NAND ECC Smart Media byte order" @@ -219,6 +219,13 @@ config MTD_NAND_SHARPSL tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" depends on MTD_NAND && ARCH_PXA +config MTD_NAND_CAFE + tristate "NAND support for OLPC CAFÉ chip" + depends on PCI + help + Use NAND flash attached to the CAFÉ chip designed for the $100 + laptop. + config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) @@ -232,12 +239,12 @@ config MTD_NAND_CS553X If you say "m", the module will be called "cs553x_nand.ko". -config MTD_NAND_CAFE - tristate "NAND support for OLPC CAFÉ chip" - depends on PCI - help - Use NAND flash attached to the CAFÉ chip designed for the $100 - laptop. +config MTD_NAND_AT91 + bool "Support for NAND Flash / SmartMedia on AT91" + depends on MTD_NAND && ARCH_AT91 + help + Enables support for NAND Flash / Smart Media Card interface + on Atmel AT91 processors. config MTD_NAND_NANDSIM tristate "Support for NAND Flash Simulator" diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 9346b831bc3..7cebc10c474 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -23,5 +23,6 @@ obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o +obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o nand-objs = nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c new file mode 100644 index 00000000000..a58ed376308 --- /dev/null +++ b/drivers/mtd/nand/at91_nand.c @@ -0,0 +1,220 @@ +/* + * drivers/mtd/nand/at91_nand.c + * + * Copyright (C) 2003 Rick Bronson + * + * Derived from drivers/mtd/nand/autcpu12.c + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * Derived from drivers/mtd/spia.c + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include <asm/io.h> +#include <asm/sizes.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +struct at91_nand_host { + struct nand_chip nand_chip; + struct mtd_info mtd; + void __iomem *io_base; + struct at91_nand_data *board; +}; + +/* + * Hardware specific access to control-lines + */ +static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *nand_chip = mtd->priv; + struct at91_nand_host *host = nand_chip->priv; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, host->io_base + (1 << host->board->cle)); + else + writeb(cmd, host->io_base + (1 << host->board->ale)); +} + +/* + * Read the Device Ready pin. + */ +static int at91_nand_device_ready(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = mtd->priv; + struct at91_nand_host *host = nand_chip->priv; + + return at91_get_gpio_value(host->board->rdy_pin); +} + +/* + * Enable NAND. + */ +static void at91_nand_enable(struct at91_nand_host *host) +{ + if (host->board->enable_pin) + at91_set_gpio_value(host->board->enable_pin, 0); +} + +/* + * Disable NAND. + */ +static void at91_nand_disable(struct at91_nand_host *host) +{ + if (host->board->enable_pin) + at91_set_gpio_value(host->board->enable_pin, 1); +} + +/* + * Probe for the NAND device. + */ +static int __init at91_nand_probe(struct platform_device *pdev) +{ + struct at91_nand_host *host; + struct mtd_info *mtd; + struct nand_chip *nand_chip; + int res; + +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partitions = NULL; + int num_partitions = 0; +#endif + + /* Allocate memory for the device structure (and zero it) */ + host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL); + if (!host) { + printk(KERN_ERR "at91_nand: failed to allocate device structure.\n"); + return -ENOMEM; + } + + host->io_base = ioremap(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1); + if (host->io_base == NULL) { + printk(KERN_ERR "at91_nand: ioremap failed\n"); + kfree(host); + return -EIO; + } + + mtd = &host->mtd; + nand_chip = &host->nand_chip; + host->board = pdev->dev.platform_data; + + nand_chip->priv = host; /* link the private data structures */ + mtd->priv = nand_chip; + mtd->owner = THIS_MODULE; + + /* Set address of NAND IO lines */ + nand_chip->IO_ADDR_R = host->io_base; + nand_chip->IO_ADDR_W = host->io_base; + nand_chip->cmd_ctrl = at91_nand_cmd_ctrl; + nand_chip->dev_ready = at91_nand_device_ready; + nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ + nand_chip->chip_delay = 20; /* 20us command delay time */ + + platform_set_drvdata(pdev, host); + at91_nand_enable(host); + + if (host->board->det_pin) { + if (at91_get_gpio_value(host->board->det_pin)) { + printk ("No SmartMedia card inserted.\n"); + res = ENXIO; + goto out; + } + } + + /* Scan to find existance of the device */ + if (nand_scan(mtd, 1)) { + res = -ENXIO; + goto out; + } + +#ifdef CONFIG_MTD_PARTITIONS + if (host->board->partition_info) + partitions = host->board->partition_info(mtd->size, &num_partitions); + + if ((!partitions) || (num_partitions == 0)) { + printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); + res = ENXIO; + goto release; + } + + res = add_mtd_partitions(mtd, partitions, num_partitions); +#else + res = add_mtd_device(mtd); +#endif + + if (!res) + return res; + +release: + nand_release(mtd); +out: + at91_nand_disable(host); + platform_set_drvdata(pdev, NULL); + iounmap(host->io_base); + kfree(host); + return res; +} + +/* + * Remove a NAND device. + */ +static int __devexit at91_nand_remove(struct platform_device *pdev) +{ + struct at91_nand_host *host = platform_get_drvdata(pdev); + struct mtd_info *mtd = &host->mtd; + + nand_release(mtd); + + at91_nand_disable(host); + + iounmap(host->io_base); + kfree(host); + + return 0; +} + +static struct platform_driver at91_nand_driver = { + .probe = at91_nand_probe, + .remove = at91_nand_remove, + .driver = { + .name = "at91_nand", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_nand_init(void) +{ + return platform_driver_register(&at91_nand_driver); +} + + +static void __exit at91_nand_exit(void) +{ + platform_driver_unregister(&at91_nand_driver); +} + + +module_init(at91_nand_init); +module_exit(at91_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200"); diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index e0a1d386e58..94924d52a9b 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -249,7 +249,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) goto out; out_ior: - iounmap((void *)this->IO_ADDR_R); + iounmap(this->IO_ADDR_R); out_mtd: kfree(new_mtd); out: diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 12017f3c6bd..1daf8231aae 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c @@ -199,7 +199,7 @@ static void __exit ep7312_cleanup(void) nand_release(ap7312_mtd); /* Release io resource */ - iounmap((void *)this->IO_ADDR_R); + iounmap(this->IO_ADDR_R); /* Free the MTD device structure */ kfree(ep7312_mtd); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index baece61169f..f23ab2c7043 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -755,7 +755,7 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_page_swecc - {REPLACABLE] software ecc based page read function + * nand_read_page_swecc - [REPLACABLE] software ecc based page read function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data @@ -795,7 +795,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function + * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data @@ -839,7 +839,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read + * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data @@ -971,7 +971,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, page = realpage & chip->pagemask; col = (int)(from & (mtd->writesize - 1)); - chip->oob_poi = chip->buffers->oobrbuf; buf = ops->datbuf; oob = ops->oobbuf; @@ -1270,8 +1269,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, realpage = (int)(from >> chip->page_shift); page = realpage & chip->pagemask; - chip->oob_poi = chip->buffers->oobrbuf; - while(1) { sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); buf = nand_transfer_oob(chip, buf, ops); @@ -1375,7 +1372,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_write_page_swecc - {REPLACABLE] software ecc based page write function + * nand_write_page_swecc - [REPLACABLE] software ecc based page write function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer @@ -1401,7 +1398,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function + * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer @@ -1429,7 +1426,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write + * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer @@ -1625,7 +1622,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, (chip->pagebuf << chip->page_shift) < (to + ops->len)) chip->pagebuf = -1; - chip->oob_poi = chip->buffers->oobwbuf; + /* If we're not given explicit OOB data, let it be 0xFF */ + if (likely(!oob)) + memset(chip->oob_poi, 0xff, mtd->oobsize); while(1) { int cached = writelen > bytes && page != blockmask; @@ -1654,9 +1653,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, } } - if (unlikely(oob)) - memset(chip->oob_poi, 0xff, mtd->oobsize); - ops->retlen = ops->len - writelen; return ret; } @@ -1744,7 +1740,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, if (page == chip->pagebuf) chip->pagebuf = -1; - chip->oob_poi = chip->buffers->oobwbuf; memset(chip->oob_poi, 0xff, mtd->oobsize); nand_fill_oob(chip, ops->oobbuf, ops); status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); @@ -2348,8 +2343,8 @@ int nand_scan_tail(struct mtd_info *mtd) if (!chip->buffers) return -ENOMEM; - /* Preset the internal oob write buffer */ - memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize); + /* Set the internal oob buffer location, just after the page data */ + chip->oob_poi = chip->buffers->databuf + mtd->writesize; /* * If no default placement scheme is given, select an appropriate one diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 545ff252d81..abebcab4763 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -37,10 +37,6 @@ #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/delay.h> -#ifdef CONFIG_NS_ABS_POS -#include <asm/io.h> -#endif - /* Default simulator parameters values */ #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ @@ -231,6 +227,14 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); #define NS_MAX_PREVSTATES 1 /* + * A union to represent flash memory contents and flash buffer. + */ +union ns_mem { + u_char *byte; /* for byte access */ + uint16_t *word; /* for 16-bit word access */ +}; + +/* * The structure which describes all the internal simulator data. */ struct nandsim { @@ -247,17 +251,11 @@ struct nandsim { uint16_t npstates; /* number of previous states saved */ uint16_t stateidx; /* current state index */ - /* The simulated NAND flash image */ - union flash_media { - u_char *byte; - uint16_t *word; - } mem; + /* The simulated NAND flash pages array */ + union ns_mem *pages; /* Internal buffer of page + OOB size bytes */ - union internal_buffer { - u_char *byte; /* for byte access */ - uint16_t *word; /* for 16-bit word access */ - } buf; + union ns_mem buf; /* NAND flash "geometry" */ struct nandsin_geometry { @@ -346,12 +344,49 @@ static struct mtd_info *nsmtd; static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; /* + * Allocate array of page pointers and initialize the array to NULL + * pointers. + * + * RETURNS: 0 if success, -ENOMEM if memory alloc fails. + */ +static int alloc_device(struct nandsim *ns) +{ + int i; + + ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem)); + if (!ns->pages) { + NS_ERR("alloc_map: unable to allocate page array\n"); + return -ENOMEM; + } + for (i = 0; i < ns->geom.pgnum; i++) { + ns->pages[i].byte = NULL; + } + + return 0; +} + +/* + * Free any allocated pages, and free the array of page pointers. + */ +static void free_device(struct nandsim *ns) +{ + int i; + + if (ns->pages) { + for (i = 0; i < ns->geom.pgnum; i++) { + if (ns->pages[i].byte) + kfree(ns->pages[i].byte); + } + vfree(ns->pages); + } +} + +/* * Initialize the nandsim structure. * * RETURNS: 0 if success, -ERRNO if failure. */ -static int -init_nandsim(struct mtd_info *mtd) +static int init_nandsim(struct mtd_info *mtd) { struct nand_chip *chip = (struct nand_chip *)mtd->priv; struct nandsim *ns = (struct nandsim *)(chip->priv); @@ -439,23 +474,8 @@ init_nandsim(struct mtd_info *mtd) printk("sector address bytes: %u\n", ns->geom.secaddrbytes); printk("options: %#x\n", ns->options); - /* Map / allocate and initialize the flash image */ -#ifdef CONFIG_NS_ABS_POS - ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); - if (!ns->mem.byte) { - NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", - (void *)CONFIG_NS_ABS_POS); - return -ENOMEM; - } -#else - ns->mem.byte = vmalloc(ns->geom.totszoob); - if (!ns->mem.byte) { - NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n", - ns->geom.totszoob); - return -ENOMEM; - } - memset(ns->mem.byte, 0xFF, ns->geom.totszoob); -#endif + if (alloc_device(ns) != 0) + goto error; /* Allocate / initialize the internal buffer */ ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); @@ -474,11 +494,7 @@ init_nandsim(struct mtd_info *mtd) return 0; error: -#ifdef CONFIG_NS_ABS_POS - iounmap(ns->mem.byte); -#else - vfree(ns->mem.byte); -#endif + free_device(ns); return -ENOMEM; } @@ -486,16 +502,10 @@ error: /* * Free the nandsim structure. */ -static void -free_nandsim(struct nandsim *ns) +static void free_nandsim(struct nandsim *ns) { kfree(ns->buf.byte); - -#ifdef CONFIG_NS_ABS_POS - iounmap(ns->mem.byte); -#else - vfree(ns->mem.byte); -#endif + free_device(ns); return; } @@ -503,8 +513,7 @@ free_nandsim(struct nandsim *ns) /* * Returns the string representation of 'state' state. */ -static char * -get_state_name(uint32_t state) +static char *get_state_name(uint32_t state) { switch (NS_STATE(state)) { case STATE_CMD_READ0: @@ -562,8 +571,7 @@ get_state_name(uint32_t state) * * RETURNS: 1 if wrong command, 0 if right. */ -static int -check_command(int cmd) +static int check_command(int cmd) { switch (cmd) { @@ -589,8 +597,7 @@ check_command(int cmd) /* * Returns state after command is accepted by command number. */ -static uint32_t -get_state_by_command(unsigned command) +static uint32_t get_state_by_command(unsigned command) { switch (command) { case NAND_CMD_READ0: @@ -626,8 +633,7 @@ get_state_by_command(unsigned command) /* * Move an address byte to the correspondent internal register. */ -static inline void -accept_addr_byte(struct nandsim *ns, u_char bt) +static inline void accept_addr_byte(struct nandsim *ns, u_char bt) { uint byte = (uint)bt; @@ -645,8 +651,7 @@ accept_addr_byte(struct nandsim *ns, u_char bt) /* * Switch to STATE_READY state. */ -static inline void -switch_to_ready_state(struct nandsim *ns, u_char status) +static inline void switch_to_ready_state(struct nandsim *ns, u_char status) { NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); @@ -705,8 +710,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) * -1 - several matches. * 0 - operation is found. */ -static int -find_operation(struct nandsim *ns, uint32_t flag) +static int find_operation(struct nandsim *ns, uint32_t flag) { int opsfound = 0; int i, j, idx = 0; @@ -791,14 +795,93 @@ find_operation(struct nandsim *ns, uint32_t flag) } /* + * Returns a pointer to the current page. + */ +static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns) +{ + return &(ns->pages[ns->regs.row]); +} + +/* + * Retuns a pointer to the current byte, within the current page. + */ +static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns) +{ + return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; +} + +/* + * Fill the NAND buffer with data read from the specified page. + */ +static void read_page(struct nandsim *ns, int num) +{ + union ns_mem *mypage; + + mypage = NS_GET_PAGE(ns); + if (mypage->byte == NULL) { + NS_DBG("read_page: page %d not allocated\n", ns->regs.row); + memset(ns->buf.byte, 0xFF, num); + } else { + NS_DBG("read_page: page %d allocated, reading from %d\n", + ns->regs.row, ns->regs.column + ns->regs.off); + memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); + } +} + +/* + * Erase all pages in the specified sector. + */ +static void erase_sector(struct nandsim *ns) +{ + union ns_mem *mypage; + int i; + + mypage = NS_GET_PAGE(ns); + for (i = 0; i < ns->geom.pgsec; i++) { + if (mypage->byte != NULL) { + NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); + kfree(mypage->byte); + mypage->byte = NULL; + } + mypage++; + } +} + +/* + * Program the specified page with the contents from the NAND buffer. + */ +static int prog_page(struct nandsim *ns, int num) +{ + int i; + union ns_mem *mypage; + u_char *pg_off; + + mypage = NS_GET_PAGE(ns); + if (mypage->byte == NULL) { + NS_DBG("prog_page: allocating page %d\n", ns->regs.row); + mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); + if (mypage->byte == NULL) { + NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); + return -1; + } + memset(mypage->byte, 0xFF, ns->geom.pgszoob); + } + + pg_off = NS_PAGE_BYTE_OFF(ns); + for (i = 0; i < num; i++) + pg_off[i] &= ns->buf.byte[i]; + + return 0; +} + +/* * If state has any action bit, perform this action. * * RETURNS: 0 if success, -1 if error. */ -static int -do_state_action(struct nandsim *ns, uint32_t action) +static int do_state_action(struct nandsim *ns, uint32_t action) { - int i, num; + int num; int busdiv = ns->busw == 8 ? 1 : 2; action &= ACTION_MASK; @@ -822,7 +905,7 @@ do_state_action(struct nandsim *ns, uint32_t action) break; } num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; - memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num); + read_page(ns, num); NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", num, NS_RAW_OFFSET(ns) + ns->regs.off); @@ -863,7 +946,7 @@ do_state_action(struct nandsim *ns, uint32_t action) ns->regs.row, NS_RAW_OFFSET(ns)); NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); - memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); + erase_sector(ns); NS_MDELAY(erase_delay); @@ -886,8 +969,8 @@ do_state_action(struct nandsim *ns, uint32_t action) return -1; } - for (i = 0; i < num; i++) - ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i]; + if (prog_page(ns, num) == -1) + return -1; NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); @@ -928,8 +1011,7 @@ do_state_action(struct nandsim *ns, uint32_t action) /* * Switch simulator's state. */ -static void -switch_state(struct nandsim *ns) +static void switch_state(struct nandsim *ns) { if (ns->op) { /* @@ -1070,8 +1152,7 @@ switch_state(struct nandsim *ns) } } -static u_char -ns_nand_read_byte(struct mtd_info *mtd) +static u_char ns_nand_read_byte(struct mtd_info *mtd) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; u_char outb = 0x00; @@ -1144,8 +1225,7 @@ ns_nand_read_byte(struct mtd_info *mtd) return outb; } -static void -ns_nand_write_byte(struct mtd_info *mtd, u_char byte) +static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1308,15 +1388,13 @@ static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) ns_nand_write_byte(mtd, cmd); } -static int -ns_device_ready(struct mtd_info *mtd) +static int ns_device_ready(struct mtd_info *mtd) { NS_DBG("device_ready\n"); return 1; } -static uint16_t -ns_nand_read_word(struct mtd_info *mtd) +static uint16_t ns_nand_read_word(struct mtd_info *mtd) { struct nand_chip *chip = (struct nand_chip *)mtd->priv; @@ -1325,8 +1403,7 @@ ns_nand_read_word(struct mtd_info *mtd) return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); } -static void -ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1353,8 +1430,7 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } } -static void -ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1407,8 +1483,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) return; } -static int -ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) { ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); |