Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 27788
b: refs/heads/master
c: 35af68b
h: refs/heads/master
v: v3
  • Loading branch information
Sergei Shtylyov authored and David Woodhouse committed May 16, 2006
1 parent 7de2126 commit dd57b58
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b020bb7d3b3a8e3568a16eaf98c033bb9ee474eb
refs/heads/master: 35af68b53a62c98bf551aaae7be179bde248eb34
139 changes: 139 additions & 0 deletions trunk/drivers/mtd/nand/au1550nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
Expand Down Expand Up @@ -318,6 +319,141 @@ int au1550_device_ready(struct mtd_info *mtd)
return ret;
}

/**
* au1550_select_chip - control -CE line
* Forbid driving -CE manually permitting the NAND controller to do this.
* Keeping -CE asserted during the whole sector reads interferes with the
* NOR flash and PCMCIA drivers as it causes contention on the static bus.
* We only have to hold -CE low for the NAND read commands since the flash
* chip needs it to be asserted during chip not ready time but the NAND
* controller keeps it released.
*
* @mtd: MTD device structure
* @chip: chipnumber to select, -1 for deselect
*/
static void au1550_select_chip(struct mtd_info *mtd, int chip)
{
}

/**
* au1550_command - Send command to NAND device
* @mtd: MTD device structure
* @command: the command to be sent
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*/
static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
int ce_override = 0, i;
ulong flags;

/* Begin command latch cycle */
this->hwcontrol(mtd, NAND_CTL_SETCLE);
/*
* 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;
}
this->write_byte(mtd, readcmd);
}
this->write_byte(mtd, command);

/* 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, (u8)(page_addr & 0xff));

if (command == NAND_CMD_READ0 ||
command == NAND_CMD_READ1 ||
command == NAND_CMD_READOOB) {
/*
* NAND controller will release -CE after
* the last address byte is written, so we'll
* have to forcibly assert it. No interrupts
* are allowed while we do this as we don't
* want the NOR flash or PCMCIA drivers to
* steal our precious bytes of data...
*/
ce_override = 1;
local_irq_save(flags);
this->hwcontrol(mtd, NAND_CTL_SETNCE);
}

this->write_byte(mtd, (u8)(page_addr >> 8));

/* One more address cycle for devices > 32MiB */
if (this->chipsize > (32 << 20))
this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
}
/* Latch in address */
this->hwcontrol(mtd, NAND_CTL_CLRALE);
}

/*
* Program and erase have their own busy handlers.
* Status and sequential in need no delay.
*/
switch (command) {

case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
return;

case NAND_CMD_RESET:
break;

case NAND_CMD_READ0:
case NAND_CMD_READ1:
case NAND_CMD_READOOB:
/* Check if we're really driving -CE low (just in case) */
if (unlikely(!ce_override))
break;

/* Apply a short delay always to ensure that we do wait tWB. */
ndelay(100);
/* Wait for a chip to become ready... */
for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
udelay(1);

/* Release -CE and re-enable interrupts. */
this->hwcontrol(mtd, NAND_CTL_CLRNCE);
local_irq_restore(flags);
return;
}
/* Apply this short delay always to ensure that we do wait tWB. */
ndelay(100);

while(!this->dev_ready(mtd));
}


/*
* Main initialization routine
*/
Expand Down Expand Up @@ -437,6 +573,9 @@ static int __init au1xxx_nand_init(void)
/* 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;

/* 30 us command delay time */
this->chip_delay = 30;
this->eccmode = NAND_ECC_SOFT;
Expand Down

0 comments on commit dd57b58

Please sign in to comment.