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
parent CYGPKG_IO_FLASH_NAND
active_if CYGPKG_IO_FLASH_NAND
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:
io/flash_nand/
+ common/
+ controller/
+ chip/
devs/flash/bfin/
+ nfc/
+ ez_kit_bf548/nand/
(+ ez_kit_bf548/nor/ for the NOR flash also on this board)
devs/flash/st-micro/nand0xG/
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_page_read()
cyg_nand_block_erase()
cyg_nand_bad_block_...()
cyg_nand_chip_select(nand, chip_number)
cyg_nand_init()
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*.
Rutger
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss