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]

Re: Re: NAND flash driver considerations: RFC

Andrew Lunn wrote:
I don't see there being any problem mixing up NOR and NAND drivers in
packages/dev/flash/ The CDL rules will prevent somebody from trying to

There are many different ways at looking at the packages. The CDL language imposes a hierarchy as well which has nothing to do with the directory hierarchy. We could have packages/io/flash_nand/current for the common code. This is not unknown. Eg we have packages/net/tcpip and packages/net/bsd_tcpip. The first one is no longer supported and the second one is what everybody uses.

I don't really see that mixing up the packages is obfuscating them. We
already have two different classes of flash drivers in
packages/dev/flash. We have chip drivers and we have target board
drivers. When the flash_v2 branch gets merged in we will have another
two classes added.

What is important here is the CDL. The new packages need to have


so that they are correctly placed into the CDL tree and only active
when appropriate.

OK, I refactored my test setup to reflect what you suggest. So now we have packages:

  + common/
  + controller/
  + chip/

  + nfc/
  + ez_kit_bf548/nand/
 (+ ez_kit_bf548/nor/ for the NOR flash also on this board)


and I refactored the .cdl's, the #defines, the includes etc etc. The .cdl-s have the parentage you suggested.

Is this OK?

The code for the *basic* API is something like this.

Example: program (within) one page:

cyg_nand_page_program(cyg_nand_t *nand,
                      const void *data, size_t len,
                      size_t col, size_t row,
                      const void *spare, size_t spare_len)

must implement the ONFI command sequence for page program. So, it is essentially implemented as follows:

   nand->cmd(nand, 0x80);
   nand->addr(nand, col, row);
   nand->program_data(nand, data, len);
   nand->goto_addr(nand, spare_offset, row);
   nand->program_data(nand, spare, spare_len);
   nand->cmd(nand, 0x10);
   nand->await_status(nand, 6);

where the indirect calls are implemented by the specific controller.

A minimal set of other calls would be:
   cyg_nand_chip_select(nand, chip_number)

Given this API, what does the device filenames /dev/nand0/1 have to do with anything. How do i get from a file descriptor returned with open() to a cyg_nand_t * nand structure?

That is not the idea. There must be a NAND filesystem that is layered on top of flash_nand devices. That file system has an open() implementation (like yaffs_open()).

> Do file descriptors and /dev/
files make any sense? The NOR devices don't do this?

NOR flash is memory-mapped, it uses the memory mapping to locate
devices. NAND flash is not memory-mapped, so I had to come up with some
other mechanism to locate devices. The target cdl must tell the devices their names, and the implementation must locate the driver data structures from that.

My proposal was to use cyg_io_lookup() to locate the controller and chip devices by name. Well, as I wrote in my RFC, this is obviously broken because NAND controller and chip devices must not be accessed through the file system. But we still need a mechanism to look them up and then tie them together.

Then, the File System must retrieve its NAND controller (+ associated chip(s)) from the name it is passed at cdl or mount time. I thought cyg_io_lookup() can be used again to get the nand_t pointer. (Or ad lib replace NAND controller here with "Abstract NAND Device".)

Would you care to suggest a better scheme for lookup for chip, controller, FS? Or would you already be satisfied if the names are not like /dev/nand0 but like '#nand0' or whatever non-filesystem-capable string?

of pages. What if we want to hide the fact that there are pages/blocks/luns/chips? Then we must address the bytes in this abstract NAND, but 32bit addresses will be insufficient.

Not necessarily bytes, but by blocks. We could define a block as being 512 bytes, and use a u32 to indicate which block to access. That would allow access to i think 2TB. For an embedded system that is quite a lot. Is 512 sensible? I have no idea.

Blocks are the unit of erase. Pages are the unit of read/program (with ECC in the page's spare area). Blocks usually consist of a good number of pages (think 64). Pages can be 256, 512, 1K, 2K, 4K bytes (with larger to come, I'd guess).

Even at the chip level, NAND allows addressing of individual x8 or x16 words (bytes or shorts). This saves on IO between CPU and NAND peripherals -- it allows random access (within a page). I wouldn't suggest to throw that faculty away. So, my proposal is to have two 32-bit indices, column (= x8/x16 word within page) and row = page+block+lun. This resembles the ONFI chip specification, where addressing is done in tuples too (some integral number of bytes for the column, some integral number of bytes for the row). It also makes evident that some things are different with NAND flash; e.g. it is impossible to program/read more than 1 page at a time (although there is an interface to do pipelining and interleaving (which I have skipped) of pages).

Brainstorm: it might be possible to generalize my previous suggestion of 'uniform chips', and let the Abstract Nand Device export one contiguous NAND 'chip'; it must translate between the abstract blocks and pages and the blocks and pages of individual chips. The block size (unit of erase) of the Abstract Chip must be the maximum of the block size of the chips. The page size (unit of ECC) must be handled carefully to translate ECC addresses within the spare area to match potentially different page sizes.

YAFFS is interesting, but from a licensing point of view, it is
bad. It is pure GPL. We can never include it into the eCos tree.  We
should also be looking at support for JFFS2, which we can and do
import into eCos. People who are using Redboot as a Linux bootloader
will want the NAND implementation to the compatible with what linux
does so that they can boot there Linux kernel out of a NAND filesystem
with JFFS2. Taking this further, UBI and UBIFS is of interest for the
Linux world, however it has the same licensing problems as YAFFS.

YAFFS is also Linuxware. It has been in the kernel for a long time. I understand that the licensing of incorporating YAFFS into their RedBoot may bite (i.e. cost) people. Just for curiosity: does anyone know what a commercial license of YAFFS would cost?

JFFS2 uses mtd. Should we then make a thin mtd portability layer on top of cyg_nand? Or should we hack JFFS2 to speak native cyg_nand (and again loose JFFS2 compatibility)? I seem to read that JFFS2 has been frozen, and JFFS3 is now UBI/UBIFS.

If we make a thin mtd portability layer on top of cyg_nand, I have to read up on mtd, or at least those parts of mtd that are actually used by JFFS2. I skimmed through mtd when I started this. mtd's interface is *huge*.


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]