Chapter 58. Samsung K9 family NAND chips

58.1. Overview

The CYGPKG_DEVS_NAND_SAMSUNG_K9 driver package currently provides support for the Samsung K9F1G08, K9F2G08 and K9F1208 series of NAND flash chips, and is intended to be expanded to provide support for more of the K9 family.

Most users will not need to interact with this package; it should be included as a hardware dependency on all appropriate targets. This package provides only an inline code fragment which is intended to be instantiated by the target platform HAL and provided with appropriate board-specific low-level functions allowing it to access the hardware.

[Note]Notes
  1. The large-page parts in this family are not quite ONFI-compliant, but this code could probably be extended to a much wider set of chips - or indeed to the ONFI specification - without too much trouble. Appropriate definitions will be required for the chip identifier, decoding of the Read ID response, and the chip's blockcount-bits and device-size fields.
  2. At the present time, this driver has the limitation that it only supports 8-bit parts. This is an area of probable future expansion.

58.2. Using this driver in a board port

This driver's top-level chip support is currently provided as two files:

cyg/devs/nand/k9_generic.h

Prototypes the low-level chip access functions required by the chip driver and declares a private struct for use by the driver.

cyg/devs/nand/k9_generic.inl

Implements high-level chip functions and exposes them via the CYG_NAND_FUNS macro. This file is not intended to be compiled on its own, but to be included by the source file in a platform HAL which implements the low-level functions.

A platform HAL would typically make use of this driver in a single source file with the following steps:

  • Declare a local private struct with contents as appropriate,
  • #include <cyg/devs/nand/k9_generic.h>
  • implement the required low-level functions,
  • #include <cyg/devs/nand/k9_generic.inl>
  • declare a list of the supported k9_subtype which may appear on the board, terminated by K9_SUBTYPE_SENTINEL
  • declare a static instance of the k9_priv struct containing pointers to that list and to an instance of the local-private struct
  • finally, instantiate the chip with the CYG_NAND_DEVICE macro, selecting the ECC and OOB semantics to use.

    [Note]Note

    If there is more than one chip on the board, each needs its own CYG_NAND_DEVICE with a distinct name and device name, its own instance of the k9_priv struct.

For more details about the infrastructure provided by the NAND layer and the semantics it expects of the chip driver, refer to Chapter 53, eCos NAND Flash Library. An example driver instantiation can be found in the NAND driver for the EA LPC2468 platform.

58.2.1. Memory usage

As discussed in Section 55.2, “High-level (chip) functions”, the chip initialisation function must set up the bbt.data pointer in the cyg_nand_device struct. This driver does so by including a large byte array in the k9_priv struct whose size is controlled by CDL depending on the enabled chip support. That struct is intended to be allocated as a static struct in the data or BSS segment (one per chip), which avoids adding a dependency on malloc.

58.2.2. Low-level functions required from the platform HAL

These functions are prototyped in k9_generic.h. They have no return value ("void"), except for read_data_1 which returns the byte it has read.

write_cmd(device, command)

Writes a single command byte to the chip's command latch.

write_addrbytes(device, pointer to bytes, number of bytes)

Writes a number of address bytes in turn to the chip's address latch.

CYG_BYTE read_data_1(device), read_data_bulk(device, output pointer, number of bytes)

Reads data from the device, respectively a single byte and in bulk.

write_data_1(device, byte), write_data_bulk(device, data pointer, number of bytes)

Writes data to the device, respectively a single byte and in bulk.

wait_ready_or_time(device, initial delay, fallback time)

Wait for the chip to signal READY line or, if this line is not available, fall back to a worst-case time delay (measured in microseconds).

wait_ready_or_status(device, mask)

Wait for the chip to signal READY line or, if this line is not available, enter a loop waiting for its Status register (ANDed with the given mask) to be non-zero.

k9_devlock(device), k9_devunlock(device)

Hooks for any board-specific locking which may be required in addition to the NAND library's chip-level locking. (This would be useful if, for example, access to multiple chips was mediated by a single set of GPIO lines which ought not to be invoked concurrently.)

k9_plf_init(device)

Board-level platform initialisation hook. This is called very early on in the chip initialisation routine; it should set up any locking required by the devlock and devunlock functions, interrupts for the driver and any further lines required to access the chip as approprate. Once this has returned, the chip driver assumes that the platform is fully prepared for it to call the other chip access functions.

k9_plf_partition_setup(device)

Board-level partition initialisation hook. This should set up the partition array of the device struct in a way which is appropriate to the platform. For example, the partitions may be set as fixed ranges of blocks, or by CDL. This is called at the end of the chip initialisation routine and may, for example, call into the chip to read out a "partition table" if one is present on the board. If you do not set up partitions, applications will not be able to use the high-level chip access functions provided the NAND library.