mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
[MTD] Refactor NAND hwcontrol to cmd_ctrl
The hwcontrol function enforced a step by step state machine for any kind of hardware chip access. Let the hardware driver know which control bits are set and inform it about a change of the control lines. Let the hardware driver write out the command and address bytes directly. This gives a peformance advantage for address bus controlled chips and simplifies the quirks in the hardware drivers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
3821720d51
commit
7abd3ef987
18 changed files with 419 additions and 532 deletions
|
@ -34,13 +34,6 @@ static struct mtd_info *ams_delta_mtd = NULL;
|
|||
|
||||
#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
|
||||
|
||||
#define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0)
|
||||
#define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE)
|
||||
#define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0)
|
||||
#define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE)
|
||||
#define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0)
|
||||
#define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE)
|
||||
|
||||
/*
|
||||
* Define partitions for flash devices
|
||||
*/
|
||||
|
@ -66,25 +59,6 @@ static struct mtd_partition partition_info[] = {
|
|||
.size = 3 * SZ_256K },
|
||||
};
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
|
||||
static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
|
||||
case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
|
||||
|
||||
case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
|
||||
case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
|
||||
|
||||
case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
|
||||
case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
@ -141,6 +115,32 @@ static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command control function
|
||||
*
|
||||
* ctrl:
|
||||
* NAND_NCE: bit 0 -> bit 2
|
||||
* NAND_CLE: bit 1 -> bit 7
|
||||
* NAND_ALE: bit 2 -> bit 6
|
||||
*/
|
||||
static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned long bits;
|
||||
|
||||
bits = (~ctrl & NAND_NCE) << 2;
|
||||
bits |= (ctrl & NAND_CLE) << 7;
|
||||
bits |= (ctrl & NAND_ALE) << 6;
|
||||
|
||||
ams_delta_latch2_write(0xC2, bits);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
ams_delta_write_byte(mtd, cmd);
|
||||
}
|
||||
|
||||
static int ams_delta_nand_ready(struct mtd_info *mtd)
|
||||
{
|
||||
return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
|
||||
|
@ -183,7 +183,7 @@ static int __init ams_delta_init(void)
|
|||
this->write_buf = ams_delta_write_buf;
|
||||
this->read_buf = ams_delta_read_buf;
|
||||
this->verify_buf = ams_delta_verify_buf;
|
||||
this->hwcontrol = ams_delta_hwcontrol;
|
||||
this->cmd_ctrl = ams_delta_hwcontrol;
|
||||
if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
|
||||
this->dev_ready = ams_delta_nand_ready;
|
||||
} else {
|
||||
|
@ -200,7 +200,7 @@ static int __init ams_delta_init(void)
|
|||
AMS_DELTA_LATCH2_NAND_NCE |
|
||||
AMS_DELTA_LATCH2_NAND_NWP);
|
||||
|
||||
/* Scan to find existance of the device */
|
||||
/* Scan to find existance of the device */
|
||||
if (nand_scan(ams_delta_mtd, 1)) {
|
||||
err = -ENXIO;
|
||||
goto out_mtd;
|
||||
|
|
|
@ -269,6 +269,18 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Select the chip by setting nCE to low */
|
||||
#define NAND_CTL_SETNCE 1
|
||||
/* Deselect the chip by setting nCE to high */
|
||||
#define NAND_CTL_CLRNCE 2
|
||||
/* Select the command latch by setting CLE to high */
|
||||
#define NAND_CTL_SETCLE 3
|
||||
/* Deselect the command latch by setting CLE to low */
|
||||
#define NAND_CTL_CLRCLE 4
|
||||
/* Select the address latch by setting ALE to high */
|
||||
#define NAND_CTL_SETALE 5
|
||||
/* Deselect the address latch by setting ALE to low */
|
||||
#define NAND_CTL_CLRALE 6
|
||||
|
||||
static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
|
@ -349,7 +361,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
|||
ulong flags;
|
||||
|
||||
/* Begin command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
/*
|
||||
* Write out the command to the device.
|
||||
*/
|
||||
|
@ -372,10 +384,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
|||
this->write_byte(mtd, command);
|
||||
|
||||
/* Set ALE and clear CLE to start address cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
|
||||
if (column != -1 || page_addr != -1) {
|
||||
this->hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
|
@ -400,7 +412,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
|||
*/
|
||||
ce_override = 1;
|
||||
local_irq_save(flags);
|
||||
this->hwcontrol(mtd, NAND_CTL_SETNCE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
|
||||
}
|
||||
|
||||
this->write_byte(mtd, (u8)(page_addr >> 8));
|
||||
|
@ -410,7 +422,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
|||
this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
|
||||
}
|
||||
/* Latch in address */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -443,7 +455,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
|
|||
udelay(1);
|
||||
|
||||
/* Release -CE and re-enable interrupts. */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRNCE);
|
||||
au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
|
@ -571,7 +583,6 @@ static int __init au1xxx_nand_init(void)
|
|||
nand_width = au_readl(MEM_STCFG3) & (1 << 22);
|
||||
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = au1550_hwcontrol;
|
||||
this->dev_ready = au1550_device_ready;
|
||||
this->select_chip = au1550_select_chip;
|
||||
this->cmdfunc = au1550_command;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
|
||||
*
|
||||
* 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.23 2005/11/07 11:14:30 gleixner Exp $
|
||||
*
|
||||
|
@ -42,11 +42,6 @@
|
|||
* MTD structure for AUTCPU12 board
|
||||
*/
|
||||
static struct mtd_info *autcpu12_mtd = NULL;
|
||||
|
||||
static int autcpu12_io_base = CS89712_VIRT_BASE;
|
||||
static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
|
||||
static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
|
||||
static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
|
||||
static void __iomem *autcpu12_fio_base;
|
||||
|
||||
/*
|
||||
|
@ -94,31 +89,42 @@ static struct mtd_partition partition_info128k[] = {
|
|||
#define NUM_PARTITIONS128K 2
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
|
||||
static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
*
|
||||
* ALE bit 4 autcpu12_pedr
|
||||
* CLE bit 5 autcpu12_pedr
|
||||
* NCE bit 0 fio_ctrl
|
||||
*
|
||||
*/
|
||||
static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
switch (cmd) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break;
|
||||
case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
void __iomem *addr
|
||||
unsigned char bits;
|
||||
|
||||
case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_ALE; break;
|
||||
case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break;
|
||||
addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
|
||||
bits = (ctrl & NAND_CLE) << 4;
|
||||
bits |= (ctrl & NAND_ALE) << 2;
|
||||
writeb((readb(addr) & ~0x30) | bits, addr);
|
||||
|
||||
case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break;
|
||||
case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break;
|
||||
addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
|
||||
writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/*
|
||||
* read device ready pin
|
||||
*/
|
||||
* read device ready pin
|
||||
*/
|
||||
int autcpu12_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
|
||||
|
||||
return ((*(volatile unsigned char *)(autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
|
||||
|
||||
return readb(addr) & AUTCPU12_SMC_RDY;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -130,7 +136,8 @@ static int __init autcpu12_init(void)
|
|||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
if (!autcpu12_mtd) {
|
||||
printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
|
@ -138,7 +145,7 @@ static int __init autcpu12_init(void)
|
|||
}
|
||||
|
||||
/* map physical adress */
|
||||
autcpu12_fio_base = ioremap(autcpu12_fio_pbase, SZ_1K);
|
||||
autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
|
||||
if (!autcpu12_fio_base) {
|
||||
printk("Ioremap autcpu12 SmartMedia Card failed\n");
|
||||
err = -EIO;
|
||||
|
@ -159,7 +166,7 @@ static int __init autcpu12_init(void)
|
|||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = autcpu12_fio_base;
|
||||
this->IO_ADDR_W = autcpu12_fio_base;
|
||||
this->hwcontrol = autcpu12_hwcontrol;
|
||||
this->cmd_ctrl = autcpu12_hwcontrol;
|
||||
this->dev_ready = autcpu12_device_ready;
|
||||
/* 20 us command delay time */
|
||||
this->chip_delay = 20;
|
||||
|
@ -179,10 +186,22 @@ static int __init autcpu12_init(void)
|
|||
|
||||
/* Register the partitions */
|
||||
switch (autcpu12_mtd->size) {
|
||||
case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
|
||||
case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break;
|
||||
case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
|
||||
case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
|
||||
case SZ_16M:
|
||||
add_mtd_partitions(autcpu12_mtd, partition_info16k,
|
||||
NUM_PARTITIONS16K);
|
||||
break;
|
||||
case SZ_32M:
|
||||
add_mtd_partitions(autcpu12_mtd, partition_info32k,
|
||||
NUM_PARTITIONS32K);
|
||||
break;
|
||||
case SZ_64M:
|
||||
add_mtd_partitions(autcpu12_mtd, partition_info64k,
|
||||
NUM_PARTITIONS64K);
|
||||
break;
|
||||
case SZ_128M:
|
||||
add_mtd_partitions(autcpu12_mtd, partition_info128k,
|
||||
NUM_PARTITIONS128K);
|
||||
break;
|
||||
default:
|
||||
printk("Unsupported SmartMedia device\n");
|
||||
err = -ENXIO;
|
||||
|
@ -191,7 +210,7 @@ static int __init autcpu12_init(void)
|
|||
goto out;
|
||||
|
||||
out_ior:
|
||||
iounmap((void *)autcpu12_fio_base);
|
||||
iounmap(autcpu12_fio_base);
|
||||
out_mtd:
|
||||
kfree(autcpu12_mtd);
|
||||
out:
|
||||
|
@ -209,7 +228,7 @@ static void __exit autcpu12_cleanup(void)
|
|||
nand_release(autcpu12_mtd);
|
||||
|
||||
/* unmap physical adress */
|
||||
iounmap((void *)autcpu12_fio_base);
|
||||
iounmap(autcpu12_fio_base);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree(autcpu12_mtd);
|
||||
|
|
|
@ -131,33 +131,17 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
writeb(byte, this->IO_ADDR_W + 0x801);
|
||||
}
|
||||
|
||||
static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
unsigned char ctl;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
ctl = CS_NAND_CTL_CLE;
|
||||
break;
|
||||
|
||||
case NAND_CTL_CLRCLE:
|
||||
case NAND_CTL_CLRALE:
|
||||
case NAND_CTL_SETNCE:
|
||||
ctl = 0;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
ctl = CS_NAND_CTL_ALE;
|
||||
break;
|
||||
|
||||
default:
|
||||
case NAND_CTL_CLRNCE:
|
||||
ctl = CS_NAND_CTL_CE;
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
|
||||
writeb(ctl, mmio_base + MM_NAND_CTL);
|
||||
}
|
||||
writeb(ctl, mmio_base + MM_NAND_CTL);
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
cs553x_write_byte(mtd, cmd);
|
||||
}
|
||||
|
||||
static int cs553x_device_ready(struct mtd_info *mtd)
|
||||
|
@ -233,7 +217,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
|||
goto out_mtd;
|
||||
}
|
||||
|
||||
this->hwcontrol = cs553x_hwcontrol;
|
||||
this->cmd_ctrl = cs553x_hwcontrol;
|
||||
this->dev_ready = cs553x_device_ready;
|
||||
this->read_byte = cs553x_read_byte;
|
||||
this->write_byte = cs553x_write_byte;
|
||||
|
|
|
@ -95,7 +95,8 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
|
|||
#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
|
||||
#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
|
||||
|
||||
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
|
||||
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int bitmask);
|
||||
static void doc200x_select_chip(struct mtd_info *mtd, int chip);
|
||||
|
||||
static int debug = 0;
|
||||
|
@ -402,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
|
|||
uint16_t ret;
|
||||
|
||||
doc200x_select_chip(mtd, nr);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
this->write_byte(mtd, NAND_CMD_READID);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
this->write_byte(mtd, 0);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_READID,
|
||||
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
|
||||
doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
/* We cant' use dev_ready here, but at least we wait for the
|
||||
* command to complete
|
||||
|
@ -425,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
|
|||
} ident;
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
doc2000_write_byte(mtd, NAND_CMD_READID);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
doc2000_write_byte(mtd, 0);
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_READID,
|
||||
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
|
||||
doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_NONE,
|
||||
NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
udelay(50);
|
||||
|
||||
|
@ -690,54 +688,37 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
|
|||
chip -= (floor * doc->chips_per_floor);
|
||||
|
||||
/* 11.4.4 -- deassert CE before changing chip */
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
|
||||
|
||||
WriteDOC(floor, docptr, FloorSelect);
|
||||
WriteDOC(chip, docptr, CDSNDeviceSelect);
|
||||
|
||||
doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
|
||||
doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
doc->curchip = chip;
|
||||
doc->curfloor = floor;
|
||||
}
|
||||
|
||||
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
|
||||
|
||||
static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct doc_priv *doc = this->priv;
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETNCE:
|
||||
doc->CDSNControl |= CDSN_CTRL_CE;
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
doc->CDSNControl &= ~CDSN_CTRL_CE;
|
||||
break;
|
||||
case NAND_CTL_SETCLE:
|
||||
doc->CDSNControl |= CDSN_CTRL_CLE;
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
doc->CDSNControl &= ~CDSN_CTRL_CLE;
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
doc->CDSNControl |= CDSN_CTRL_ALE;
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
doc->CDSNControl &= ~CDSN_CTRL_ALE;
|
||||
break;
|
||||
case NAND_CTL_SETWP:
|
||||
doc->CDSNControl |= CDSN_CTRL_WP;
|
||||
break;
|
||||
case NAND_CTL_CLRWP:
|
||||
doc->CDSNControl &= ~CDSN_CTRL_WP;
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
doc->CDSNControl &= ~CDSN_CTRL_MSK;
|
||||
doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
|
||||
if (debug)
|
||||
printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
|
||||
WriteDOC(doc->CDSNControl, docptr, CDSNControl);
|
||||
/* 11.4.3 -- 4 NOPs after CSDNControl write */
|
||||
DoC_Delay(doc, 4);
|
||||
}
|
||||
if (debug)
|
||||
printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
|
||||
WriteDOC(doc->CDSNControl, docptr, CDSNControl);
|
||||
/* 11.4.3 -- 4 NOPs after CSDNControl write */
|
||||
DoC_Delay(doc, 4);
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
this->write_byte(mtd, cmd);
|
||||
}
|
||||
|
||||
static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
|
||||
|
@ -1510,7 +1491,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
|
|||
this->read_buf = doc2001plus_readbuf;
|
||||
this->verify_buf = doc2001plus_verifybuf;
|
||||
this->scan_bbt = inftl_scan_bbt;
|
||||
this->hwcontrol = NULL;
|
||||
this->cmd_ctrl = NULL;
|
||||
this->select_chip = doc2001plus_select_chip;
|
||||
this->cmdfunc = doc2001plus_command;
|
||||
this->ecc.hwctl = doc2001plus_enable_hwecc;
|
||||
|
@ -1670,7 +1651,7 @@ static int __init doc_probe(unsigned long physadr)
|
|||
|
||||
nand->priv = doc;
|
||||
nand->select_chip = doc200x_select_chip;
|
||||
nand->hwcontrol = doc200x_hwcontrol;
|
||||
nand->cmd_ctrl = doc200x_hwcontrol;
|
||||
nand->dev_ready = doc200x_dev_ready;
|
||||
nand->waitfunc = doc200x_wait;
|
||||
nand->block_bad = doc200x_block_bad;
|
||||
|
|
|
@ -73,32 +73,26 @@ static struct mtd_partition partition_info[] = {
|
|||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*
|
||||
* NAND_NCE: bit 0 -> bit 7
|
||||
* NAND_CLE: bit 1 -> bit 4
|
||||
* NAND_ALE: bit 2 -> bit 5
|
||||
*/
|
||||
static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
switch (cmd) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr);
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char bits;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr);
|
||||
break;
|
||||
bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
|
||||
bits = (ctrl & NAND_NCE) << 7;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr);
|
||||
break;
|
||||
clps_writeb((clps_readb(ep7312_pxdr) & 0xB0) | 0x10,
|
||||
ep7312_pxdr);
|
||||
}
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -159,7 +153,7 @@ static int __init ep7312_init(void)
|
|||
/* insert callbacks */
|
||||
this->IO_ADDR_R = ep7312_fio_base;
|
||||
this->IO_ADDR_W = ep7312_fio_base;
|
||||
this->hwcontrol = ep7312_hwcontrol;
|
||||
this->cmd_ctrl = ep7312_hwcontrol;
|
||||
this->dev_ready = ep7312_device_ready;
|
||||
/* 15 us command delay time */
|
||||
this->chip_delay = 15;
|
||||
|
|
|
@ -56,36 +56,18 @@ static struct mtd_partition partition_info[] = {
|
|||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*
|
||||
* NAND_NCE: bit 0 - don't care
|
||||
* NAND_CLE: bit 1 - address bit 2
|
||||
* NAND_ALE: bit 2 - address bit 3
|
||||
*/
|
||||
static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *)(mtd->priv);
|
||||
struct nand_chip *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;
|
||||
}
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -145,7 +127,7 @@ static int __init h1910_init(void)
|
|||
/* insert callbacks */
|
||||
this->IO_ADDR_R = nandaddr;
|
||||
this->IO_ADDR_W = nandaddr;
|
||||
this->hwcontrol = h1910_hwcontrol;
|
||||
this->cmd_ctrl = 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;
|
||||
|
|
|
@ -276,10 +276,10 @@ static void nand_select_chip(struct mtd_info *mtd, int chip)
|
|||
struct nand_chip *this = mtd->priv;
|
||||
switch (chip) {
|
||||
case -1:
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRNCE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
|
||||
break;
|
||||
case 0:
|
||||
this->hwcontrol(mtd, NAND_CTL_SETNCE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -548,13 +548,12 @@ static void nand_wait_ready(struct mtd_info *mtd)
|
|||
* Send command to NAND device. This function is used for small page
|
||||
* devices (256/512 Bytes per page)
|
||||
*/
|
||||
static void nand_command(struct mtd_info *mtd, unsigned command, int column,
|
||||
int page_addr)
|
||||
static void nand_command(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
register struct nand_chip *this = mtd->priv;
|
||||
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
||||
|
||||
/* Begin command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
/*
|
||||
* Write out the command to the device.
|
||||
*/
|
||||
|
@ -572,33 +571,32 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
|
|||
column -= 256;
|
||||
readcmd = NAND_CMD_READ1;
|
||||
}
|
||||
this->write_byte(mtd, readcmd);
|
||||
this->cmd_ctrl(mtd, readcmd, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
}
|
||||
this->write_byte(mtd, command);
|
||||
this->cmd_ctrl(mtd, command, ctrl);
|
||||
|
||||
/* Set ALE and clear CLE to start address cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
|
||||
if (column != -1 || page_addr != -1) {
|
||||
this->hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
/* Adjust columns for 16 bit buswidth */
|
||||
if (this->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
this->write_byte(mtd, column);
|
||||
}
|
||||
if (page_addr != -1) {
|
||||
this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
|
||||
this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
|
||||
/* One more address cycle for devices > 32MiB */
|
||||
if (this->chipsize > (32 << 20))
|
||||
this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f));
|
||||
}
|
||||
/* Latch in address */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
/*
|
||||
* Address cycle, when necessary
|
||||
*/
|
||||
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
/* Adjust columns for 16 bit buswidth */
|
||||
if (this->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
this->cmd_ctrl(mtd, column, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
}
|
||||
if (page_addr != -1) {
|
||||
this->cmd_ctrl(mtd, page_addr, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
|
||||
/* One more address cycle for devices > 32MiB */
|
||||
if (this->chipsize > (32 << 20))
|
||||
this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
|
||||
}
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
/*
|
||||
* program and erase have their own busy handlers
|
||||
|
@ -611,15 +609,16 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
|
|||
case NAND_CMD_ERASE2:
|
||||
case NAND_CMD_SEQIN:
|
||||
case NAND_CMD_STATUS:
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
|
||||
return;
|
||||
|
||||
case NAND_CMD_RESET:
|
||||
if (this->dev_ready)
|
||||
break;
|
||||
udelay(this->chip_delay);
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
this->write_byte(mtd, NAND_CMD_STATUS);
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_STATUS,
|
||||
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
|
||||
while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
|
||||
return;
|
||||
|
||||
|
@ -648,12 +647,13 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
|
|||
* @column: the column address for this command, -1 if none
|
||||
* @page_addr: the page address for this command, -1 if none
|
||||
*
|
||||
* Send command to NAND device. This is the version for the new large page devices
|
||||
* We dont have the separate regions as we have in the small page devices.
|
||||
* We must emulate NAND_CMD_READOOB to keep the code compatible.
|
||||
* Send command to NAND device. This is the version for the new large page
|
||||
* devices We dont have the separate regions as we have in the small page
|
||||
* devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
|
||||
*
|
||||
*/
|
||||
static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
|
||||
static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
||||
int column, int page_addr)
|
||||
{
|
||||
register struct nand_chip *this = mtd->priv;
|
||||
|
||||
|
@ -663,34 +663,33 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
|
|||
command = NAND_CMD_READ0;
|
||||
}
|
||||
|
||||
/* Begin command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
/* Write out the command to the device. */
|
||||
this->write_byte(mtd, (command & 0xff));
|
||||
/* End command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
/* Command latch cycle */
|
||||
this->cmd_ctrl(mtd, command & 0xff,
|
||||
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
|
||||
|
||||
if (column != -1 || page_addr != -1) {
|
||||
this->hwcontrol(mtd, NAND_CTL_SETALE);
|
||||
int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
|
||||
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
/* Adjust columns for 16 bit buswidth */
|
||||
if (this->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
this->write_byte(mtd, column & 0xff);
|
||||
this->write_byte(mtd, column >> 8);
|
||||
this->cmd_ctrl(mtd, column, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
this->cmd_ctrl(mtd, column >> 8, ctrl);
|
||||
}
|
||||
if (page_addr != -1) {
|
||||
this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
|
||||
this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
|
||||
this->cmd_ctrl(mtd, page_addr, ctrl);
|
||||
this->cmd_ctrl(mtd, page_addr >> 8,
|
||||
NAND_NCE | NAND_ALE);
|
||||
/* One more address cycle for devices > 128MiB */
|
||||
if (this->chipsize > (128 << 20))
|
||||
this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff));
|
||||
this->cmd_ctrl(mtd, page_addr >> 16,
|
||||
NAND_NCE | NAND_ALE);
|
||||
}
|
||||
/* Latch in address */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRALE);
|
||||
}
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
/*
|
||||
* program and erase have their own busy handlers
|
||||
|
@ -722,20 +721,14 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
|
|||
if (this->dev_ready)
|
||||
break;
|
||||
udelay(this->chip_delay);
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
this->write_byte(mtd, NAND_CMD_STATUS);
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
|
||||
while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
|
||||
return;
|
||||
|
||||
case NAND_CMD_READ0:
|
||||
/* Begin command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_SETCLE);
|
||||
/* Write out the start read command */
|
||||
this->write_byte(mtd, NAND_CMD_READSTART);
|
||||
/* End command latch cycle */
|
||||
this->hwcontrol(mtd, NAND_CTL_CLRCLE);
|
||||
/* Fall through into ready check */
|
||||
this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
|
||||
|
||||
/* This applies to read commands */
|
||||
default:
|
||||
|
|
|
@ -1071,68 +1071,6 @@ switch_state(struct nandsim *ns)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ns_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
/* set CLE line high */
|
||||
case NAND_CTL_SETCLE:
|
||||
NS_DBG("ns_hwcontrol: start command latch cycles\n");
|
||||
ns->lines.cle = 1;
|
||||
break;
|
||||
|
||||
/* set CLE line low */
|
||||
case NAND_CTL_CLRCLE:
|
||||
NS_DBG("ns_hwcontrol: stop command latch cycles\n");
|
||||
ns->lines.cle = 0;
|
||||
break;
|
||||
|
||||
/* set ALE line high */
|
||||
case NAND_CTL_SETALE:
|
||||
NS_DBG("ns_hwcontrol: start address latch cycles\n");
|
||||
ns->lines.ale = 1;
|
||||
break;
|
||||
|
||||
/* set ALE line low */
|
||||
case NAND_CTL_CLRALE:
|
||||
NS_DBG("ns_hwcontrol: stop address latch cycles\n");
|
||||
ns->lines.ale = 0;
|
||||
break;
|
||||
|
||||
/* set WP line high */
|
||||
case NAND_CTL_SETWP:
|
||||
NS_DBG("ns_hwcontrol: enable write protection\n");
|
||||
ns->lines.wp = 1;
|
||||
break;
|
||||
|
||||
/* set WP line low */
|
||||
case NAND_CTL_CLRWP:
|
||||
NS_DBG("ns_hwcontrol: disable write protection\n");
|
||||
ns->lines.wp = 0;
|
||||
break;
|
||||
|
||||
/* set CE line low */
|
||||
case NAND_CTL_SETNCE:
|
||||
NS_DBG("ns_hwcontrol: enable chip\n");
|
||||
ns->lines.ce = 1;
|
||||
break;
|
||||
|
||||
/* set CE line high */
|
||||
case NAND_CTL_CLRNCE:
|
||||
NS_DBG("ns_hwcontrol: disable chip\n");
|
||||
ns->lines.ce = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERR("hwcontrol: unknown command\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static u_char
|
||||
ns_nand_read_byte(struct mtd_info *mtd)
|
||||
{
|
||||
|
@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
|||
return;
|
||||
}
|
||||
|
||||
static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
|
||||
{
|
||||
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
|
||||
|
||||
ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
|
||||
ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
|
||||
ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
ns_nand_write_byte(mtd, cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
ns_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
|
@ -1514,7 +1464,7 @@ static int __init ns_init_module(void)
|
|||
/*
|
||||
* Register simulator's callbacks.
|
||||
*/
|
||||
chip->hwcontrol = ns_hwcontrol;
|
||||
chip->cmd_ctrl = ns_hwcontrol;
|
||||
chip->read_byte = ns_nand_read_byte;
|
||||
chip->dev_ready = ns_device_ready;
|
||||
chip->write_byte = ns_nand_write_byte;
|
||||
|
|
|
@ -60,22 +60,17 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
|
|||
writel(ccr, ndfc->ndfcbase + NDFC_CCR);
|
||||
}
|
||||
|
||||
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct ndfc_controller *ndfc = &ndfc_ctrl;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_CMD;
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_ALE;
|
||||
break;
|
||||
default:
|
||||
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
|
||||
break;
|
||||
}
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
if (ctrl & NAND_CLE)
|
||||
writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD);
|
||||
else
|
||||
writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE);
|
||||
}
|
||||
|
||||
static int ndfc_ready(struct mtd_info *mtd)
|
||||
|
@ -158,7 +153,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
|
|||
|
||||
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
|
||||
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
|
||||
chip->hwcontrol = ndfc_hwcontrol;
|
||||
chip->cmd_ctrl = ndfc_hwcontrol;
|
||||
chip->dev_ready = ndfc_ready;
|
||||
chip->select_chip = ndfc_select_chip;
|
||||
chip->chip_delay = 50;
|
||||
|
|
|
@ -108,54 +108,68 @@ extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio
|
|||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
|
||||
static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
switch (cmd) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
#error Missing headerfiles. No way to fix this. -tglx
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
|
||||
static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
switch (cmd) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
#error Missing headerfiles. No way to fix this. -tglx
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
#ifdef USE_READY_BUSY_PIN
|
||||
|
@ -251,7 +265,7 @@ static int __init ppchameleonevb_init(void)
|
|||
/* insert callbacks */
|
||||
this->IO_ADDR_R = ppchameleon_fio_base;
|
||||
this->IO_ADDR_W = ppchameleon_fio_base;
|
||||
this->hwcontrol = ppchameleon_hwcontrol;
|
||||
this->cmd_ctrl = ppchameleon_hwcontrol;
|
||||
#ifdef USE_READY_BUSY_PIN
|
||||
this->dev_ready = ppchameleon_device_ready;
|
||||
#endif
|
||||
|
@ -351,7 +365,7 @@ static int __init ppchameleonevb_init(void)
|
|||
/* insert callbacks */
|
||||
this->IO_ADDR_R = ppchameleonevb_fio_base;
|
||||
this->IO_ADDR_W = ppchameleonevb_fio_base;
|
||||
this->hwcontrol = ppchameleonevb_hwcontrol;
|
||||
this->cmd_ctrl = ppchameleonevb_hwcontrol;
|
||||
#ifdef USE_READY_BUSY_PIN
|
||||
this->dev_ready = ppchameleonevb_device_ready;
|
||||
#endif
|
||||
|
|
|
@ -208,32 +208,18 @@ static uint8_t revbits[256] = {
|
|||
* Address lines (A24-A22), so no action is required here.
|
||||
*
|
||||
*/
|
||||
static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *)(mtd->priv);
|
||||
struct nand_chip *chip = (mtd->priv);
|
||||
|
||||
switch (cmd) {
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
break;
|
||||
|
||||
}
|
||||
if (ctrl & NAND_CLE)
|
||||
writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
|
||||
else
|
||||
writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -559,7 +545,7 @@ static int __init rtc_from4_init(void)
|
|||
this->IO_ADDR_R = rtc_from4_fio_base;
|
||||
this->IO_ADDR_W = rtc_from4_fio_base;
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = rtc_from4_hwcontrol;
|
||||
this->cmd_ctrl = rtc_from4_hwcontrol;
|
||||
/* Set address of chip select function */
|
||||
this->select_chip = rtc_from4_nand_select_chip;
|
||||
/* command delay time (in us) */
|
||||
|
|
|
@ -256,60 +256,36 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
|
|||
*
|
||||
*/
|
||||
|
||||
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigend int ctrl)
|
||||
{
|
||||
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETNCE:
|
||||
case NAND_CTL_CLRNCE:
|
||||
printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
|
||||
break;
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;
|
||||
break;
|
||||
|
||||
/* NAND_CTL_CLRCLE: */
|
||||
/* NAND_CTL_CLRALE: */
|
||||
default:
|
||||
chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
|
||||
break;
|
||||
}
|
||||
if (cmd & NAND_CLE)
|
||||
writeb(cmd, info->regs + S3C2410_NFCMD);
|
||||
else
|
||||
writeb(cmd, info->regs + S3C2410_NFADDR);
|
||||
}
|
||||
|
||||
/* command and control functions */
|
||||
|
||||
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigend int ctrl)
|
||||
{
|
||||
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETNCE:
|
||||
case NAND_CTL_CLRNCE:
|
||||
printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
|
||||
break;
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;
|
||||
break;
|
||||
|
||||
/* NAND_CTL_CLRCLE: */
|
||||
/* NAND_CTL_CLRALE: */
|
||||
default:
|
||||
chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
|
||||
break;
|
||||
}
|
||||
if (cmd & NAND_CLE)
|
||||
writeb(cmd, info->regs + S3C2440_NFCMD);
|
||||
else
|
||||
writeb(cmd, info->regs + S3C2440_NFADDR);
|
||||
}
|
||||
|
||||
/* s3c2410_nand_devready()
|
||||
|
@ -498,7 +474,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
|
|||
|
||||
chip->IO_ADDR_R = info->regs + S3C2410_NFDATA;
|
||||
chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
|
||||
chip->hwcontrol = s3c2410_nand_hwcontrol;
|
||||
chip->cmd_ctrl = s3c2410_nand_hwcontrol;
|
||||
chip->dev_ready = s3c2410_nand_devready;
|
||||
chip->write_buf = s3c2410_nand_write_buf;
|
||||
chip->read_buf = s3c2410_nand_read_buf;
|
||||
|
@ -511,7 +487,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
|
|||
if (info->is_s3c2440) {
|
||||
chip->IO_ADDR_R = info->regs + S3C2440_NFDATA;
|
||||
chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
|
||||
chip->hwcontrol = s3c2440_nand_hwcontrol;
|
||||
chip->cmd_ctrl = s3c2440_nand_hwcontrol;
|
||||
}
|
||||
|
||||
nmtd->info = info;
|
||||
|
|
|
@ -77,31 +77,26 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = {
|
|||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
* ctrl:
|
||||
* NAND_CNE: bit 0 -> bit 0 & 4
|
||||
* NAND_CLE: bit 1 -> bit 1
|
||||
* NAND_ALE: bit 2 -> bit 2
|
||||
*
|
||||
*/
|
||||
static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
writeb(readb(FLASHCTL) | FLCLE, FLASHCTL);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL);
|
||||
break;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned char bits = ctrl & 0x07;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
writeb(readb(FLASHCTL) & ~(FLCE0 | FLCE1), FLASHCTL);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
writeb(readb(FLASHCTL) | (FLCE0 | FLCE1), FLASHCTL);
|
||||
break;
|
||||
bits |= (ctrl & 0x01) << 4;
|
||||
writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||
|
@ -196,7 +191,7 @@ static int __init sharpsl_nand_init(void)
|
|||
this->IO_ADDR_R = FLASHIO;
|
||||
this->IO_ADDR_W = FLASHIO;
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = sharpsl_nand_hwcontrol;
|
||||
this->cmd_ctrl = sharpsl_nand_hwcontrol;
|
||||
this->dev_ready = sharpsl_nand_dev_ready;
|
||||
/* 15 us command delay time */
|
||||
this->chip_delay = 15;
|
||||
|
|
|
@ -82,20 +82,27 @@ static const struct mtd_partition partition_info[] = {
|
|||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
*
|
||||
* ctrl:
|
||||
* NAND_CNE: bit 0 -> bit 2
|
||||
* NAND_CLE: bit 1 -> bit 0
|
||||
* NAND_ALE: bit 2 -> bit 1
|
||||
*/
|
||||
static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break;
|
||||
case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
void __iomem *addr = spia_io_base + spia_pedr;
|
||||
unsigned char bits;
|
||||
|
||||
case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x02; break;
|
||||
case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break;
|
||||
|
||||
case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
|
||||
case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break;
|
||||
bits = (ctrl & NAND_CNE) << 2;
|
||||
bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
|
||||
writeb((readb(addr) & ~0x7) | bits, addr);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -133,7 +140,7 @@ static int __init spia_init(void)
|
|||
this->IO_ADDR_R = (void __iomem *)spia_fio_base;
|
||||
this->IO_ADDR_W = (void __iomem *)spia_fio_base;
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = spia_hwcontrol;
|
||||
this->cmd_ctrl = spia_hwcontrol;
|
||||
/* 15 us command delay time */
|
||||
this->chip_delay = 15;
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <asm/arch-omap1510/hardware.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
|
||||
#define CONFIG_NAND_WORKAROUND 1
|
||||
|
||||
/*
|
||||
* MTD structure for TOTO board
|
||||
*/
|
||||
|
@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL;
|
|||
|
||||
static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
|
||||
|
||||
#define CONFIG_NAND_WORKAROUND 1
|
||||
|
||||
#define NAND_NCE 0x4000
|
||||
#define NAND_CLE 0x1000
|
||||
#define NAND_ALE 0x0002
|
||||
#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
|
||||
|
||||
#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
|
||||
#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
|
||||
#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
|
||||
#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
|
||||
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
|
||||
#else
|
||||
#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0)
|
||||
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE)
|
||||
#endif
|
||||
#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0)
|
||||
#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE)
|
||||
|
||||
/*
|
||||
* Define partitions for flash devices
|
||||
*/
|
||||
|
@ -91,25 +74,43 @@ static struct mtd_partition partition_info32M[] = {
|
|||
|
||||
#define NUM_PARTITIONS32M 3
|
||||
#define NUM_PARTITIONS64M 4
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
|
||||
static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
*
|
||||
* ctrl:
|
||||
* NAND_NCE: bit 0 -> bit 14 (0x4000)
|
||||
* NAND_CLE: bit 1 -> bit 12 (0x1000)
|
||||
* NAND_ALE: bit 2 -> bit 1 (0x0002)
|
||||
*/
|
||||
static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
udelay(1); /* hopefully enough time for tc make proceding write to clear */
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
|
||||
case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned long bits;
|
||||
|
||||
case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
|
||||
case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
|
||||
/* hopefully enough time for tc make proceding write to clear */
|
||||
udelay(1);
|
||||
|
||||
case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
|
||||
case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
|
||||
bits = (~ctrl & NAND_NCE) << 14;
|
||||
bits |= (ctrl & NAND_CLE) << 12;
|
||||
bits |= (ctrl & NAND_ALE) >> 1;
|
||||
|
||||
#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
|
||||
gpiosetout(0x5002, bits);
|
||||
|
||||
#ifdef CONFIG_NAND_WORKAROUND
|
||||
/* "some" dev boards busted, blue wired to rts2 :( */
|
||||
rts2setout(2, (ctrl & NAND_CLE) << 1);
|
||||
#endif
|
||||
/* allow time to ensure gpio state to over take memory write */
|
||||
udelay(1);
|
||||
}
|
||||
udelay(1); /* allow time to ensure gpio state to over take memory write */
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -142,7 +143,7 @@ static int __init toto_init(void)
|
|||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = toto_io_base;
|
||||
this->IO_ADDR_W = toto_io_base;
|
||||
this->hwcontrol = toto_hwcontrol;
|
||||
this->cmd_ctrl = toto_hwcontrol;
|
||||
this->dev_ready = NULL;
|
||||
/* 25 us command delay time */
|
||||
this->chip_delay = 30;
|
||||
|
|
|
@ -83,31 +83,29 @@ static struct mtd_partition partition_info128[] = {
|
|||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*
|
||||
* ctrl:
|
||||
* NAND_NCE: bit 0 -> bit 2
|
||||
* NAND_CLE: bit 1 -> bit 1
|
||||
* NAND_ALE: bit 2 -> bit 0
|
||||
*/
|
||||
static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
__raw_writeb(__raw_readb(ctrl) | 0x2, ctrl);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
__raw_writeb(__raw_readb(ctrl) & ~0x2, ctrl);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
__raw_writeb(__raw_readb(ctrl) | 0x1, ctrl);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
__raw_writeb(__raw_readb(ctrl) & ~0x1, ctrl);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
__raw_writeb(__raw_readb(ctrl) | 0x4, ctrl);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
__raw_writeb(__raw_readb(ctrl) & ~0x4, ctrl);
|
||||
break;
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
|
||||
unsigned char bits;
|
||||
|
||||
bits = (ctrl & NAND_CNE) << 2;
|
||||
bits |= ctrl & NAND_CLE;
|
||||
bits |= (ctrl & NAND_ALE) >> 2;
|
||||
|
||||
__raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -152,7 +150,7 @@ static int __init ts7250_init(void)
|
|||
/* insert callbacks */
|
||||
this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
|
||||
this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
|
||||
this->hwcontrol = ts7250_hwcontrol;
|
||||
this->cmd_ctrl = ts7250_hwcontrol;
|
||||
this->dev_ready = ts7250_device_ready;
|
||||
this->chip_delay = 15;
|
||||
this->ecc.mode = NAND_ECC_SOFT;
|
||||
|
|
|
@ -50,23 +50,20 @@ extern int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
|
||||
/*
|
||||
* Constants for hardware specific CLE/ALE/NCE function
|
||||
*/
|
||||
*
|
||||
* These are bits which can be or'ed to set/clear multiple
|
||||
* bits in one go.
|
||||
*/
|
||||
/* Select the chip by setting nCE to low */
|
||||
#define NAND_CTL_SETNCE 1
|
||||
/* Deselect the chip by setting nCE to high */
|
||||
#define NAND_CTL_CLRNCE 2
|
||||
#define NAND_NCE 0x01
|
||||
/* Select the command latch by setting CLE to high */
|
||||
#define NAND_CTL_SETCLE 3
|
||||
/* Deselect the command latch by setting CLE to low */
|
||||
#define NAND_CTL_CLRCLE 4
|
||||
#define NAND_CLE 0x02
|
||||
/* Select the address latch by setting ALE to high */
|
||||
#define NAND_CTL_SETALE 5
|
||||
/* Deselect the address latch by setting ALE to low */
|
||||
#define NAND_CTL_CLRALE 6
|
||||
/* Set write protection by setting WP to high. Not used! */
|
||||
#define NAND_CTL_SETWP 7
|
||||
/* Clear write protection by setting WP to low. Not used! */
|
||||
#define NAND_CTL_CLRWP 8
|
||||
#define NAND_ALE 0x04
|
||||
|
||||
#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
|
||||
#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
|
||||
#define NAND_CTRL_CHANGE 0x80
|
||||
|
||||
/*
|
||||
* Standard NAND flash commands
|
||||
|
@ -106,6 +103,8 @@ extern int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
#define NAND_CMD_STATUS_RESET 0x7f
|
||||
#define NAND_CMD_STATUS_CLEAR 0xff
|
||||
|
||||
#define NAND_CMD_NONE -1
|
||||
|
||||
/* Status bits */
|
||||
#define NAND_STATUS_FAIL 0x01
|
||||
#define NAND_STATUS_FAIL_N1 0x02
|
||||
|
@ -263,7 +262,8 @@ struct nand_ecc_ctrl {
|
|||
* @select_chip: [REPLACEABLE] select chip nr
|
||||
* @block_bad: [REPLACEABLE] check, if the block is bad
|
||||
* @block_markbad: [REPLACEABLE] mark the block bad
|
||||
* @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
|
||||
* @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling
|
||||
* ALE/CLE/nCE. Also used to write command and address
|
||||
* @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
|
||||
* If set to NULL no access to ready/busy is available and the ready/busy information
|
||||
* is read from the chip status register
|
||||
|
@ -317,7 +317,8 @@ struct nand_chip {
|
|||
void (*select_chip)(struct mtd_info *mtd, int chip);
|
||||
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
|
||||
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
|
||||
void (*hwcontrol)(struct mtd_info *mtd, int cmd);
|
||||
void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
|
||||
unsigned int ctrl);
|
||||
int (*dev_ready)(struct mtd_info *mtd);
|
||||
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
|
||||
int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
|
||||
|
|
Loading…
Reference in a new issue