Subject: Re: RFC: Flash memory device API
To: None <tech-kern@netbsd.org>
From: Bucky Katz <bucky@picovex.com>
List: tech-kern
Date: 09/04/2006 23:44:22
"Jared D. McNeill" <jmcneill@invisible.ca> writes:

Your timing is fortunate. I've just started working on a NAND driver
for an arm part and am inventing the same wheel, but for NAND, with no
clear understanding of how to cope with raw NOR.

> Externally, flash(4) exposes the following ioctl operations:
> 	FLASH_ERASEBLOCK: erase a single block
> 	FLASH_GBLOCKSTATUS: get the status of a single block
> 	FLASH_SBLOCKSTATUS: set the status of a single block
> 	FLASH_GETINFO: query flash device capabilities

Not sure what you mean by "status".  I *assume* that by BLOCK you mean
the erasable unit of the flash.  I've seen several naming schemes used
so it would be good to specific what label you're going to use for the
readable unit and what label for the erasable.  readable = sector,
erasable = block is fine.

For NAND I would add two more:

 	FLASH_READSPARE:  read the spare area
 	FLASH_WRITESPARE: write the spare area

>
> Flash device capabilities is defined by flash_info_t, which provides:
> 	enum flash_type fi_type;		/* NOR or NAND */
> 	block_id_t fi_nblocks;
> 	size_t fi_bytesperblock;
> 	size_t fi_sectorsperblock;
> 	size_t fi_sectorsize;

NAND requires also

 	size_t fi_bytesperspareblock;

For NAND it would be useful to have the vendor id bits as well. I
think it would be useful to have an ioctl

 	FLASH_GETCAPABILITIES: read the capabilities of the device.

>
> Internally, a hardware flash device driver must implement the
> following callbacks:
> 	init(void *)
> 	deinit(void *)
> 	get_info(void *, flash_info_t *)
> 	erase_block(void *, block_id_t)
> 	get_block_status(void *, block_id_t)
> 	set_block_status(void *, block_id_t, int)
> 	read_sector(void *, int, uint8_t *, sector_info_t *, int)
> 	write_sector(void *, int, uint8_t *, sector_info_t *, int)
> 	ioctl(void *, u_long, caddr_t, int, struct lwp *)	<-- optional

NAND requires also

 	read_spare(void *, int, uint8_t *, sector_info_t *, int)
 	write_spare(void *, int, uint8_t *, sector_info_t *, int)

>
> After filling in the structure of function callbacks, the hardware
> driver must call flash_attach_mi.
>
> Additionally, a userland utility is provided as flashctl(8) that
> allows you to query device info, erase blocks, and get or set block
> status.

For NAND there is also the issue of reading the spare section.

Which brings up the whole issue of flash ecc.  I've found in the past
that a userland utility should be able to give you some visibility
into that as well.

Another fairly significant way in which NAND differs from NOR is that
raw NOR parts usually allow execute-in-place, but NAND doesn't.

>
> Source code is available here for review:
>   http://www.invisible.ca/~jmcneill/netbsd/flash-20060904.tar

Thanks. I'll look at it tomorrow.