This is the mail archive of the mailing list for the eCos project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

NAND flash driver considerations: RFC

I am writing a NAND flash driver for eCos. I would like to get reactions and advice on some issues, so I can correct now while I am still coding (and my guess is, this won't be the last time).

NAND internal interfaces ------------------------

NAND flash is actually two devices: the flash chip(s), and the controller, often a separate part, sometimes integrated into a CPU (as with my BlackFin BF54x).
The chips seem to have a fairly uniform interface, as canonicalized by ONFI ( All chips have lines for 'chip enable', 'select command', 'select address', 'r/w', 'data bus (x8 or x16)', 'status', which are handled in a standard way.
Consequently, any controller has a very good chance of being able to speak to any chip, in hardware terms.
Moreover, the command set is mostly (a subset of) ONFI.
Deviations from the ONFI standard seem to be centered in the command that interrogates the chip about its properties. #LUNs, #blocks/LUN, #pages/block, data/page, spare size, bus width (x8 or x16), support for optional commands, and timing characteristics can typically be obtained either in ONFI speak (the 'READ PARAMETER BLOCK' command) or with a manufacturer-specific command.

The NAND flash controllers vary in their CPU interface. They may have registers that reflect the basic capabilities of the chip interface ('command', 'address', 'data', 'status'). Or they may solve that differently, in some serial way or whatever.

+++ My proposal:

= define a NAND controller /interface/ that specifies functions for the chip capabilities ('command', 'address', 'data', 'status'); any NAND controller /implementation/ must define them.
(See below: on top of that NAND controller interface, generic NAND code provides the functions specified by ONFI to read/program (partial) pages incl. spare erea, erase blocks, etc.)

= as far as the chip is concerned: most of the parameters are found through chip interrogation, only very few parameters remain to be specified in a .cdl or a chip .h file: bus width?, maybe some timings; the src for the chip must contain any routines that deviate from ONFI, where the device interrogation routine may be an obvious candidate. (If a chip doesn't support this kind of interrogation, or if it must be overridden, well, it must go into the chip .cdl after all.)

eCos directory structure ------------------------

Should NAND be grouped under flash in packages/io and packages/devs? To be honest, the interface under which NAND flash is approached only vaguely resembles that for NOR flash. When we would choose for flash/nand, then we should also have to have flash/nor/ and move all things currently flashing down there.

+++ My proposal:

have packages/io/nand/ and packages/devs/nand/* *beside* packages/flash/ and packages/devs/flash/*. They are very different. Also, who wants refactoring of flash/* into flash/nor/*.
Is there a case to be made for separate nand/controller/ and nand/chip/ trees?

NAND eCos device type ----------------

NAND flash is neither a character device (CHAR_DEVTAB_ENTRY), nor a block device (BLOCK_DEVTAB_ENTRY), nor a net device (NET_DEVTAB_ENTRY), nor a flash device in the sense of the eCos device driver structure.
- must be erased in 'blocks'
- must be programmed/read in (partial) pages (there usually is a good number of pages per block)
- has a 'spare' area for each page (to store ECCs, bad block info, and client, e.g. file system info); spare is to be handled explicitly
- has single-bit failures, corrected by ECCs
- has bad blocks
- and may have a copy-back function to relocate data within the flash chip.
NAND controllers may calculate ECCs in hardware on the fly.

So, should we copy/paste one of those many device driver infrastructures and modify them to accomodate the NAND flash devices?
eCos NOR flash has solved this in its own way: it does device lookup based on the addresses that the NOR flash is memory-mapped to. But NAND flash is *not* memory-mapped. Besides, NAND flashes can/will exceed 4GB in size, so they cannot be addressed with 32bits.

+++ My proposal:

= I would rather create NAND devices as just DEVTAB_ENTRYs, and mark them as NAND (or OTHER or ...) i.s.o. CHAR/BLOCK type. The function dispatch block ptr can be cast, or it can be put in the private area. This way one can do device lookup in the normal way with cyg_io_lookup() ("/dev/nand0" resolves to a device handle).

= I propose to create two separate device types: NAND controllers and NAND chips. The two device types might be designated as "/dev/nand0" for controller 0, and "/dev/nand0.2" for the third chip connected to controller 0.

I agree that this is kind of broken. But I have trouble thinking of a way to do device lookup otherwise. Besides, we might consider generalization of the device structure in the sense that the functions block is no longer strictly typed. Its actual type might be derived from the device driver type field.

External interface of NAND devices (controller on top of chip) --------------------------------------------------------------

+++ My proposal:
the ONFI functions exported by the generic NAND controller code are sufficient.

These are:
- lookup/init; a controller must initialize any chips it owns, locating them e.g. by their names ("/dev/nand0" owns "/dev/nand0.0" .. "/dev/nand0.X")
- programming of a (partial) page incl spare
- reading of a (partial) page incl spare, optionally exporting the controller's calculated ECC
- erase of a block
- marking block as bad
- querying block badness
- retrieving initial bad block table

To be extended later:
- reading/programming of multiple pages ?within a block
- copyback
- interleaved support

The spare area will usually have fields for ECC values, either calculated by the layer above, or by a controller that supports it.

So, at the NAND flash layer, there is no attempt to hide bad blocks, spare areas, ECC handling. The layer above (file system, 'contiguous' programmer) must handle that.

This exactly fits the YAFFS2 interface (sorry, no idea about JFFS2, but I'd hope so).

I don't know yet how 'contiguous' programming should work. Typical application: the boot loader code. For NAND flash booting, typically a first-level bootstrap is read from block 0 (guaranteed to be 'good'). This contains code to copy the rest of the bootloader code from NAND flash to RAM, while taking in consideration any bad blocks. Hmmm... would there be any interest in this? As for me, I am currently just interested in getting YAFFS2 alive.

Well, I hope that this is understandable, and sorry that it is so much.

Looking forward to your comments,

Rutger Hofman
VU Amsterdam

Before posting, please read the FAQ:
and search the list archive:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]