Commit 987817ef authored by David Woodhouse's avatar David Woodhouse

NAND flash driver updates.

Update the core NAND code:
 - support multiple chips
 - support bad block tables
 - improved generic ECC support and 'spare area' usage.
 - 16-bit NAND
 - Large-block NAND devices
 - Renesas AG-AND devices
 - M-Systems DiskOnChip devices
 - Other new board support wrappers

Most of the work was done by Thomas Gleixner.
Signed-Off-By: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 29b6d1fb
......@@ -1090,6 +1090,10 @@ E: jbglaw@lug-owl.de
D: SRM environment driver (for Alpha systems)
P: 1024D/8399E1BB 250D 3BCF 7127 0D8C A444 A961 1DBD 5E75 8399 E1BB
N: Thomas Gleixner
E: tglx@linutronix.de
D: NAND flash hardware support, JFFS2 on NAND flash
N: Richard E. Gooch
E: rgooch@atnf.csiro.au
D: parent process death signal to children
......
......@@ -5,7 +5,7 @@
*
* This code is GPL
*
* $Id: mtdpart.c,v 1.41 2003/06/18 14:53:02 dwmw2 Exp $
* $Id: mtdpart.c,v 1.46 2004/07/12 13:28:07 dwmw2 Exp $
*
* 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
* added support for read_oob, write_oob
......@@ -239,12 +239,16 @@ static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs,
static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
{
struct mtd_part *part = PART(mtd);
int ret;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (instr->addr >= mtd->size)
return -EINVAL;
instr->addr += part->offset;
return part->master->erase(part->master, instr);
ret = part->master->erase(part->master, instr);
if (instr->fail_addr != 0xffffffff)
instr->fail_addr -= part->offset;
return ret;
}
static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
......@@ -281,6 +285,26 @@ static void part_resume(struct mtd_info *mtd)
part->master->resume(part->master);
}
static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
if (ofs >= mtd->size)
return -EINVAL;
ofs += part->offset;
return part->master->block_isbad(part->master, ofs);
}
static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (ofs >= mtd->size)
return -EINVAL;
ofs += part->offset;
return part->master->block_markbad(part->master, ofs);
}
/*
* This function unregisters and destroy all slave MTD objects which are
* attached to the given master MTD object.
......@@ -316,7 +340,7 @@ int del_mtd_partitions(struct mtd_info *master)
*/
int add_mtd_partitions(struct mtd_info *master,
struct mtd_partition *parts,
const struct mtd_partition *parts,
int nbparts)
{
struct mtd_part *slave;
......@@ -391,6 +415,10 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.lock = part_lock;
if (master->unlock)
slave->mtd.unlock = part_unlock;
if (master->block_isbad)
slave->mtd.block_isbad = part_block_isbad;
if (master->block_markbad)
slave->mtd.block_markbad = part_block_markbad;
slave->mtd.erase = part_erase;
slave->master = master;
slave->offset = parts[i].offset;
......@@ -461,6 +489,9 @@ int add_mtd_partitions(struct mtd_info *master,
parts[i].name);
}
/* copy oobinfo from master */
memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
if(parts[i].mtdp)
{ /* store the object pointer (caller may or may not register it */
*parts[i].mtdp = &slave->mtd;
......
# drivers/mtd/nand/Kconfig
# $Id: Kconfig,v 1.4 2003/05/28 10:04:23 dwmw2 Exp $
# $Id: Kconfig,v 1.14 2004/07/13 00:14:35 dbrown Exp $
menu "NAND Flash Device Drivers"
depends on MTD!=n
......@@ -9,7 +9,7 @@ config MTD_NAND
depends on MTD
help
This enables support for accessing all type of NAND flash
devices with an 8-bit data bus interface. For further information see
devices. For further information see
<http://www.linux-mtd.infradead.org/tech/nand.html>.
config MTD_NAND_VERIFY_WRITE
......@@ -42,10 +42,73 @@ config MTD_NAND_SPIA
help
If you had to ask, you don't have one. Say 'N'.
config MTD_NAND_TOTO
tristate "NAND Flash device on TOTO board"
depends on ARM && ARCH_OMAP && MTD_NAND
help
Support for NAND flash on Texas Instruments Toto platform.
config MTD_NAND_IDS
tristate
default y if MTD_NAND = y || MTD_DOC2000 = y || MTD_DOC2001 = y || MTD_DOC2001PLUS = y
default m if MTD_NAND = m || MTD_DOC2000 = m || MTD_DOC2001 = m || MTD_DOC2001PLUS = m
endmenu
config MTD_NAND_TX4925NDFMC
tristate "SmartMedia Card on Toshiba RBTX4925 reference board"
depends on TOSHIBA_RBTX4925 && MTD_NAND && TOSHIBA_RBTX4925_MPLEX_NAND
help
This enables the driver for the NAND flash device found on the
Toshiba RBTX4925 reference board, which is a SmartMediaCard.
config MTD_NAND_TX4938NDFMC
tristate "NAND Flash device on Toshiba RBTX4938 reference board"
depends on TOSHIBA_RBTX4938 && MTD_NAND && TOSHIBA_RBTX4938_MPLEX_NAND
help
This enables the driver for the NAND flash device found on the
Toshiba RBTX4938 reference board.
config MTD_NAND_AU1550
tristate "Au1550 NAND support"
depends on SOC_AU1550 && MTD_NAND
help
This enables the driver for the NAND flash controller on the
AMD/Alchemy 1550 SOC.
config MTD_NAND_PPCHAMELEONEVB
tristate "NAND Flash device on PPChameleonEVB board"
depends on PPCHAMELEONEVB && MTD_NAND
help
This enables the NAND flash driver on the PPChameleon EVB Board.
config MTD_NAND_DISKONCHIP
tristate "DiskOnChip 2000 and Millennium (NAND reimplementation) (EXPERIMENTAL)"
depends on MTD_NAND && EXPERIMENTAL
help
This is a reimplementation of M-Systems DiskOnChip 2000 and
Millennium as a standard NAND device driver, as opposed to the
earlier self-contained MTD device drivers.
This should enable, among other things, proper JFFS2 operation on
these devices.
config MTD_NAND_DISKONCHIP_BBTWRITE
bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
depends on MTD_NAND_DISKONCHIP
help
On DiskOnChip devices shipped with the INFTL filesystem (Millennium
and 2000 TSOP/Alon), Linux reserves some space at the end of the
device for the Bad Block Table (BBT). If you have existing INFTL
data on your device (created by non-Linux tools such as M-Systems'
DOS drivers), your data might overlap the area Linux wants to use for
the BBT. If this is a concern for you, leave this option disabled and
Linux will not write BBT data into this area.
The downside of leaving this option disabled is that if bad blocks
are detected by Linux, they will not be recorded in the BBT, which
could cause future problems.
Once you enable this option, new filesystems (INFTL or others, created
in Linux or other operating systems) will not use the reserved area.
The only reason not to enable this option is to prevent damage to
preexisting filesystems.
Even if you leave this disabled, you can enable BBT writes at module
load time (assuming you build diskonchip as a module) with the module
parameter "inftl_bbt_write=1".
endmenu
#
# linux/drivers/nand/Makefile
#
# $Id: Makefile.common,v 1.2 2003/05/28 11:38:54 dwmw2 Exp $
# $Id: Makefile.common,v 1.9 2004/07/12 16:07:31 dwmw2 Exp $
obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o
obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
nand-objs = nand_base.o nand_bbt.o
/*
* drivers/mtd/nand/au1550nd.c
*
* Copyright (C) 2004 Embedded Edge, LLC
*
* $Id: au1550nd.c,v 1.5 2004/05/17 07:19:35 ppopov 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.
*
*/
#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/au1000.h>
#ifdef CONFIG_MIPS_PB1550
#include <asm/pb1550.h>
#endif
#ifdef CONFIG_MIPS_DB1550
#include <asm/db1x00.h>
#endif
/*
* MTD structure for NAND controller
*/
static struct mtd_info *au1550_mtd = NULL;
static volatile u32 p_nand;
static int nand_width = 1; /* default, only x8 supported for now */
/* Internal buffers. Page buffer and oob buffer for one block*/
static u_char data_buf[512 + 16];
static u_char oob_buf[16 * 32];
/*
* Define partitions for flash device
*/
const static struct mtd_partition partition_info[] = {
#ifdef CONFIG_MIPS_PB1550
#define NUM_PARTITIONS 2
{
.name = "Pb1550 NAND FS 0",
.offset = 0,
.size = 8*1024*1024
},
{
.name = "Pb1550 NAND FS 1",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL
}
#endif
#ifdef CONFIG_MIPS_DB1550
#define NUM_PARTITIONS 2
{
.name = "Db1550 NAND FS 0",
.offset = 0,
.size = 8*1024*1024
},
{
.name = "Db1550 NAND FS 1",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL
}
#endif
};
static inline void write_cmd_reg(u8 cmd)
{
if (nand_width)
*((volatile u8 *)(p_nand + MEM_STNAND_CMD)) = cmd;
else
*((volatile u16 *)(p_nand + MEM_STNAND_CMD)) = cmd;
au_sync();
}
static inline void write_addr_reg(u8 addr)
{
if (nand_width)
*((volatile u8 *)(p_nand + MEM_STNAND_ADDR)) = addr;
else
*((volatile u16 *)(p_nand + MEM_STNAND_ADDR)) = addr;
au_sync();
}
static inline void write_data_reg(u8 data)
{
if (nand_width)
*((volatile u8 *)(p_nand + MEM_STNAND_DATA)) = data;
else
*((volatile u16 *)(p_nand + MEM_STNAND_DATA)) = data;
au_sync();
}
static inline u32 read_data_reg(void)
{
u32 data;
if (nand_width) {
data = *((volatile u8 *)(p_nand + MEM_STNAND_DATA));
au_sync();
}
else {
data = *((volatile u16 *)(p_nand + MEM_STNAND_DATA));
au_sync();
}
return data;
}
void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
{
}
int au1550_device_ready(struct mtd_info *mtd)
{
int ready;
ready = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
return ready;
}
static u_char au1550_nand_read_byte(struct mtd_info *mtd)
{
u_char ret;
ret = read_data_reg();
return ret;
}
static void au1550_nand_write_byte(struct mtd_info *mtd, u_char byte)
{
write_data_reg((u8)byte);
}
static void
au1550_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
for (i=0; i<len; i++)
write_data_reg(buf[i]);
}
static void
au1550_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
for (i=0; i<len; i++)
buf[i] = (u_char)read_data_reg();
}
static int
au1550_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
for (i=0; i<len; i++)
if (buf[i] != (u_char)read_data_reg())
return -EFAULT;
return 0;
}
static void au1550_nand_select_chip(struct mtd_info *mtd, int chip)
{
switch(chip) {
case -1:
/* deassert chip enable */
au_writel(au_readl(MEM_STNDCTL) & ~0x20 , MEM_STNDCTL);
break;
case 0:
/* assert (force assert) chip enable */
au_writel(au_readl(MEM_STNDCTL) | 0x20 , MEM_STNDCTL);
break;
default:
BUG();
}
}
static void au1550_nand_command (struct mtd_info *mtd, unsigned command,
int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
/*
* Write out the command to the device.
*/
if (command == NAND_CMD_SEQIN) {
int readcmd;
if (column >= mtd->oobblock) {
/* OOB area */
column -= mtd->oobblock;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
readcmd = NAND_CMD_READ0;
} else {
column -= 256;
readcmd = NAND_CMD_READ1;
}
write_cmd_reg(readcmd);
}
write_cmd_reg(command);
if (column != -1 || page_addr != -1) {
/* Serially input address */
if (column != -1)
write_addr_reg(column);
if (page_addr != -1) {
write_addr_reg((unsigned char) (page_addr & 0xff));
write_addr_reg(((page_addr >> 8) & 0xff));
/* One more address cycle for higher density devices */
if (mtd->size & 0x0c000000)
write_addr_reg((unsigned char) ((page_addr >> 16) & 0x0f));
}
}
switch (command) {
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
break;
case NAND_CMD_RESET:
if (this->dev_ready)
break;
udelay(this->chip_delay);
write_cmd_reg(NAND_CMD_STATUS);
while ( !(read_data_reg() & 0x40));
return;
/* This applies to read commands */
default:
udelay (this->chip_delay);
}
/* wait until command is processed */
while (!this->dev_ready(mtd));
}
/*
* Main initialization routine
*/
int __init au1550_init (void)
{
struct nand_chip *this;
u16 boot_swapboot = 0; /* default value */
u32 mem_time;
/* Allocate memory for MTD device structure and private data */
au1550_mtd = kmalloc (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]);
/* Initialize structures */
memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
au1550_mtd->priv = this;
/* disable interrupts */
au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
/* disable NAND boot */
au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
#ifdef CONFIG_MIPS_PB1550
/* set gpio206 high */
au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
((bcsr->status >> 6) & 0x1);
switch (boot_swapboot) {
case 0:
case 2:
case 8:
case 0xC:
case 0xD:
/* x16 NAND Flash */
nand_width = 0;
printk("Pb1550 NAND: 16-bit NAND not supported by MTD\n");
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");
kfree(au1550_mtd);
return 1;
}
/* Configure RCE1 - should be done by YAMON */
au_writel(0x5 | (nand_width << 22), MEM_STCFG1);
au_writel(NAND_TIMING, MEM_STTIME1);
mem_time = au_readl(MEM_STTIME1);
au_sync();
/* setup and enable chip select */
/* we really need to decode offsets only up till 0x20 */
au_writel((1<<28) | (NAND_PHYS_ADDR>>4) |
(((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18),
MEM_STADDR1);
au_sync();
#endif
#ifdef CONFIG_MIPS_DB1550
/* Configure RCE1 - should be done by YAMON */
au_writel(0x00400005, MEM_STCFG1);
au_writel(0x00007774, MEM_STTIME1);
au_writel(0x12000FFF, MEM_STADDR1);
#endif
p_nand = (volatile struct nand_regs *)ioremap(NAND_PHYS_ADDR, 0x1000);
/* Set address of hardware control function */
this->hwcontrol = au1550_hwcontrol;
this->dev_ready = au1550_device_ready;
/* 30 us command delay time */
this->chip_delay = 30;
this->cmdfunc = au1550_nand_command;
this->select_chip = au1550_nand_select_chip;
this->write_byte = au1550_nand_write_byte;
this->read_byte = au1550_nand_read_byte;
this->write_buf = au1550_nand_write_buf;
this->read_buf = au1550_nand_read_buf;
this->verify_buf = au1550_nand_verify_buf;
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 */
if (nand_scan (au1550_mtd, 1)) {
kfree (au1550_mtd);
return -ENXIO;
}
/* Register the partitions */
add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);
return 0;
}
module_init(au1550_init);
/*
* Clean up routine
*/
#ifdef MODULE
static void __exit au1550_cleanup (void)
{
struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
iounmap ((void *)p_nand);
/* Unregister partitions */
del_mtd_partitions(au1550_mtd);
/* Unregister the device */
del_mtd_device (au1550_mtd);
/* Free the MTD device structure */
kfree (au1550_mtd);
}
module_exit(au1550_cleanup);
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Embedded Edge, LLC");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");
......@@ -6,7 +6,7 @@
* Derived from drivers/mtd/spia.c
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
* $Id: autcpu12.c,v 1.11 2003/06/04 17:04:09 gleixner Exp $
* $Id: autcpu12.c,v 1.19 2004/07/12 15:02:15 dwmw2 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
......@@ -15,7 +15,7 @@
* Overview:
* This is a device driver for the NAND flash device found on the
* autronix autcpu12 board, which is a SmartMediaCard. It supports
* 16MB, 32MB and 64MB cards.
* 16MiB, 32MiB and 64MiB cards.
*
*
* 02-12-2002 TG Cleanup of module params
......@@ -71,42 +71,40 @@ __setup("autcpu12_pedr=",autcpu12_pedr);
/*
* Define partitions for flash devices
*/
extern struct nand_oobinfo jffs2_oobinfo;
static struct mtd_partition partition_info16k[] = {
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 8 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 8 * SZ_1M,
.size = 8 * SZ_1M },
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 8 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 8 * SZ_1M,
.size = 8 * SZ_1M },
};
static struct mtd_partition partition_info32k[] = {
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 8 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 8 * SZ_1M,
.size = 24 * SZ_1M },
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 8 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 8 * SZ_1M,
.size = 24 * SZ_1M },
};
static struct mtd_partition partition_info64k[] = {
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 16 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 16 * SZ_1M,
.size = 48 * SZ_1M },
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 16 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 16 * SZ_1M,
.size = 48 * SZ_1M },
};
static struct mtd_partition partition_info128k[] = {
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 16 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 16 * SZ_1M,
.size = 112 * SZ_1M },
{ .name = "AUTCPU12 flash partition 1",
.offset = 0,
.size = 16 * SZ_1M },
{ .name = "AUTCPU12 flash partition 2",
.offset = 16 * SZ_1M,
.size = 112 * SZ_1M },
};
#define NUM_PARTITIONS16K 2
......@@ -116,7 +114,7 @@ static struct mtd_partition partition_info128k[] = {
/*
* hardware specific access to control-lines
*/
void autcpu12_hwcontrol(int cmd)
static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
{
switch(cmd){
......@@ -135,12 +133,13 @@ void autcpu12_hwcontrol(int cmd)
/*
* read device ready pin
*/
int autcpu12_device_ready(void)
int autcpu12_device_ready(struct mtd_info *mtd)
{
return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
}
/*
* Main initialization routine
*/
......@@ -185,20 +184,18 @@ int __init autcpu12_init (void)
this->chip_delay = 20;
this->eccmode = NAND_ECC_SOFT;
/* Enable the following for a flash based bad block table */
/*
this->options = NAND_USE_FLASH_BBT;
*/
this->options = NAND_USE_FLASH_BBT;
/* Scan to find existance of the device */
if (nand_scan (autcpu12_mtd)) {
if (nand_scan (autcpu12_mtd, 1)) {
err = -ENXIO;
goto out_ior;
}
/* Allocate memory for internal data buffer */
this->data_buf = kmalloc (sizeof(u_char) * (autcpu12_mtd->oobblock + autcpu12_mtd->oobsize), GFP_KERNEL);
if (!this->data_buf) {
printk ("Unable to allocate NAND data buffer for AUTCPU12.\n");
err = -ENOMEM;
goto out_ior;
}
/* Register the partitions */
switch(autcpu12_mtd->size){
case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
......@@ -208,13 +205,11 @@ int __init autcpu12_init (void)
default: {
printk ("Unsupported SmartMedia device\n");
err = -ENXIO;
goto out_buf;
goto out_ior;
}
}
goto out;
out_buf:
kfree (this->data_buf);
out_ior:
iounmap((void *)autcpu12_fio_base);
out_mtd:
......@@ -231,20 +226,12 @@ module_init(autcpu12_init);
#ifdef MODULE
static void __exit autcpu12_cleanup (void)
{
struct nand_chip *this = (struct nand_chip *) &autcpu12_mtd[1];
/* Unregister partitions */
del_mtd_partitions(autcpu12_mtd);
/* Unregister the device */
del_mtd_device (autcpu12_mtd);
/* Free internal data buffers */
kfree (this->data_buf);
/* Release resources, unregister device */
nand_release (autcpu12_mtd);
/* unmap physical adress */
iounmap((void *)autcpu12_fio_base);
/* Free the MTD device structure */
kfree (autcpu12_mtd);
}
......
This diff is collapsed.
......@@ -6,7 +6,7 @@
* Derived from drivers/mtd/nand/autcpu12.c
* Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
*
* $Id: edb7312.c,v 1.5 2003/04/20 07:24:40 gleixner Exp $
* $Id: edb7312.c,v 1.8 2004/07/12 15:03:26 dwmw2 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
......@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
......@@ -83,7 +84,7 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*/
static void ep7312_hwcontrol(int cmd)
static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
{
switch(cmd) {
......@@ -113,10 +114,13 @@ static void ep7312_hwcontrol(int cmd)
/*
* read device ready pin
*/
static int ep7312_device_ready(void)
static int ep7312_device_ready(struct mtd_info *mtd)
{
return 1;
}
#ifdef CONFIG_MTD_PARTITIONS
const char *part_probes[] = { "cmdlinepart", NULL };
#endif
/*
* Main initialization routine
......@@ -171,7 +175,7 @@ static int __init ep7312_init (void)
this->chip_delay = 15;
/* Scan to find existence of the device */
if (nand_scan (ep7312_mtd)) {
if (nand_scan (ep7312_mtd, 1)) {
iounmap((void *)ep7312_fio_base);
kfree (ep7312_mtd);
return -ENXIO;
......@@ -186,16 +190,16 @@ static int __init ep7312_init (void)
return -ENOMEM;
}
#ifdef CONFIG_MTD_CMDLINE_PARTS
mtd_parts_nb = parse_cmdline_partitions(ep7312_mtd, &mtd_parts,
"edb7312-nand");
#ifdef CONFIG_PARTITIONS
ep7312_mtd->name = "edb7312-nand";
mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
&mtd_parts, 0);
if (mtd_parts_nb > 0)
part_type = "command line";
part_type = "command line";
else
mtd_parts_nb = 0;
mtd_parts_nb = 0;
#endif
if (mtd_parts_nb == 0)
{
if (mtd_parts_nb == 0) {
mtd_parts = partition_info;
mtd_parts_nb = NUM_PARTITIONS;
part_type = "static";
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* drivers/mtd/nand_ecc.c
* This file contains an ECC algorithm from Toshiba that detects and
* corrects 1 bit errors in a 256 byte block of data.
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* Toshiba America Electronics Components, Inc.
* drivers/mtd/nand/nand_ecc.c
*
* $Id: nand_ecc.c,v 1.9 2003/02/20 13:34:19 sjhill Exp $
* Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
* Toshiba America Electronics Components, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
* $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $
*
* This file contains an ECC algorithm from Toshiba that detects and
* corrects 1 bit errors in a 256 byte block of data.
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 or (at your option) any
* later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this file; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or use
* macros or inline functions from these files, or you compile these
* files and link them with other works to produce a work based on these
* files, these files do not by themselves cause the resulting work to be
* covered by the GNU General Public License. However the source code for
* these files must still be made available in accordance with section (3)
* of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work based on
* this file might be covered by the GNU General Public License.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/nand_ecc.h>
/*
* Pre-calculated 256-way 1 byte column parity
......@@ -41,7 +63,12 @@ static const u_char nand_ecc_precalc_table[] = {
};
/*
/**
* nand_trans_result - [GENERIC] create non-inverted ECC
* @reg2: line parity reg 2
* @reg3: line parity reg 3
* @ecc_code: ecc
*
* Creates non-inverted ECC code from line parity
*/
static void nand_trans_result(u_char reg2, u_char reg3,
......@@ -81,10 +108,13 @@ static void nand_trans_result(u_char reg2, u_char reg3,
ecc_code[1] = tmp2;
}
/*
* Calculate 3 byte ECC code for 256 byte block
/**
* nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
* @mtd: MTD block structure
* @dat: raw data
* @ecc_code: buffer for ECC
*/
void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
{
u_char idx, reg1, reg2, reg3;
int j;
......@@ -114,12 +144,19 @@ void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
ecc_code[0] = ~ecc_code[0];
ecc_code[1] = ~ecc_code[1];
ecc_code[2] = ((~reg1) << 2) | 0x03;
return 0;
}
/*
/**
* nand_correct_data - [NAND Interface] Detect and correct bit error(s)
* @mtd: MTD block structure
* @dat: raw data read from the chip
* @read_ecc: ECC from the chip
* @calc_ecc: the ECC calculated from raw data
*
* Detect and correct a 1 bit error for 256 byte block
*/
int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
{
u_char a, b, c, d1, d2, d3, add, bit, i;
......
......@@ -2,9 +2,8 @@
* drivers/mtd/nandids.c
*
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
*
*
* $Id: nand_ids.c,v 1.4 2003/05/21 15:15:08 dwmw2 Exp $
*
* $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 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
......@@ -13,26 +12,99 @@
*/
#include <linux/module.h>
#include <linux/mtd/nand.h>
/*
* Chip ID list
*
* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
* options
*
* Pagesize; 0, 256, 512
* 0 get this information from the extended chip ID
+ 256 256 Byte page size
* 512 512 Byte page size
*/
struct nand_flash_dev nand_flash_ids[] = {
{"NAND 1MiB 5V", 0x6e, 20, 0x1000, 1},
{"NAND 2MiB 5V", 0x64, 21, 0x1000, 1},
{"NAND 4MiB 5V", 0x6b, 22, 0x2000, 0},
{"NAND 1MiB 3,3V", 0xe8, 20, 0x1000, 1},
{"NAND 1MiB 3,3V", 0xec, 20, 0x1000, 1},
{"NAND 2MiB 3,3V", 0xea, 21, 0x1000, 1},
{"NAND 4MiB 3,3V", 0xd5, 22, 0x2000, 0},
{"NAND 4MiB 3,3V", 0xe3, 22, 0x2000, 0},
{"NAND 4MiB 3,3V", 0xe5, 22, 0x2000, 0},
{"NAND 8MiB 3,3V", 0xd6, 23, 0x2000, 0},
{"NAND 8MiB 3,3V", 0xe6, 23, 0x2000, 0},
{"NAND 16MiB 3,3V", 0x73, 24, 0x4000, 0},
{"NAND 32MiB 3,3V", 0x75, 25, 0x4000, 0},
{"NAND 64MiB 3,3V", 0x76, 26, 0x4000, 0},
{"NAND 128MiB 3,3V", 0x79, 27, 0x4000, 0},
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
{"NAND 512MiB 3,3V 8-bit", 0xDC, 512, 512, 0x4000, 0},
/* These are the new chips with large page size. The pagesize
* and the erasesize is determined from the extended id bytes
*/
/* 1 Gigabit */
{"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 2 Gigabit */
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 4 Gigabit */
{"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 8 Gigabit */
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 16 Gigabit */
{"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
* The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
* 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
* Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
* There are more speed improvements for reads and writes possible, but not implemented now
*/
{"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
{NULL,}
};
......@@ -44,10 +116,11 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_SAMSUNG, "Samsung"},
{NAND_MFR_FUJITSU, "Fujitsu"},
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"},
{0x0, "Unknown"}
};
EXPORT_SYMBOL (nand_manuf_ids);
EXPORT_SYMBOL (nand_flash_ids);
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
* to controllines (due to change in nand.c)
* page_cache added
*
* $Id: spia.c,v 1.19 2003/04/20 07:24:40 gleixner Exp $
* $Id: spia.c,v 1.21 2003/07/11 15:12:29 dwmw2 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
......@@ -20,6 +20,8 @@
* a 64Mibit (8MiB x 8 bits) NAND flash device.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
......@@ -35,14 +37,14 @@ static struct mtd_info *spia_mtd = NULL;
/*
* Values specific to the SPIA board (used with EP7212 processor)
*/
#define SPIA_IO_ADDR = 0xd0000000 /* Start of EP7212 IO address space */
#define SPIA_FIO_ADDR = 0xf0000000 /* Address where flash is mapped */
#define SPIA_PEDR = 0x0080 /*
#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
#define SPIA_PEDR 0x0080 /*
* IO offset to Port E data register
* where the CLE, ALE and NCE pins
* are wired to.
*/
#define SPIA_PEDDR = 0x00c0 /*
#define SPIA_PEDDR 0x00c0 /*
* IO offset to Port E data direction
* register so we can control the IO
* lines.
......@@ -62,11 +64,6 @@ MODULE_PARM(spia_fio_base, "i");
MODULE_PARM(spia_pedr, "i");
MODULE_PARM(spia_peddr, "i");
__setup("spia_io_base=",spia_io_base);
__setup("spia_fio_base=",spia_fio_base);
__setup("spia_pedr=",spia_pedr);
__setup("spia_peddr=",spia_peddr);
/*
* Define partitions for flash device
*/
......@@ -88,7 +85,7 @@ const static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
*/
void spia_hwcontrol(int cmd){
static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
switch(cmd){
......@@ -143,7 +140,7 @@ int __init spia_init (void)
this->chip_delay = 15;
/* Scan to find existence of the device */
if (nand_scan (spia_mtd)) {
if (nand_scan (spia_mtd, 1)) {
kfree (spia_mtd);
return -ENXIO;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,7 @@
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
* $Id: nand_ecc.h,v 1.2 2003/02/20 13:34:20 sjhill Exp $
* $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown 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
......@@ -12,17 +12,19 @@
* This file is the header for the ECC algorithm.
*/
/*
* Creates non-inverted ECC code from line parity
*/
void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code);
#ifndef __MTD_NAND_ECC_H__
#define __MTD_NAND_ECC_H__
struct mtd_info;
/*
* Calculate 3 byte ECC code for 256 byte block
*/
void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
/*
* Detect and correct a 1 bit error for 256 byte block
*/
int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
#endif /* __MTD_NAND_ECC_H__ */
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