diff options
Diffstat (limited to 'drivers/mtd/nand')
30 files changed, 382 insertions, 443 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index dd02792..31b034b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -110,7 +110,7 @@ config MTD_NAND_AMS_DELTA config MTD_NAND_OMAP2 tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4" - depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4) + depends on ARCH_OMAP2PLUS help Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 platforms. diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 9e6b498..3197e97 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -280,17 +280,7 @@ static struct platform_driver ams_delta_nand_driver = { }, }; -static int __init ams_delta_nand_init(void) -{ - return platform_driver_register(&ams_delta_nand_driver); -} -module_init(ams_delta_nand_init); - -static void __exit ams_delta_nand_exit(void) -{ - platform_driver_unregister(&ams_delta_nand_driver); -} -module_exit(ams_delta_nand_exit); +module_platform_driver(ams_delta_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4dd056e..35b4fb5 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) !!host->board->rdy_pin_active_low; } +/* + * Minimal-overhead PIO for data access. + */ +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsb(nand_chip->IO_ADDR_R, buf, len); +} + +static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); +} + +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesb(nand_chip->IO_ADDR_W, buf, len); +} + +static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); +} + static void dma_complete_func(void *completion) { complete(completion); @@ -235,27 +266,33 @@ err_buf: static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_fromio(buf, chip->IO_ADDR_R, len); + if (host->board->bus_width_16) + atmel_read_buf16(mtd, buf, len); + else + atmel_read_buf8(mtd, buf, len); } static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_toio(chip->IO_ADDR_W, buf, len); + if (host->board->bus_width_16) + atmel_write_buf16(mtd, buf, len); + else + atmel_write_buf8(mtd, buf, len); } /* diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 7dd3700..73abbc3 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -17,35 +17,19 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/platform_device.h> #include <asm/io.h> +#include <asm/mach-au1x00/au1000.h> +#include <asm/mach-au1x00/au1550nd.h> -#ifdef CONFIG_MIPS_PB1550 -#include <asm/mach-pb1x00/pb1550.h> -#elif defined(CONFIG_MIPS_DB1550) -#include <asm/mach-db1x00/db1x00.h> -#endif -#include <asm/mach-db1x00/bcsr.h> -/* - * MTD structure for NAND controller - */ -static struct mtd_info *au1550_mtd = NULL; -static void __iomem *p_nand; -static int nand_width = 1; /* default x8 */ -static void (*au1550_write_byte)(struct mtd_info *, u_char); +struct au1550nd_ctx { + struct mtd_info info; + struct nand_chip chip; -/* - * Define partitions for flash device - */ -static const struct mtd_partition partition_info[] = { - { - .name = "NAND FS 0", - .offset = 0, - .size = 8 * 1024 * 1024}, - { - .name = "NAND FS 1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL} + int cs; + void __iomem *base; + void (*write_byte)(struct mtd_info *, u_char); }; /** @@ -259,24 +243,25 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { - register struct nand_chip *this = mtd->priv; + struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); + struct nand_chip *this = mtd->priv; switch (cmd) { case NAND_CTL_SETCLE: - this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; + this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD; break; case NAND_CTL_CLRCLE: - this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA; break; case NAND_CTL_SETALE: - this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; + this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR; break; case NAND_CTL_CLRALE: - this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA; /* FIXME: Nobody knows why this is necessary, * but it works only that way */ udelay(1); @@ -284,7 +269,7 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) case NAND_CTL_SETNCE: /* assert (force assert) chip enable */ - au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL); + au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL); break; case NAND_CTL_CLRNCE: @@ -331,9 +316,10 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip) */ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { - register struct nand_chip *this = mtd->priv; + struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info); + struct nand_chip *this = mtd->priv; int ce_override = 0, i; - ulong flags; + unsigned long flags = 0; /* Begin command latch cycle */ au1550_hwcontrol(mtd, NAND_CTL_SETCLE); @@ -354,9 +340,9 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i column -= 256; readcmd = NAND_CMD_READ1; } - au1550_write_byte(mtd, readcmd); + ctx->write_byte(mtd, readcmd); } - au1550_write_byte(mtd, command); + ctx->write_byte(mtd, command); /* Set ALE and clear CLE to start address cycle */ au1550_hwcontrol(mtd, NAND_CTL_CLRCLE); @@ -369,10 +355,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i /* Adjust columns for 16 bit buswidth */ if (this->options & NAND_BUSWIDTH_16) column >>= 1; - au1550_write_byte(mtd, column); + ctx->write_byte(mtd, column); } if (page_addr != -1) { - au1550_write_byte(mtd, (u8)(page_addr & 0xff)); + ctx->write_byte(mtd, (u8)(page_addr & 0xff)); if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || @@ -390,11 +376,12 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i au1550_hwcontrol(mtd, NAND_CTL_SETNCE); } - au1550_write_byte(mtd, (u8)(page_addr >> 8)); + ctx->write_byte(mtd, (u8)(page_addr >> 8)); /* One more address cycle for devices > 32MiB */ if (this->chipsize > (32 << 20)) - au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f)); + ctx->write_byte(mtd, + ((page_addr >> 16) & 0x0f)); } /* Latch in address */ au1550_hwcontrol(mtd, NAND_CTL_CLRALE); @@ -440,121 +427,79 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i while(!this->dev_ready(mtd)); } - -/* - * Main initialization routine - */ -static int __init au1xxx_nand_init(void) +static int __devinit find_nand_cs(unsigned long nand_base) { - struct nand_chip *this; - u16 boot_swapboot = 0; /* default value */ - int retval; - u32 mem_staddr; - u32 nand_phys; - - /* Allocate memory for MTD device structure and private data */ - au1550_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); - if (!au1550_mtd) { - printk("Unable to allocate NAND MTD dev structure.\n"); - return -ENOMEM; - } - - /* Get pointer to private data */ - this = (struct nand_chip *)(&au1550_mtd[1]); - - /* Link the private data with the MTD structure */ - au1550_mtd->priv = this; - au1550_mtd->owner = THIS_MODULE; - + void __iomem *base = + (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR); + unsigned long addr, staddr, start, mask, end; + int i; - /* MEM_STNDCTL: disable ints, disable nand boot */ - au_writel(0, MEM_STNDCTL); + for (i = 0; i < 4; i++) { + addr = 0x1000 + (i * 0x10); /* CSx */ + staddr = __raw_readl(base + addr + 0x08); /* STADDRx */ + /* figure out the decoded range of this CS */ + start = (staddr << 4) & 0xfffc0000; + mask = (staddr << 18) & 0xfffc0000; + end = (start | (start - 1)) & ~(start ^ mask); + if ((nand_base >= start) && (nand_base < end)) + return i; + } -#ifdef CONFIG_MIPS_PB1550 - /* set gpio206 high */ - gpio_direction_input(206); + return -ENODEV; +} - boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr_read(BCSR_STATUS) >> 6) & 0x1); +static int __devinit au1550nd_probe(struct platform_device *pdev) +{ + struct au1550nd_platdata *pd; + struct au1550nd_ctx *ctx; + struct nand_chip *this; + struct resource *r; + int ret, cs; - switch (boot_swapboot) { - case 0: - case 2: - case 8: - case 0xC: - case 0xD: - /* x16 NAND Flash */ - nand_width = 0; - break; - case 1: - case 9: - case 3: - case 0xE: - case 0xF: - /* x8 NAND Flash */ - nand_width = 1; - break; - default: - printk("Pb1550 NAND: bad boot:swap\n"); - retval = -EINVAL; - goto outmem; + pd = pdev->dev.platform_data; + if (!pd) { + dev_err(&pdev->dev, "missing platform data\n"); + return -ENODEV; } -#endif - - /* Configure chip-select; normally done by boot code, e.g. YAMON */ -#ifdef NAND_STCFG - if (NAND_CS == 0) { - au_writel(NAND_STCFG, MEM_STCFG0); - au_writel(NAND_STTIME, MEM_STTIME0); - au_writel(NAND_STADDR, MEM_STADDR0); - } - if (NAND_CS == 1) { - au_writel(NAND_STCFG, MEM_STCFG1); - au_writel(NAND_STTIME, MEM_STTIME1); - au_writel(NAND_STADDR, MEM_STADDR1); + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + dev_err(&pdev->dev, "no memory for NAND context\n"); + return -ENOMEM; } - if (NAND_CS == 2) { - au_writel(NAND_STCFG, MEM_STCFG2); - au_writel(NAND_STTIME, MEM_STTIME2); - au_writel(NAND_STADDR, MEM_STADDR2); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no NAND memory resource\n"); + ret = -ENODEV; + goto out1; } - if (NAND_CS == 3) { - au_writel(NAND_STCFG, MEM_STCFG3); - au_writel(NAND_STTIME, MEM_STTIME3); - au_writel(NAND_STADDR, MEM_STADDR3); + if (request_mem_region(r->start, resource_size(r), "au1550-nand")) { + dev_err(&pdev->dev, "cannot claim NAND memory area\n"); + ret = -ENOMEM; + goto out1; } -#endif - - /* Locate NAND chip-select in order to determine NAND phys address */ - mem_staddr = 0x00000000; - if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0)) - mem_staddr = au_readl(MEM_STADDR0); - else if (((au_readl(MEM_STCFG1) & 0x7) == 0x5) && (NAND_CS == 1)) - mem_staddr = au_readl(MEM_STADDR1); - else if (((au_readl(MEM_STCFG2) & 0x7) == 0x5) && (NAND_CS == 2)) - mem_staddr = au_readl(MEM_STADDR2); - else if (((au_readl(MEM_STCFG3) & 0x7) == 0x5) && (NAND_CS == 3)) - mem_staddr = au_readl(MEM_STADDR3); - - if (mem_staddr == 0x00000000) { - printk("Au1xxx NAND: ERROR WITH NAND CHIP-SELECT\n"); - kfree(au1550_mtd); - return 1; + + ctx->base = ioremap_nocache(r->start, 0x1000); + if (!ctx->base) { + dev_err(&pdev->dev, "cannot remap NAND memory area\n"); + ret = -ENODEV; + goto out2; } - nand_phys = (mem_staddr << 4) & 0xFFFC0000; - p_nand = ioremap(nand_phys, 0x1000); + this = &ctx->chip; + ctx->info.priv = this; + ctx->info.owner = THIS_MODULE; - /* make controller and MTD agree */ - if (NAND_CS == 0) - nand_width = au_readl(MEM_STCFG0) & (1 << 22); - if (NAND_CS == 1) - nand_width = au_readl(MEM_STCFG1) & (1 << 22); - if (NAND_CS == 2) - nand_width = au_readl(MEM_STCFG2) & (1 << 22); - if (NAND_CS == 3) - nand_width = au_readl(MEM_STCFG3) & (1 << 22); + /* figure out which CS# r->start belongs to */ + cs = find_nand_cs(r->start); + if (cs < 0) { + dev_err(&pdev->dev, "cannot detect NAND chipselect\n"); + ret = -ENODEV; + goto out3; + } + ctx->cs = cs; - /* Set address of hardware control function */ this->dev_ready = au1550_device_ready; this->select_chip = au1550_select_chip; this->cmdfunc = au1550_command; @@ -565,54 +510,57 @@ static int __init au1xxx_nand_init(void) this->options = NAND_NO_AUTOINCR; - if (!nand_width) + if (pd->devwidth) this->options |= NAND_BUSWIDTH_16; - this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte; - au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; + this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte; + ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte; this->read_word = au_read_word; - this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf; - this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf; - this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; - - /* Scan to find existence of the device */ - if (nand_scan(au1550_mtd, 1)) { - retval = -ENXIO; - goto outio; + this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; + this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; + this->verify_buf = (pd->devwidth) ? au_verify_buf16 : au_verify_buf; + + ret = nand_scan(&ctx->info, 1); + if (ret) { + dev_err(&pdev->dev, "NAND scan failed with %d\n", ret); + goto out3; } - /* Register the partitions */ - mtd_device_register(au1550_mtd, partition_info, - ARRAY_SIZE(partition_info)); + mtd_device_register(&ctx->info, pd->parts, pd->num_parts); return 0; - outio: - iounmap(p_nand); - - outmem: - kfree(au1550_mtd); - return retval; +out3: + iounmap(ctx->base); +out2: + release_mem_region(r->start, resource_size(r)); +out1: + kfree(ctx); + return ret; } -module_init(au1xxx_nand_init); - -/* - * Clean up routine - */ -static void __exit au1550_cleanup(void) +static int __devexit au1550nd_remove(struct platform_device *pdev) { - /* Release resources, unregister device */ - nand_release(au1550_mtd); + struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); + struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - /* Free the MTD device structure */ - kfree(au1550_mtd); - - /* Unmap */ - iounmap(p_nand); + nand_release(&ctx->info); + iounmap(ctx->base); + release_mem_region(r->start, 0x1000); + kfree(ctx); + return 0; } -module_exit(au1550_cleanup); +static struct platform_driver au1550nd_driver = { + .driver = { + .name = "au1550-nand", + .owner = THIS_MODULE, + }, + .probe = au1550nd_probe, + .remove = __devexit_p(au1550nd_remove), +}; + +module_platform_driver(au1550nd_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Embedded Edge, LLC"); diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index 46b58d6..50387fd 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c @@ -546,18 +546,7 @@ static struct platform_driver nand_driver = { .resume = bcm_umi_nand_resume, }; -static int __init nand_init(void) -{ - return platform_driver_register(&nand_driver); -} - -static void __exit nand_exit(void) -{ - platform_driver_unregister(&nand_driver); -} - -module_init(nand_init); -module_exit(nand_exit); +module_platform_driver(nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Broadcom"); diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index c153e1f..6e56615 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -675,7 +675,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val); - ret = davinci_aemif_setup_timing(info->timing, info->base, + ret = 0; + if (info->timing) + ret = davinci_aemif_setup_timing(info->timing, info->base, info->core_chipsel); if (ret < 0) { dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 5780dba..df921e7 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1072,7 +1072,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch size_t retlen; for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { - ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); if (retlen != mtd->writesize) continue; if (ret) { @@ -1097,7 +1097,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch /* Only one mediaheader was found. We want buf to contain a mediaheader on return, so we'll have to re-read the one we found. */ offs = doc->mh0_page << this->page_shift; - ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); if (retlen != mtd->writesize) { /* Insanity. Give up. */ printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index eedd8ee..7195ee6 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -166,15 +166,22 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) elbc_fcm_ctrl->page = page_addr; - out_be32(&lbc->fbar, - page_addr >> (chip->phys_erase_shift - chip->page_shift)); - if (priv->page_size) { + /* + * large page size chip : FPAR[PI] save the lowest 6 bits, + * FBAR[BLK] save the other bits. + */ + out_be32(&lbc->fbar, page_addr >> 6); out_be32(&lbc->fpar, ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | (oob ? FPAR_LP_MS : 0) | column); buf_num = (page_addr & 1) << 2; } else { + /* + * small page size chip : FPAR[PI] save the lowest 5 bits, + * FBAR[BLK] save the other bits. + */ + out_be32(&lbc->fbar, page_addr >> 5); out_be32(&lbc->fpar, ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | (oob ? FPAR_SP_MS : 0) | column); @@ -349,20 +356,22 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, fsl_elbc_run_command(mtd); return; - /* READID must read all 5 possible bytes while CEB is active */ case NAND_CMD_READID: - dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); + case NAND_CMD_PARAM: + dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command); out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | (FIR_OP_UA << FIR_OP1_SHIFT) | (FIR_OP_RBW << FIR_OP2_SHIFT)); - out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); - /* nand_get_flash_type() reads 8 bytes of entire ID string */ - out_be32(&lbc->fbcr, 8); - elbc_fcm_ctrl->read_bytes = 8; + out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); + /* + * although currently it's 8 bytes for READID, we always read + * the maximum 256 bytes(for PARAM) + */ + out_be32(&lbc->fbcr, 256); + elbc_fcm_ctrl->read_bytes = 256; elbc_fcm_ctrl->use_mdr = 1; - elbc_fcm_ctrl->mdr = 0; - + elbc_fcm_ctrl->mdr = column; set_addr(mtd, 0, 0, 0); fsl_elbc_run_command(mtd); return; @@ -407,9 +416,17 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, page_addr, column); elbc_fcm_ctrl->column = column; - elbc_fcm_ctrl->oob = 0; elbc_fcm_ctrl->use_mdr = 1; + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + elbc_fcm_ctrl->oob = 1; + } else { + WARN_ON(column != 0); + elbc_fcm_ctrl->oob = 0; + } + fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); @@ -434,16 +451,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, (FIR_OP_CW1 << FIR_OP6_SHIFT) | (FIR_OP_RS << FIR_OP7_SHIFT)); - if (column >= mtd->writesize) { + if (elbc_fcm_ctrl->oob) /* OOB area --> READOOB */ - column -= mtd->writesize; fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; - elbc_fcm_ctrl->oob = 1; - } else { - WARN_ON(column != 0); + else /* First 256 bytes --> READ0 */ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; - } } out_be32(&lbc->fcr, fcr); @@ -463,7 +476,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, */ if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) - out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); + out_be32(&lbc->fbcr, + elbc_fcm_ctrl->index - elbc_fcm_ctrl->column); else out_be32(&lbc->fbcr, 0); @@ -659,9 +673,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) if (chip->pagemask & 0xff000000) al++; - /* add to ECCM mode set in fsl_elbc_init */ - priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ - (al << FMR_AL_SHIFT); + priv->fmr |= al << FMR_AL_SHIFT; dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", chip->numchips); @@ -764,8 +776,10 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) priv->mtd.priv = chip; priv->mtd.owner = THIS_MODULE; - /* Set the ECCM according to the settings in bootloader.*/ - priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM; + /* set timeout to maximum */ + priv->fmr = 15 << FMR_CWTO_SHIFT; + if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) + priv->fmr |= FMR_ECCM; /* fill in nand_chip structure */ /* set up function call table */ @@ -971,18 +985,7 @@ static struct platform_driver fsl_elbc_nand_driver = { .remove = fsl_elbc_nand_remove, }; -static int __init fsl_elbc_nand_init(void) -{ - return platform_driver_register(&fsl_elbc_nand_driver); -} - -static void __exit fsl_elbc_nand_exit(void) -{ - platform_driver_unregister(&fsl_elbc_nand_driver); -} - -module_init(fsl_elbc_nand_init); -module_exit(fsl_elbc_nand_exit); +module_platform_driver(fsl_elbc_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Freescale"); diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index b4f3cc9..45df542 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -353,17 +353,7 @@ static struct platform_driver of_fun_driver = { .remove = __devexit_p(fun_remove), }; -static int __init fun_module_init(void) -{ - return platform_driver_register(&of_fun_driver); -} -module_init(fun_module_init); - -static void __exit fun_module_exit(void) -{ - platform_driver_unregister(&of_fun_driver); -} -module_exit(fun_module_exit); +module_platform_driver(of_fun_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 2c2060b..27000a5 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -27,6 +27,9 @@ #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand-gpio.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_gpio.h> struct gpiomtd { void __iomem *io_sync; @@ -171,6 +174,96 @@ static int gpio_nand_devready(struct mtd_info *mtd) return gpio_get_value(gpiomtd->plat.gpio_rdy); } +#ifdef CONFIG_OF +static const struct of_device_id gpio_nand_id_table[] = { + { .compatible = "gpio-control-nand" }, + {} +}; +MODULE_DEVICE_TABLE(of, gpio_nand_id_table); + +static int gpio_nand_get_config_of(const struct device *dev, + struct gpio_nand_platdata *plat) +{ + u32 val; + + if (!of_property_read_u32(dev->of_node, "bank-width", &val)) { + if (val == 2) { + plat->options |= NAND_BUSWIDTH_16; + } else if (val != 1) { + dev_err(dev, "invalid bank-width %u\n", val); + return -EINVAL; + } + } + + plat->gpio_rdy = of_get_gpio(dev->of_node, 0); + plat->gpio_nce = of_get_gpio(dev->of_node, 1); + plat->gpio_ale = of_get_gpio(dev->of_node, 2); + plat->gpio_cle = of_get_gpio(dev->of_node, 3); + plat->gpio_nwp = of_get_gpio(dev->of_node, 4); + + if (!of_property_read_u32(dev->of_node, "chip-delay", &val)) + plat->chip_delay = val; + + return 0; +} + +static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev) +{ + struct resource *r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL); + u64 addr; + + if (!r || of_property_read_u64(pdev->dev.of_node, + "gpio-control-nand,io-sync-reg", &addr)) + return NULL; + + r->start = addr; + r->end = r->start + 0x3; + r->flags = IORESOURCE_MEM; + + return r; +} +#else /* CONFIG_OF */ +#define gpio_nand_id_table NULL +static inline int gpio_nand_get_config_of(const struct device *dev, + struct gpio_nand_platdata *plat) +{ + return -ENOSYS; +} + +static inline struct resource * +gpio_nand_get_io_sync_of(struct platform_device *pdev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +static inline int gpio_nand_get_config(const struct device *dev, + struct gpio_nand_platdata *plat) +{ + int ret = gpio_nand_get_config_of(dev, plat); + + if (!ret) + return ret; + + if (dev->platform_data) { + memcpy(plat, dev->platform_data, sizeof(*plat)); + return 0; + } + + return -EINVAL; +} + +static inline struct resource * +gpio_nand_get_io_sync(struct platform_device *pdev) +{ + struct resource *r = gpio_nand_get_io_sync_of(pdev); + + if (r) + return r; + + return platform_get_resource(pdev, IORESOURCE_MEM, 1); +} + static int __devexit gpio_nand_remove(struct platform_device *dev) { struct gpiomtd *gpiomtd = platform_get_drvdata(dev); @@ -178,7 +271,7 @@ static int __devexit gpio_nand_remove(struct platform_device *dev) nand_release(&gpiomtd->mtd_info); - res = platform_get_resource(dev, IORESOURCE_MEM, 1); + res = gpio_nand_get_io_sync(dev); iounmap(gpiomtd->io_sync); if (res) release_mem_region(res->start, resource_size(res)); @@ -226,9 +319,10 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) struct gpiomtd *gpiomtd; struct nand_chip *this; struct resource *res0, *res1; - int ret; + struct mtd_part_parser_data ppdata = {}; + int ret = 0; - if (!dev->dev.platform_data) + if (!dev->dev.of_node && !dev->dev.platform_data) return -EINVAL; res0 = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -248,7 +342,7 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) goto err_map; } - res1 = platform_get_resource(dev, IORESOURCE_MEM, 1); + res1 = gpio_nand_get_io_sync(dev); if (res1) { gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret); if (!gpiomtd->io_sync) { @@ -257,7 +351,9 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) } } - memcpy(&gpiomtd->plat, dev->dev.platform_data, sizeof(gpiomtd->plat)); + ret = gpio_nand_get_config(&dev->dev, &gpiomtd->plat); + if (ret) + goto err_nce; ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE"); if (ret) @@ -316,8 +412,12 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) gpiomtd->plat.adjust_parts(&gpiomtd->plat, gpiomtd->mtd_info.size); - mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts, - gpiomtd->plat.num_parts); + ppdata.of_node = dev->dev.of_node; + ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata, + gpiomtd->plat.parts, + gpiomtd->plat.num_parts); + if (ret) + goto err_wp; platform_set_drvdata(dev, gpiomtd); return 0; @@ -352,6 +452,7 @@ static struct platform_driver gpio_nand_driver = { .remove = gpio_nand_remove, .driver = { .name = "gpio-nand", + .of_match_table = gpio_nand_id_table, }, }; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 2a56fc6..7db6555 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) * [1] enable the module. * [2] reset the module. * - * In most of the cases, it's ok. But there is a hardware bug in the BCH block. + * In most of the cases, it's ok. + * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. - * You will see a DMA timeout in this case. + * You will see a DMA timeout in this case. The bug has been fixed + * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here. */ -int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) +static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; @@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = gpmi_reset_block(r->bch_regs, true); + /* + * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this + * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. + * On the other hand, the MX28 needs the reset, because one case has been + * seen where the BCH produced ECC errors constantly after 10000 + * consecutive reboots. The latter case has not been seen on the MX23 yet, + * still we don't know if it could happen there as well. + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); if (ret) goto err_out; @@ -827,7 +837,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) pio[1] = pio[2] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -839,7 +849,7 @@ int gpmi_send_command(struct gpmi_nand_data *this) sg_init_one(sgl, this->cmd_buffer, this->command_length); dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, - sgl, 1, DMA_TO_DEVICE, 1); + sgl, 1, DMA_MEM_TO_DEV, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -872,7 +882,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -881,7 +891,7 @@ int gpmi_send_data(struct gpmi_nand_data *this) /* [2] send DMA request */ prepare_data_dma(this, DMA_TO_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_TO_DEVICE, 1); + 1, DMA_MEM_TO_DEV, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -908,7 +918,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -917,7 +927,7 @@ int gpmi_read_data(struct gpmi_nand_data *this) /* [2] : send DMA request */ prepare_data_dma(this, DMA_FROM_DEVICE); desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, - 1, DMA_FROM_DEVICE, 1); + 1, DMA_DEV_TO_MEM, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -964,7 +974,7 @@ int gpmi_send_page(struct gpmi_nand_data *this, desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 0); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -998,7 +1008,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, | BF_GPMI_CTRL0_XFER_COUNT(0); pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, - (struct scatterlist *)pio, 2, DMA_NONE, 0); + (struct scatterlist *)pio, 2, + DMA_TRANS_NONE, 0); if (!desc) { pr_err("step 1 error\n"); return -1; @@ -1027,7 +1038,7 @@ int gpmi_read_page(struct gpmi_nand_data *this, pio[5] = auxiliary; desc = channel->device->device_prep_slave_sg(channel, (struct scatterlist *)pio, - ARRAY_SIZE(pio), DMA_NONE, 1); + ARRAY_SIZE(pio), DMA_TRANS_NONE, 1); if (!desc) { pr_err("step 2 error\n"); return -1; @@ -1045,7 +1056,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); pio[1] = 0; desc = channel->device->device_prep_slave_sg(channel, - (struct scatterlist *)pio, 2, DMA_NONE, 1); + (struct scatterlist *)pio, 2, + DMA_TRANS_NONE, 1); if (!desc) { pr_err("step 3 error\n"); return -1; diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index e266407..ac3b9f2 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -423,17 +423,7 @@ static struct platform_driver jz_nand_driver = { }, }; -static int __init jz_nand_init(void) -{ - return platform_driver_register(&jz_nand_driver); -} -module_init(jz_nand_init); - -static void __exit jz_nand_exit(void) -{ - platform_driver_unregister(&jz_nand_driver); -} -module_exit(jz_nand_exit); +module_platform_driver(jz_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 5ede647..c240cf1 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -879,19 +879,7 @@ static struct platform_driver mpc5121_nfc_driver = { }, }; -static int __init mpc5121_nfc_init(void) -{ - return platform_driver_register(&mpc5121_nfc_driver); -} - -module_init(mpc5121_nfc_init); - -static void __exit mpc5121_nfc_cleanup(void) -{ - platform_driver_unregister(&mpc5121_nfc_driver); -} - -module_exit(mpc5121_nfc_cleanup); +module_platform_driver(mpc5121_nfc_driver); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("MPC5121 NAND MTD driver"); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 3ed9c5e..8a393f9 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, instr->state = MTD_ERASING; while (len) { - /* Heck if we have a bad block, we do not erase bad blocks! */ + /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", @@ -3132,8 +3132,8 @@ ident_done: * Bad block marker is stored in the last page of each block * on Samsung and Hynix MLC devices; stored in first two pages * of each block on Micron devices with 2KiB pages and on - * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan - * only the first page. + * SLC Samsung, Hynix, Toshiba, AMD/Spansion, and Macronix. + * All others scan only the first page. */ if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && (*maf_id == NAND_MFR_SAMSUNG || @@ -3143,7 +3143,8 @@ ident_done: (*maf_id == NAND_MFR_SAMSUNG || *maf_id == NAND_MFR_HYNIX || *maf_id == NAND_MFR_TOSHIBA || - *maf_id == NAND_MFR_AMD)) || + *maf_id == NAND_MFR_AMD || + *maf_id == NAND_MFR_MACRONIX)) || (mtd->writesize == 2048 && *maf_id == NAND_MFR_MICRON)) chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 69148ae..20a112f 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -201,7 +201,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, from += marker_len; marker_len = 0; } - res = mtd->read(mtd, from, len, &retlen, buf); + res = mtd_read(mtd, from, len, &retlen, buf); if (res < 0) { if (mtd_is_eccerr(res)) { pr_info("nand_bbt: ECC error in BBT at " @@ -298,7 +298,7 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, if (td->options & NAND_BBT_VERSION) len++; - return mtd->read(mtd, offs, len, &retlen, buf); + return mtd_read(mtd, offs, len, &retlen, buf); } /* Scan read raw data from flash */ @@ -317,7 +317,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, ops.len = min(len, (size_t)mtd->writesize); ops.oobbuf = buf + ops.len; - res = mtd->read_oob(mtd, offs, &ops); + res = mtd_read_oob(mtd, offs, &ops); if (res) return res; @@ -350,7 +350,7 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, ops.oobbuf = oob; ops.len = len; - return mtd->write_oob(mtd, offs, &ops); + return mtd_write_oob(mtd, offs, &ops); } static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) @@ -434,7 +434,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, * Read the full oob until read_oob is fixed to handle single * byte reads for 16 bit buswidth. */ - ret = mtd->read_oob(mtd, offs, &ops); + ret = mtd_read_oob(mtd, offs, &ops); /* Ignore ECC errors when checking for BBM */ if (ret && !mtd_is_bitflip_or_eccerr(ret)) return ret; @@ -756,7 +756,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, /* Make it block aligned */ to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); len = 1 << this->bbt_erase_shift; - res = mtd->read(mtd, to, len, &retlen, buf); + res = mtd_read(mtd, to, len, &retlen, buf); if (res < 0) { if (retlen != len) { pr_info("nand_bbt: error reading block " @@ -769,7 +769,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, /* Read oob data */ ops.ooblen = (len >> this->page_shift) * mtd->oobsize; ops.oobbuf = &buf[len]; - res = mtd->read_oob(mtd, to + mtd->writesize, &ops); + res = mtd_read_oob(mtd, to + mtd->writesize, &ops); if (res < 0 || ops.oobretlen != ops.ooblen) goto outerr; diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 00cf1b0..af4fe8c 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -73,11 +73,12 @@ struct nand_flash_dev nand_flash_ids[] = { #define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) - /*512 Megabit */ + /* 512 Megabit */ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS}, + {"NAND 64MiB 3,3V 8-bit", 0xF0, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, @@ -176,6 +177,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_MICRON, "Micron"}, {NAND_MFR_AMD, "AMD"}, + {NAND_MFR_MACRONIX, "Macronix"}, {0x0, "Unknown"} }; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 34c03be..261f478 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -737,7 +737,7 @@ static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd) return -EINVAL; } offset = erase_block_no * ns->geom.secsz; - if (mtd->block_markbad(mtd, offset)) { + if (mtd_block_markbad(mtd, offset)) { NS_ERR("invalid badblocks.\n"); return -EINVAL; } diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index f8aacf4..ec68854 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -294,18 +294,7 @@ static struct platform_driver ndfc_driver = { .remove = __devexit_p(ndfc_remove), }; -static int __init ndfc_nand_init(void) -{ - return platform_driver_register(&ndfc_driver); -} - -static void __exit ndfc_nand_exit(void) -{ - platform_driver_unregister(&ndfc_driver); -} - -module_init(ndfc_nand_init); -module_exit(ndfc_nand_exit); +module_platform_driver(ndfc_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index b463ecf..a86aa81 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c @@ -201,7 +201,7 @@ static int nomadik_nand_suspend(struct device *dev) struct nomadik_nand_host *host = dev_get_drvdata(dev); int ret = 0; if (host) - ret = host->mtd.suspend(&host->mtd); + ret = mtd_suspend(&host->mtd); return ret; } @@ -209,7 +209,7 @@ static int nomadik_nand_resume(struct device *dev) { struct nomadik_nand_host *host = dev_get_drvdata(dev); if (host) - host->mtd.resume(&host->mtd); + mtd_resume(&host->mtd); return 0; } @@ -228,19 +228,7 @@ static struct platform_driver nomadik_nand_driver = { }, }; -static int __init nand_nomadik_init(void) -{ - pr_info("Nomadik NAND driver\n"); - return platform_driver_register(&nomadik_nand_driver); -} - -static void __exit nand_nomadik_exit(void) -{ - platform_driver_unregister(&nomadik_nand_driver); -} - -module_init(nand_nomadik_init); -module_exit(nand_nomadik_exit); +module_platform_driver(nomadik_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)"); diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index fa8faed..8febe46 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -364,18 +364,7 @@ static struct platform_driver nuc900_nand_driver = { }, }; -static int __init nuc900_nand_init(void) -{ - return platform_driver_register(&nuc900_nand_driver); -} - -static void __exit nuc900_nand_exit(void) -{ - platform_driver_unregister(&nuc900_nand_driver); -} - -module_init(nuc900_nand_init); -module_exit(nuc900_nand_exit); +module_platform_driver(nuc900_nand_driver); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("w90p910/NUC9xx nand driver!"); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index f745f00..b3a883e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1145,20 +1145,7 @@ static struct platform_driver omap_nand_driver = { }, }; -static int __init omap_nand_init(void) -{ - pr_info("%s driver initializing\n", DRIVER_NAME); - - return platform_driver_register(&omap_nand_driver); -} - -static void __exit omap_nand_exit(void) -{ - platform_driver_unregister(&omap_nand_driver); -} - -module_init(omap_nand_init); -module_exit(omap_nand_exit); +module_platform_driver(omap_nand_driver); MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index a97264e..974dbf8 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -230,17 +230,7 @@ static struct platform_driver pasemi_nand_driver = .remove = pasemi_nand_remove, }; -static int __init pasemi_nand_init(void) -{ - return platform_driver_register(&pasemi_nand_driver); -} -module_init(pasemi_nand_init); - -static void __exit pasemi_nand_exit(void) -{ - platform_driver_unregister(&pasemi_nand_driver); -} -module_exit(pasemi_nand_exit); +module_platform_driver(pasemi_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index ea8e123..7f2da69 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -148,18 +148,7 @@ static struct platform_driver plat_nand_driver = { }, }; -static int __init plat_nand_init(void) -{ - return platform_driver_register(&plat_nand_driver); -} - -static void __exit plat_nand_exit(void) -{ - platform_driver_unregister(&plat_nand_driver); -} - -module_init(plat_nand_init); -module_exit(plat_nand_exit); +module_platform_driver(plat_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vitaly Wool"); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 9eb7f87..5c3d719 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -185,7 +185,7 @@ struct pxa3xx_nand_info { uint32_t ndcb2; }; -static int use_dma = 1; +static bool use_dma = 1; module_param(use_dma, bool, 0444); MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW"); @@ -1258,7 +1258,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) for (cs = 0; cs < pdata->num_cs; cs++) { mtd = info->host[cs]->mtd; - mtd->suspend(mtd); + mtd_suspend(mtd); } return 0; @@ -1291,7 +1291,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) nand_writel(info, NDSR, NDSR_MASK); for (cs = 0; cs < pdata->num_cs; cs++) { mtd = info->host[cs]->mtd; - mtd->resume(mtd); + mtd_resume(mtd); } return 0; @@ -1311,17 +1311,7 @@ static struct platform_driver pxa3xx_nand_driver = { .resume = pxa3xx_nand_resume, }; -static int __init pxa3xx_nand_init(void) -{ - return platform_driver_register(&pxa3xx_nand_driver); -} -module_init(pxa3xx_nand_init); - -static void __exit pxa3xx_nand_exit(void) -{ - platform_driver_unregister(&pxa3xx_nand_driver); -} -module_exit(pxa3xx_nand_exit); +module_platform_driver(pxa3xx_nand_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("PXA3xx NAND controller driver"); diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index f20f393..769a4e0 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -22,7 +22,7 @@ #include "r852.h" -static int r852_enable_dma = 1; +static bool r852_enable_dma = 1; module_param(r852_enable_dma, bool, S_IRUGO); MODULE_PARM_DESC(r852_enable_dma, "Enable usage of the DMA (default)"); diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 619d2a5..b175c0f 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -230,17 +230,7 @@ static struct platform_driver sharpsl_nand_driver = { .remove = __devexit_p(sharpsl_nand_remove), }; -static int __init sharpsl_nand_init(void) -{ - return platform_driver_register(&sharpsl_nand_driver); -} -module_init(sharpsl_nand_init); - -static void __exit sharpsl_nand_exit(void) -{ - platform_driver_unregister(&sharpsl_nand_driver); -} -module_exit(sharpsl_nand_exit); +module_platform_driver(sharpsl_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index 32ae5af..774c3c2 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c @@ -55,7 +55,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) ops.datbuf = NULL; - ret = mtd->write_oob(mtd, ofs, &ops); + ret = mtd_write_oob(mtd, ofs, &ops); if (ret < 0 || ops.oobretlen != SM_OOB_SIZE) { printk(KERN_NOTICE "sm_common: can't mark sector at %i as bad\n", diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index 0fb24f9..e02b08b 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -273,18 +273,7 @@ static struct platform_driver socrates_nand_driver = { .remove = __devexit_p(socrates_nand_remove), }; -static int __init socrates_nand_init(void) -{ - return platform_driver_register(&socrates_nand_driver); -} - -static void __exit socrates_nand_exit(void) -{ - platform_driver_unregister(&socrates_nand_driver); -} - -module_init(socrates_nand_init); -module_exit(socrates_nand_exit); +module_platform_driver(socrates_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ilya Yanok"); diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index beebd95..6caa0cd 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -533,18 +533,7 @@ static struct platform_driver tmio_driver = { .resume = tmio_resume, }; -static int __init tmio_init(void) -{ - return platform_driver_register(&tmio_driver); -} - -static void __exit tmio_exit(void) -{ - platform_driver_unregister(&tmio_driver); -} - -module_init(tmio_init); -module_exit(tmio_exit); +module_platform_driver(tmio_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton, Dirk Opfer, Chris Humbert, Dmitry Baryshkov"); diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index ace46fd..c7c4f1d 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -298,11 +298,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - if (!devm_request_mem_region(&dev->dev, res->start, - resource_size(res), dev_name(&dev->dev))) - return -EBUSY; - drvdata->base = devm_ioremap(&dev->dev, res->start, - resource_size(res)); + drvdata->base = devm_request_and_ioremap(&dev->dev, res); if (!drvdata->base) return -EBUSY; |