Commit ce9ef9d9 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by David Woodhouse

MTD: NAND flash driver updates.

 - Use new RS library for ECC
 - Add support for new NAND flash chips
 - New board support:
   - iPAQ H1910
   - Renesas AG-AND devel board
   - Simtec S3C210 
 - Support for shared controllers on multiple chips.
Signed-Off-By: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-Off-By: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 91c73041
# drivers/mtd/nand/Kconfig # drivers/mtd/nand/Kconfig
# $Id: Kconfig,v 1.17 2004/08/10 14:24:07 dwmw2 Exp $ # $Id: Kconfig,v 1.22 2004/10/05 22:11:46 gleixner Exp $
menu "NAND Flash Device Drivers" menu "NAND Flash Device Drivers"
depends on MTD!=n depends on MTD!=n
...@@ -36,6 +36,12 @@ config MTD_NAND_EDB7312 ...@@ -36,6 +36,12 @@ config MTD_NAND_EDB7312
This enables the driver for the Cirrus Logic EBD7312 evaluation This enables the driver for the Cirrus Logic EBD7312 evaluation
board to access the onboard NAND Flash. board to access the onboard NAND Flash.
config MTD_NAND_H1900
tristate "iPAQ H1900 flash"
depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS
help
This enables the driver for the iPAQ h1900 flash.
config MTD_NAND_SPIA config MTD_NAND_SPIA
tristate "NAND Flash device on SPIA board" tristate "NAND Flash device on SPIA board"
depends on ARM && ARCH_P720T && MTD_NAND depends on ARM && ARCH_P720T && MTD_NAND
...@@ -74,15 +80,54 @@ config MTD_NAND_AU1550 ...@@ -74,15 +80,54 @@ config MTD_NAND_AU1550
This enables the driver for the NAND flash controller on the This enables the driver for the NAND flash controller on the
AMD/Alchemy 1550 SOC. AMD/Alchemy 1550 SOC.
config MTD_NAND_RTC_FROM4
tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
depends on MTD_NAND && SH_SOLUTION_ENGINE
select REED_SOLOMON
select REED_SOLOMON_DEC8
help
This enables the driver for the Renesas Technology AG-AND
flash interface board (FROM_BOARD4)
config MTD_NAND_PPCHAMELEONEVB config MTD_NAND_PPCHAMELEONEVB
tristate "NAND Flash device on PPChameleonEVB board" tristate "NAND Flash device on PPChameleonEVB board"
depends on PPCHAMELEONEVB && MTD_NAND depends on PPCHAMELEONEVB && MTD_NAND
help help
This enables the NAND flash driver on the PPChameleon EVB Board. This enables the NAND flash driver on the PPChameleon EVB Board.
config MTD_NAND_S3C2410
tristate "NAND Flash support for S3C2410 SoC"
depends on ARCH_S3C2410 && MTD_NAND
help
This enables the NAND flash controller on the S3C2410.
No board specfic support is done by this driver, each board
must advertise a platform_device for the driver to attach.
config MTD_NAND_S3C2410_DEBUG
bool "S3C2410 NAND driver debug"
depends on MTD_NAND_S3C2410
help
Enable debugging of the S3C2410 NAND driver
config MTD_NAND_S3C2410_HWECC
bool "S3C2410 NAND Hardware ECC"
depends on MTD_NAND_S3C2410
help
Enable the use of the S3C2410's internal ECC generator when
using NAND. Early versions of the chip have had problems with
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
If you lay down a device with the hardware ECC, then you will
currently not be able to switch to software, as there is no
implementation for ECC method used by the S3C2410
config MTD_NAND_DISKONCHIP config MTD_NAND_DISKONCHIP
tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
depends on MTD_NAND && EXPERIMENTAL depends on MTD_NAND && EXPERIMENTAL
select REED_SOLOMON
select REED_SOLOMON_DEC16
help help
This is a reimplementation of M-Systems DiskOnChip 2000, This is a reimplementation of M-Systems DiskOnChip 2000,
Millennium and Millennium Plus as a standard NAND device driver, Millennium and Millennium Plus as a standard NAND device driver,
......
# #
# linux/drivers/nand/Makefile # linux/drivers/nand/Makefile
# #
# $Id: Makefile.common,v 1.9 2004/07/12 16:07:31 dwmw2 Exp $ # $Id: Makefile.common,v 1.13 2004/09/28 22:04:23 bjd Exp $
obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
...@@ -14,6 +14,9 @@ obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o ...@@ -14,6 +14,9 @@ obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o
obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o
obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o
nand-objs = nand_base.o nand_bbt.o nand-objs = nand_base.o nand_bbt.o
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Derived from drivers/mtd/spia.c * Derived from drivers/mtd/spia.c
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* *
* $Id: autcpu12.c,v 1.20 2004/07/20 02:44:26 dwmw2 Exp $ * $Id: autcpu12.c,v 1.21 2004/09/16 23:27:14 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -48,7 +48,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE; ...@@ -48,7 +48,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE;
static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET; static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
static int autcpu12_fio_base; static void __iomem * autcpu12_fio_base;
#ifdef MODULE #ifdef MODULE
MODULE_PARM(autcpu12_fio_pbase, "i"); MODULE_PARM(autcpu12_fio_pbase, "i");
...@@ -150,7 +150,7 @@ int __init autcpu12_init (void) ...@@ -150,7 +150,7 @@ int __init autcpu12_init (void)
} }
/* map physical adress */ /* map physical adress */
autcpu12_fio_base=(unsigned long)ioremap(autcpu12_fio_pbase,SZ_1K); autcpu12_fio_base=(void __iomem *)ioremap(autcpu12_fio_pbase,SZ_1K);
if(!autcpu12_fio_base){ if(!autcpu12_fio_base){
printk("Ioremap autcpu12 SmartMedia Card failed\n"); printk("Ioremap autcpu12 SmartMedia Card failed\n");
err = -EIO; err = -EIO;
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Derived from drivers/mtd/nand/autcpu12.c * Derived from drivers/mtd/nand/autcpu12.c
* Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
* *
* $Id: edb7312.c,v 1.8 2004/07/12 15:03:26 dwmw2 Exp $ * $Id: edb7312.c,v 1.10 2004/10/05 13:50:20 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -53,9 +53,9 @@ static struct mtd_info *ep7312_mtd = NULL; ...@@ -53,9 +53,9 @@ static struct mtd_info *ep7312_mtd = NULL;
* Module stuff * Module stuff
*/ */
static int ep7312_fio_pbase = EP7312_FIO_PBASE; static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
static int ep7312_pxdr = EP7312_PXDR; static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR;
static int ep7312_pxddr = EP7312_PXDDR; static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR;
#ifdef MODULE #ifdef MODULE
MODULE_PARM(ep7312_fio_pbase, "i"); MODULE_PARM(ep7312_fio_pbase, "i");
...@@ -131,7 +131,7 @@ static int __init ep7312_init (void) ...@@ -131,7 +131,7 @@ static int __init ep7312_init (void)
const char *part_type = 0; const char *part_type = 0;
int mtd_parts_nb = 0; int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = 0; struct mtd_partition *mtd_parts = 0;
int ep7312_fio_base; void __iomem * ep7312_fio_base;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ep7312_mtd = kmalloc(sizeof(struct mtd_info) + ep7312_mtd = kmalloc(sizeof(struct mtd_info) +
...@@ -143,7 +143,7 @@ static int __init ep7312_init (void) ...@@ -143,7 +143,7 @@ static int __init ep7312_init (void)
} }
/* map physical adress */ /* map physical adress */
ep7312_fio_base = (unsigned long)ioremap(ep7312_fio_pbase, SZ_1K); ep7312_fio_base = (void __iomem *)ioremap(ep7312_fio_pbase, SZ_1K);
if(!ep7312_fio_base) { if(!ep7312_fio_base) {
printk("ioremap EDB7312 NAND flash failed\n"); printk("ioremap EDB7312 NAND flash failed\n");
kfree(ep7312_mtd); kfree(ep7312_mtd);
...@@ -181,16 +181,7 @@ static int __init ep7312_init (void) ...@@ -181,16 +181,7 @@ static int __init ep7312_init (void)
return -ENXIO; return -ENXIO;
} }
/* Allocate memory for internal data buffer */ #ifdef CONFIG_MTD_PARTITIONS
this->data_buf = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk("Unable to allocate NAND data buffer for EDB7312.\n");
iounmap((void *)ep7312_fio_base);
kfree (ep7312_mtd);
return -ENOMEM;
}
#ifdef CONFIG_PARTITIONS
ep7312_mtd->name = "edb7312-nand"; ep7312_mtd->name = "edb7312-nand";
mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
&mtd_parts, 0); &mtd_parts, 0);
...@@ -221,8 +212,8 @@ static void __exit ep7312_cleanup (void) ...@@ -221,8 +212,8 @@ static void __exit ep7312_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
/* Unregister the device */ /* Release resources, unregister device */
del_mtd_device (ep7312_mtd); nand_release (ap7312_mtd);
/* Free internal data buffer */ /* Free internal data buffer */
kfree (this->data_buf); kfree (this->data_buf);
......
/*
* drivers/mtd/nand/h1910.c
*
* Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
*
* Derived from drivers/mtd/nand/edb7312.c
* Copyright (C) 2002 Marius Grger (mag@sysgo.de)
* Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
*
* $Id: h1910.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
*
* 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.
*
* Overview:
* This is a device driver for the NAND flash device found on the
* iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is
* a 128Mibit (16MiB x 8 bits) NAND flash device.
*/
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
#include <asm/sizes.h>
#include <asm/arch/h1900-gpio.h>
#include <asm/arch/ipaq.h>
/*
* MTD structure for EDB7312 board
*/
static struct mtd_info *h1910_nand_mtd = NULL;
/*
* Module stuff
*/
#ifdef CONFIG_MTD_PARTITIONS
/*
* Define static partitions for flash device
*/
static struct mtd_partition partition_info[] = {
{ name: "h1910 NAND Flash",
offset: 0,
size: 16*1024*1024 }
};
#define NUM_PARTITIONS 1
#endif
/*
* hardware specific access to control-lines
*/
static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
{
struct nand_chip* this = (struct nand_chip *) (mtd->priv);
switch(cmd) {
case NAND_CTL_SETCLE:
this->IO_ADDR_R |= (1 << 2);
this->IO_ADDR_W |= (1 << 2);
break;
case NAND_CTL_CLRCLE:
this->IO_ADDR_R &= ~(1 << 2);
this->IO_ADDR_W &= ~(1 << 2);
break;
case NAND_CTL_SETALE:
this->IO_ADDR_R |= (1 << 3);
this->IO_ADDR_W |= (1 << 3);
break;
case NAND_CTL_CLRALE:
this->IO_ADDR_R &= ~(1 << 3);
this->IO_ADDR_W &= ~(1 << 3);
break;
case NAND_CTL_SETNCE:
break;
case NAND_CTL_CLRNCE:
break;
}
}
/*
* read device ready pin
*/
#if 0
static int h1910_device_ready(struct mtd_info *mtd)
{
return (GPLR(55) & GPIO_bit(55));
}
#endif
/*
* Main initialization routine
*/
static int __init h1910_init (void)
{
struct nand_chip *this;
const char *part_type = 0;
int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = 0;
void __iomem *nandaddr;
if (!machine_is_h1900())
return -ENODEV;
nandaddr = (void __iomem *)__ioremap(0x08000000, 0x1000, 0, 1);
if (!nandaddr) {
printk("Failed to ioremap nand flash.\n");
return -ENOMEM;
}
/* Allocate memory for MTD device structure and private data */
h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip),
GFP_KERNEL);
if (!h1910_nand_mtd) {
printk("Unable to allocate h1910 NAND MTD device structure.\n");
iounmap ((void *) nandaddr);
return -ENOMEM;
}
/* Get pointer to private data */
this = (struct nand_chip *) (&h1910_nand_mtd[1]);
/* Initialize structures */
memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
h1910_nand_mtd->priv = this;
/*
* Enable VPEN
*/
GPSR(37) = GPIO_bit(37);
/* insert callbacks */
this->IO_ADDR_R = nandaddr;
this->IO_ADDR_W = nandaddr;
this->hwcontrol = h1910_hwcontrol;
this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
/* 15 us command delay time */
this->chip_delay = 50;
this->eccmode = NAND_ECC_SOFT;
this->options = NAND_NO_AUTOINCR;
/* Scan to find existence of the device */
if (nand_scan (h1910_nand_mtd, 1)) {
printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
kfree (h1910_nand_mtd);
iounmap ((void *) nandaddr);
return -ENXIO;
}
#ifdef CONFIG_MTD_CMDLINE_PARTS
mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts,
"h1910-nand");
if (mtd_parts_nb > 0)
part_type = "command line";
else
mtd_parts_nb = 0;
#endif
if (mtd_parts_nb == 0)
{
mtd_parts = partition_info;
mtd_parts_nb = NUM_PARTITIONS;
part_type = "static";
}
/* Register the partitions */
printk(KERN_NOTICE "Using %s partition definition\n", part_type);
add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
/* Return happy */
return 0;
}
module_init(h1910_init);
/*
* Clean up routine
*/
static void __exit h1910_cleanup (void)
{
struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
/* Release resources, unregister device */
nand_release (h1910_nand_mtd);
/* Release io resource */
iounmap ((void *) this->IO_ADDR_W);
/* Free the MTD device structure */
kfree (h1910_nand_mtd);
}
module_exit(h1910_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joshua Wise <joshua at joshuawise dot com>");
MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910");
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
* *
* $Id: nand_bbt.c,v 1.24 2004/06/28 08:25:35 gleixner Exp $ * $Id: nand_bbt.c,v 1.26 2004/10/05 13:50:20 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -114,6 +114,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des ...@@ -114,6 +114,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
* @num: the number of bbt descriptors to read * @num: the number of bbt descriptors to read
* @bits: number of bits per block * @bits: number of bits per block
* @offs: offset in the memory table * @offs: offset in the memory table
* @reserved_block_code: Pattern to identify reserved blocks
* *
* Read the bad block table starting from page. * Read the bad block table starting from page.
* *
...@@ -796,7 +797,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) ...@@ -796,7 +797,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
len = mtd->size >> (this->bbt_erase_shift + 2); len = mtd->size >> (this->bbt_erase_shift + 2);
/* Allocate memory (2bit per block) */ /* Allocate memory (2bit per block) */
this->bbt = (uint8_t *) kmalloc (len, GFP_KERNEL); this->bbt = kmalloc (len, GFP_KERNEL);
if (!this->bbt) { if (!this->bbt) {
printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
return -ENOMEM; return -ENOMEM;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Derived from drivers/mtd/nand/edb7312.c * Derived from drivers/mtd/nand/edb7312.c
* *
* *
* $Id: ppchameleonevb.c,v 1.2 2004/05/05 22:09:54 gleixner Exp $ * $Id: ppchameleonevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -74,12 +74,6 @@ MODULE_PARM(ppchameleonevb_fio_pbase, "i"); ...@@ -74,12 +74,6 @@ MODULE_PARM(ppchameleonevb_fio_pbase, "i");
__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
#endif #endif
/* Internal buffers. Page buffer and oob buffer for one block */
static u_char data_buf[2048 + 64];
static u_char oob_buf[64 * 64];
static u_char data_buf_evb[512 + 16];
static u_char oob_buf_evb[16 * 32];
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
/* /*
* Define static partitions for flash devices * Define static partitions for flash devices
...@@ -196,8 +190,8 @@ static int __init ppchameleonevb_init (void) ...@@ -196,8 +190,8 @@ static int __init ppchameleonevb_init (void)
const char *part_type = 0; const char *part_type = 0;
int mtd_parts_nb = 0; int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = 0; struct mtd_partition *mtd_parts = 0;
int ppchameleon_fio_base; void __iomem *ppchameleon_fio_base;
int ppchameleonevb_fio_base; void __iomem *ppchameleonevb_fio_base;
/********************************* /*********************************
...@@ -205,15 +199,14 @@ static int __init ppchameleonevb_init (void) ...@@ -205,15 +199,14 @@ static int __init ppchameleonevb_init (void)
*********************************/ *********************************/
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip), sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!ppchameleon_mtd) { if (!ppchameleon_mtd) {
printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
} }
/* map physical address */ /* map physical address */
ppchameleon_fio_base = (unsigned long)ioremap(ppchameleon_fio_pbase, SZ_4M); ppchameleon_fio_base = (void __iomem *) ioremap(ppchameleon_fio_pbase, SZ_4M);
if(!ppchameleon_fio_base) { if(!ppchameleon_fio_base) {
printk("ioremap PPChameleon NAND flash failed\n"); printk("ioremap PPChameleon NAND flash failed\n");
kfree(ppchameleon_mtd); kfree(ppchameleon_mtd);
...@@ -264,10 +257,6 @@ static int __init ppchameleonevb_init (void) ...@@ -264,10 +257,6 @@ static int __init ppchameleonevb_init (void)
/* ECC mode */ /* ECC mode */
this->eccmode = NAND_ECC_SOFT; this->eccmode = NAND_ECC_SOFT;
/* Set internal data buffer */
this->data_buf = data_buf;
this->oob_buf = oob_buf;
/* Scan to find existence of the device (it could not be mounted) */ /* Scan to find existence of the device (it could not be mounted) */
if (nand_scan (ppchameleon_mtd, 1)) { if (nand_scan (ppchameleon_mtd, 1)) {
iounmap((void *)ppchameleon_fio_base); iounmap((void *)ppchameleon_fio_base);
...@@ -309,15 +298,14 @@ static int __init ppchameleonevb_init (void) ...@@ -309,15 +298,14 @@ static int __init ppchameleonevb_init (void)
****************************/ ****************************/
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip), sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!ppchameleonevb_mtd) { if (!ppchameleonevb_mtd) {
printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
} }
/* map physical address */ /* map physical address */
ppchameleonevb_fio_base = (unsigned long)ioremap(ppchameleonevb_fio_pbase, SZ_4M); ppchameleonevb_fio_base = (void __iomem *)ioremap(ppchameleonevb_fio_pbase, SZ_4M);
if(!ppchameleonevb_fio_base) { if(!ppchameleonevb_fio_base) {
printk("ioremap PPChameleonEVB NAND flash failed\n"); printk("ioremap PPChameleonEVB NAND flash failed\n");
kfree(ppchameleonevb_mtd); kfree(ppchameleonevb_mtd);
...@@ -349,7 +337,8 @@ static int __init ppchameleonevb_init (void) ...@@ -349,7 +337,8 @@ static int __init ppchameleonevb_init (void)
out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
/* enable output driver */ /* enable output driver */
out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
#ifdef USE_READY_BUSY_PIN #ifdef USE_READY_BUSY_PIN
/* three-state select */ /* three-state select */
out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC); out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
...@@ -359,7 +348,6 @@ static int __init ppchameleonevb_init (void) ...@@ -359,7 +348,6 @@ static int __init ppchameleonevb_init (void)
out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
#endif #endif
/* insert callbacks */ /* insert callbacks */
this->IO_ADDR_R = ppchameleonevb_fio_base; this->IO_ADDR_R = ppchameleonevb_fio_base;
this->IO_ADDR_W = ppchameleonevb_fio_base; this->IO_ADDR_W = ppchameleonevb_fio_base;
...@@ -372,10 +360,6 @@ static int __init ppchameleonevb_init (void) ...@@ -372,10 +360,6 @@ static int __init ppchameleonevb_init (void)
/* ECC mode */ /* ECC mode */
this->eccmode = NAND_ECC_SOFT; this->eccmode = NAND_ECC_SOFT;
/* Set internal data buffer */
this->data_buf = data_buf_evb;
this->oob_buf = oob_buf_evb;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
if (nand_scan (ppchameleonevb_mtd, 1)) { if (nand_scan (ppchameleonevb_mtd, 1)) {
iounmap((void *)ppchameleonevb_fio_base); iounmap((void *)ppchameleonevb_fio_base);
...@@ -412,15 +396,20 @@ module_init(ppchameleonevb_init); ...@@ -412,15 +396,20 @@ module_init(ppchameleonevb_init);
*/ */
static void __exit ppchameleonevb_cleanup (void) static void __exit ppchameleonevb_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) &ppchameleonevb_mtd[1]; struct nand_chip *this;
/* Unregister the device */
del_mtd_device (ppchameleonevb_mtd);
/* Free internal data buffer */ /* Release resources, unregister device(s) */
kfree (this->data_buf); nand_release (ppchameleon_mtd);
nand_release (ppchameleonevb_mtd);
/* Release iomaps */
this = (struct nand_chip *) &ppchameleon_mtd[1];
iounmap((void *) this->IO_ADDR_R;
this = (struct nand_chip *) &ppchameleonevb_mtd[1];
iounmap((void *) this->IO_ADDR_R;
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (ppchameleon_mtd);
kfree (ppchameleonevb_mtd); kfree (ppchameleonevb_mtd);
} }
module_exit(ppchameleonevb_cleanup); module_exit(ppchameleonevb_cleanup);
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* to controllines (due to change in nand.c) * to controllines (due to change in nand.c)
* page_cache added * page_cache added
* *
* $Id: spia.c,v 1.21 2003/07/11 15:12:29 dwmw2 Exp $ * $Id: spia.c,v 1.23 2004/10/05 13:50:20 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -132,8 +132,8 @@ int __init spia_init (void) ...@@ -132,8 +132,8 @@ int __init spia_init (void)
(*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07;
/* Set address of NAND IO lines */ /* Set address of NAND IO lines */
this->IO_ADDR_R = spia_fio_base; this->IO_ADDR_R = (void __iomem *) spia_fio_base;
this->IO_ADDR_W = spia_fio_base; this->IO_ADDR_W = (void __iomem *) spia_fio_base;
/* Set address of hardware control function */ /* Set address of hardware control function */
this->hwcontrol = spia_hwcontrol; this->hwcontrol = spia_hwcontrol;
/* 15 us command delay time */ /* 15 us command delay time */
...@@ -145,14 +145,6 @@ int __init spia_init (void) ...@@ -145,14 +145,6 @@ int __init spia_init (void)
return -ENXIO; return -ENXIO;
} }
/* Allocate memory for internal data buffer */
this->data_buf = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk ("Unable to allocate NAND data buffer for SPIA.\n");
kfree (spia_mtd);
return -ENOMEM;
}
/* Register the partitions */ /* Register the partitions */
add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS);
...@@ -167,13 +159,8 @@ module_init(spia_init); ...@@ -167,13 +159,8 @@ module_init(spia_init);
#ifdef MODULE #ifdef MODULE
static void __exit spia_cleanup (void) static void __exit spia_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) &spia_mtd[1]; /* Release resources, unregister device */
nand_release (spia_mtd);
/* Unregister the device */
del_mtd_device (spia_mtd);
/* Free internal data buffer */
kfree (this->data_buf);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (spia_mtd); kfree (spia_mtd);
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* This is a device driver for the NAND flash device found on the * This is a device driver for the NAND flash device found on the
* TI fido board. It supports 32MiB and 64MiB cards * TI fido board. It supports 32MiB and 64MiB cards
* *
* $Id: toto.c,v 1.2 2003/10/21 10:04:58 dwmw2 Exp $ * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
*/ */
#include <linux/slab.h> #include <linux/slab.h>
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
*/ */
static struct mtd_info *toto_mtd = NULL; static struct mtd_info *toto_mtd = NULL;
static int toto_io_base = OMAP_FLASH_1_BASE; static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
#define CONFIG_NAND_WORKAROUND 1 #define CONFIG_NAND_WORKAROUND 1
...@@ -155,14 +155,6 @@ int __init toto_init (void) ...@@ -155,14 +155,6 @@ int __init toto_init (void)
goto out_mtd; goto out_mtd;
} }
/* Allocate memory for internal data buffer */
this->data_buf = kmalloc (sizeof(u_char) * (toto_mtd->oobblock + toto_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk (KERN_WARNING "Unable to allocate NAND data buffer for toto.\n");
err = -ENOMEM;
goto out_mtd;
}
/* Register the partitions */ /* Register the partitions */
switch(toto_mtd->size){ switch(toto_mtd->size){
case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break;
...@@ -194,16 +186,8 @@ module_init(toto_init); ...@@ -194,16 +186,8 @@ module_init(toto_init);
*/ */
static void __exit toto_cleanup (void) static void __exit toto_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) &toto_mtd[1]; /* Release resources, unregister device */
nand_release (toto_mtd);
/* Unregister partitions */
del_mtd_partitions(toto_mtd);
/* Unregister the device */
del_mtd_device (toto_mtd);
/* Free internal data buffers */
kfree (this->data_buf);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (toto_mtd); kfree (toto_mtd);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Derived from drivers/mtd/autcpu12.c * Derived from drivers/mtd/autcpu12.c
* Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
* *
* $Id: tx4925ndfmc.c,v 1.3 2004/07/20 02:44:26 dwmw2 Exp $ * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $
* *
* Copyright (C) 2001 Toshiba Corporation * Copyright (C) 2001 Toshiba Corporation
* *
...@@ -340,8 +340,8 @@ int __init tx4925ndfmc_init (void) ...@@ -340,8 +340,8 @@ int __init tx4925ndfmc_init (void)
tx4925ndfmc_mtd->priv = this; tx4925ndfmc_mtd->priv = this;
/* Set address of NAND IO lines */ /* Set address of NAND IO lines */
this->IO_ADDR_R = (unsigned long)&(tx4925_ndfmcptr->dtr); this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr);
this->IO_ADDR_W = (unsigned long)&(tx4925_ndfmcptr->dtr); this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr);
this->hwcontrol = tx4925ndfmc_hwcontrol; this->hwcontrol = tx4925ndfmc_hwcontrol;
this->enable_hwecc = tx4925ndfmc_enable_hwecc; this->enable_hwecc = tx4925ndfmc_enable_hwecc;
this->calculate_ecc = tx4925ndfmc_readecc; this->calculate_ecc = tx4925ndfmc_readecc;
...@@ -363,14 +363,6 @@ int __init tx4925ndfmc_init (void) ...@@ -363,14 +363,6 @@ int __init tx4925ndfmc_init (void)
goto out_ior; goto out_ior;
} }
/* Allocate memory for internal data buffer */
this->data_buf = kmalloc (sizeof(u_char) * (tx4925ndfmc_mtd->oobblock + tx4925ndfmc_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk ("Unable to allocate NAND data buffer for RBTX4925.\n");
err = -ENOMEM;
goto out_ior;
}
/* Register the partitions */ /* Register the partitions */
#ifdef CONFIG_MTD_CMDLINE_PARTS #ifdef CONFIG_MTD_CMDLINE_PARTS
{ {
...@@ -391,14 +383,12 @@ int __init tx4925ndfmc_init (void) ...@@ -391,14 +383,12 @@ int __init tx4925ndfmc_init (void)
default: { default: {
printk ("Unsupported SmartMedia device\n"); printk ("Unsupported SmartMedia device\n");
err = -ENXIO; err = -ENXIO;
goto out_buf; goto out_ior;
} }
} }
#endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ #endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */
goto out; goto out;
out_buf:
kfree (this->data_buf);
out_ior: out_ior:
out: out:
return err; return err;
...@@ -412,16 +402,8 @@ module_init(tx4925ndfmc_init); ...@@ -412,16 +402,8 @@ module_init(tx4925ndfmc_init);
#ifdef MODULE #ifdef MODULE
static void __exit tx4925ndfmc_cleanup (void) static void __exit tx4925ndfmc_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) &tx4925ndfmc_mtd[1]; /* Release resources, unregister device */
nand_release (tx4925ndfmc_mtd);
/* Unregister partitions */
del_mtd_partitions(tx4925ndfmc_mtd);
/* Unregister the device */
del_mtd_device (tx4925ndfmc_mtd);
/* Free internal data buffers */
kfree (this->data_buf);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (tx4925ndfmc_mtd); kfree (tx4925ndfmc_mtd);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* Based on spia.c by Steven J. Hill * Based on spia.c by Steven J. Hill
* *
* $Id: tx4938ndfmc.c,v 1.2 2004/03/27 19:55:53 gleixner Exp $ * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
* *
* Copyright (C) 2000-2001 Toshiba Corporation * Copyright (C) 2000-2001 Toshiba Corporation
* *
...@@ -365,14 +365,6 @@ int __init tx4938ndfmc_init (void) ...@@ -365,14 +365,6 @@ int __init tx4938ndfmc_init (void)
return -ENXIO; return -ENXIO;
} }
/* Allocate memory for internal data buffer */
this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk ("Unable to allocate NAND data buffer for TX4938.\n");
kfree (tx4938ndfmc_mtd);
return -ENOMEM;
}
if (protected) { if (protected) {
printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); printk(KERN_INFO "TX4938 NDFMC: write protected.\n");
tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE);
...@@ -401,19 +393,11 @@ module_init(tx4938ndfmc_init); ...@@ -401,19 +393,11 @@ module_init(tx4938ndfmc_init);
*/ */
static void __exit tx4938ndfmc_cleanup (void) static void __exit tx4938ndfmc_cleanup (void)
{ {
struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv; /* Release resources, unregister device */
nand_release (tx4938ndfmc_mtd);
/* Unregister the device */
#ifdef CONFIG_MTD_CMDLINE_PARTS
del_mtd_partitions(tx4938ndfmc_mtd);
#endif
del_mtd_device (tx4938ndfmc_mtd);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (tx4938ndfmc_mtd); kfree (tx4938ndfmc_mtd);
/* Free internal data buffer */
kfree (this->data_buf);
} }
module_exit(tx4938ndfmc_cleanup); module_exit(tx4938ndfmc_cleanup);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Steven J. Hill <sjhill@realitydiluted.com> * Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de> * Thomas Gleixner <tglx@linutronix.de>
* *
* $Id: nand.h,v 1.63 2004/07/07 16:29:43 gleixner Exp $ * $Id: nand.h,v 1.66 2004/10/02 10:07:08 gleixner Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -212,6 +212,18 @@ typedef enum { ...@@ -212,6 +212,18 @@ typedef enum {
FL_CACHEDPRG, FL_CACHEDPRG,
} nand_state_t; } nand_state_t;
/* Keep gcc happy */
struct nand_chip;
/**
* struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
* @lock: protection lock
* @active: the mtd device which holds the controller currently
*/
struct nand_hw_control {
spinlock_t lock;
struct nand_chip *active;
};
/** /**
* struct nand_chip - NAND Private Flash Chip Data * struct nand_chip - NAND Private Flash Chip Data
...@@ -265,12 +277,13 @@ typedef enum { ...@@ -265,12 +277,13 @@ typedef enum {
* @bbt: [INTERN] bad block table pointer * @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
* @bbt_md: [REPLACEABLE] bad block table mirror descriptor * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
* @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
* @priv: [OPTIONAL] pointer to private chip date * @priv: [OPTIONAL] pointer to private chip date
*/ */
struct nand_chip { struct nand_chip {
unsigned long IO_ADDR_R; void __iomem *IO_ADDR_R;
unsigned long IO_ADDR_W; void __iomem *IO_ADDR_W;
u_char (*read_byte)(struct mtd_info *mtd); u_char (*read_byte)(struct mtd_info *mtd);
void (*write_byte)(struct mtd_info *mtd, u_char byte); void (*write_byte)(struct mtd_info *mtd, u_char byte);
...@@ -317,6 +330,7 @@ struct nand_chip { ...@@ -317,6 +330,7 @@ struct nand_chip {
uint8_t *bbt; uint8_t *bbt;
struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_td;
struct nand_bbt_descr *bbt_md; struct nand_bbt_descr *bbt_md;
struct nand_hw_control *controller;
void *priv; void *priv;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment