NAND Flash Hardware configuration?

David Woodhouse dwmw2 at
Thu Sep 20 03:38:27 EDT 2001

On Thu, 20 Sep 2001, Kim, Sanghun wrote:

> M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.

You don't need a DiskOnChip driver. The DiskOnChip uses NAND flash, but 
has other magic too. There's a separate driver for standalone NAND flash 

> Linux how to know what GPIO maped to "ALE,CLE,CE"???

Yes, you're right - you'll have to write a small piece of code to teach 
Linux how to drive the control lines.

drivers/mtd/nand/nand.c is a generic driver for NAND flash chips. It needs
to be coupled with a board-specific module, as you noticed. So far, I
believe that it's only been used with the 'spia' driver, which you can use
as an example for your own code.

Before invoking the generic NAND driver, the board-specific module 
fills in the 'nand_chip' data structure with the virtual address of 
the data port, the virtual address of the GPIO register containing the 
control lines, and the three bits in that register which are connected to 
each of the CLE, ALE and CE pins:

        /* Set address of NAND IO lines */
        this->IO_ADDR = spia_fio_base;
        this->CTRL_ADDR = spia_io_base + spia_pedr;
        this->CLE = 0x01;
        this->ALE = 0x02;
        this->NCE = 0x04;

Currently the CTRL_ADDR is treated as an 8-bit wide register. The generic 
NAND code will do things like

	*(volatile unsigned char *)this->CTRL_ADDR |= this->CLE;

	*(volatile unsigned char *)this->CTRL_ADDR &= ~this->CLE;

This can be a little suboptimal because it means there's no locking, and
it's not very flexible - if you need a 32-bit wide register, if your
output pins are inverted, or if your three control lines are actually
spread across more than one register it can't express that.

We may need to rethink the abstraction between the generic NAND driver and 
the board-specific code. I wonder how much performance would be affected 
if we made it an out-of-line function call?

BTW, Steve: nand_deselect() has a superfluous '~', afaict. 

#define nand_select()   NAND_CTRL &= ~this->NCE; \
                        nand_command(mtd, NAND_CMD_RESET, -1, -1); \
                        udelay (10);
#define nand_deselect() NAND_CTRL |= ~this->NCE;


More information about the linux-mtd mailing list