3.2.4.15. NANDΒΆ
Introduction
TI infrastructure for NAND Flash devices
TI’s SoC interface with NAND Flash devices via on-chip GPMC (General Purpose Memory Controller) interface or via AEMIF depending on the SoC.
For devices that include GPMC: The ECC algorithms required by NAND devices to protect their data, are managed by two independent hardware engines:
- GPMC ECC engine: used for calculating ECC checksum while writing and reading the NAND device.
- ELM ECC engine: used for locating and decoding ECC errors while reading the NAND device.
- NAND subsystem: protocol driver in MTD sub-system for interfacing with NAND flash devices.
For K2L and K2E:
- AEMIF driver: controller driver for AEMIF engine
For all other SoCs:
- GPMC driver: controller driver for GPMC engine
- ELM driver (for applicable SoC) : controller driver for ELM engine.
Supported Features
- NAND devices having:
- bus-width = x8 | x16
- page-size = 2048 | 4096
- block-size = 128k | 256k
- 1-bit Hamming, BCH4, BCH8 and BCH16 ECC schemes.
- Various transfer modes for different use-cases and applications (like Polled, Polled Prefetch, IRQ and DMA).
- NAND boot support for custom non-ONFI compatible NAND devices using NAND-I2C boot-mode (Refer Chapter on Initialization in processor’s TRM).
- Sub-page write
Accessing NAND partitions
Linux
Within the kernel NAND partitions are accessed via mtd devices. Instead are referring to a partition by its name or its offset a user simply needs to specify the NAND partition in question in the form of its mtd device path. Usually in the format of /dev/mtdX where X is the mtd device number.
Determine NAND Partition MTD Identifier
Within the kernel figuring out the mtd device number that is for a particular NAND partition is simple. A user simply needs to view the list of mtd devices along with its name. Below command will provide this information:
cat /proc/mtd
An example of this output performed on the DRA71x EVM can be seen below.
dev: size erasesize name
mtd0: 00010000 00010000 "QSPI.SPL"
mtd1: 00010000 00010000 "QSPI.SPL.backup1"
mtd2: 00010000 00010000 "QSPI.SPL.backup2"
mtd3: 00010000 00010000 "QSPI.SPL.backup3"
mtd4: 00100000 00010000 "QSPI.u-boot"
mtd5: 00080000 00010000 "QSPI.u-boot-spl-os"
mtd6: 00010000 00010000 "QSPI.u-boot-env"
mtd7: 00010000 00010000 "QSPI.u-boot-env.backup1"
mtd8: 00800000 00010000 "QSPI.kernel"
mtd9: 01620000 00010000 "QSPI.file-system"
mtd10: 00020000 00020000 "NAND.SPL"
mtd11: 00020000 00020000 "NAND.SPL.backup1"
mtd12: 00020000 00020000 "NAND.SPL.backup2"
mtd13: 00020000 00020000 "NAND.SPL.backup3"
mtd14: 00040000 00020000 "NAND.u-boot-spl-os"
mtd15: 00100000 00020000 "NAND.u-boot"
mtd16: 00020000 00020000 "NAND.u-boot-env"
mtd17: 00020000 00020000 "NAND.u-boot-env.backup1"
mtd18: 00800000 00020000 "NAND.kernel"
mtd19: 0f600000 00020000 "NAND.file-system"
As you can see above the list of mtd devices may not only include NAND partitions but list other peripherals that create mtd devices also. From the above you can see that if the user wants to access the file-system partition within the NAND then they use /dev/mtd19 to reference the partition. The names of these partitions, their sizes (in hex) and offsets (in hex) are determined within the specific board’s device tree file.
Erasing, Reading and Writing
For the below sections it is important to remember to replaced mtdX with the mtd device that is associated with the particular NAND partition as described in the above section.
flash_erase /dev/mtdX 0 0
The command to write to a NAND partition is below:
nandwrite -p /dev/mtdX <filename>
nanddump /dev/mtdX -f <filename>
The symbol <filename> should be replaced with the name of a file you want to be created that contains with contents of the NAND partition. Note that the above command by default with save to a file the complete contents of the NAND partition. If your interested in only a certain amount of data being dumped additional parameters can be passed to the utility.
Command Line Partitioning
In some situations, partitions defined in device-tree may not be sufficient or correct. Note that once partitions are defined in device-tree and present in a mainline kernel release, they cannot be changed because this breaks users who have existing data on NAND flash and upgrade to new kernel and device-tree. If you are not affected by this issue, you may choose to override partition information passed from device-tree using command line.
In TI kernel releases, MTD command line partitioning support is built as
module. To use it, add something like following to the kernel command
line (passed using bootargs
U-Boot variable)
setenv bootargs ${bootargs} cmdlinepart.mtdparts=davinci-nand.0:1m(image)ro,-(free-space)
Note that MTD command line parses breaks if there is space in partition
name. So use “free-space” not “free space”. Change davinci-nand.0
to
the correct device name. You can usually find the name to use from
dmesg
output
Creating 2 MTD partitions on "davinci-nand.0":
You can also setup new partitions after kernel has booted with old partitions. You will need to re-probe the NAND driver if it has already probed. Something like:
$ modprobe -r davinci_nand
$ modprobe cmdlinepart mtdparts="davinci-nand.0:2m(image)ro,-(free space)"
$ modprobe davinci_nand
davinci_nand
module name here may have to be changed based on the
SoC you are using.
U-boot
NAND Based File system
Required Software
Building a UBI file system depends on two applications. Ubinize and mkfs.ubifs which are both provided by Ubuntu’s mtd-utils package (apt-get install mtd-utils). The below instructions are based on version 1.5.0 of mtd-utils although newer version are likely to work.
Building UBI File system
When building a UBI file system you need to have a directory that contains the exact files and directories layout that you plan to use for your file system. This is similar to the files and directories layout you will use to copy a file system onto a SD card for booting purposes. It is important that your file system size is smaller than the file system partition in the NAND.
[ubifs]
mode=ubi
image=<name>.ubifs
vol_id=0
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize
mkfs.ubifs -r <directory path> -o <name>.ubifs <MKUBIFS ARGS>
ubinize -o <name>.ubi <UBINIZE ARGS> ubinize.cfg
Once these commands are executed <name>.ubi can then be programmed into the NAND’s designated file-system partition.
Board Name | MKUBIFS Args | UBINIZE Args |
---|---|---|
AM335X GP EVM | -F -m 2048 -e 126976 -c 5600 | -m 2048 -p 128KiB -s 512 -O 2048 |
AM437x GP EVM | -F -m 4096 -e 253952 -c 2650 | -m 4096 -p 256KiB -s 4096 -O 4096 |
K2E EVM | -F -m 2048 -e 126976 -c 3856 | -m 2048 -p 128KiB -s 2048 -O 2048 |
K2L EVM | -F -m 4096 -e 253952 -c 1926 | -m 4096 -p 256KiB -s 4096 -O 4096 |
K2G EVM | -F -m 4096 -e 253952 -c 1926 | -m 4096 -p 256KiB -s 4096 -O 4096 |
DRA71x EVM | -F -m 2048 -e 126976 -c 8192 | -m 2048 -p 128KiB -s 512 -O 2048 |
Table: Table of Parameters to use for Building UBI filesystem image
Board specific configurations
EVM | NAND Part # | Size | Bus-Widt h | Block-Si ze (KB) | Page-Siz e (KB) | OOB-Size (bytes) | ECC Scheme | Hardware |
---|---|---|---|---|---|---|---|---|
AM335x GP | MT29F2G0 8AB | 256 MB | 8 | 128 | 2 | 64 | BCH 8 | GPMC |
AM437x GP | MT29F4G0 8AB | 512 MB | 8 | 256 | 4 | 224 | BCH 16 | GPMC |
AM437x EPOS | MT29F4G0 8AB | 512 MB | 8 | 256 | 4 | 224 | BCH 16 | GPMC |
DRA71x | MT29F2G1 6AADWP:D | 256 MB | 16 | 128 | 2 | 64 | BCH 8 | GPMC |
K2G | MT29F2G1 6ABAFAWP :F | 512 MB | 16 | 128 | 2 | 64 | BCH 16 | GPMC |
K2E | MT29F4G0 8ABBDAH4 D | 1 GB | 8 | 128 | 2 | 64 | TBD | AEMIF |
K2L | MT29F16G 08ADBCAH 4:C | 512 MB | 8 | 256 | 4 | 224 | TBD | AEMIF | |
Table: NAND Flash Specification Summary
AM43xx GP EVM
On this board, NAND Flash data lines are muxed with eMMC, so either eMMC or NAND can be used enabled at a time. By default NAND is enabled.
AM43xx EPOS EVM
On this board, NAND Flash control lines are muxed with QSPI, Thus either NAND or QSPI-NOR can be used at a time. By default NAND is enabled.
DRA71x EVM
On the board, NAND Flash signals are muxed between NAND, NOR and Video Out signals. Therefore, to have the signals properly muxed for NAND to work Pin 1 (first pin on the left) must be turned on and Pin 2 must be turned off. Pin 1 and 2 must never be switched on at the same time. Doing so may cause damage to the board or SoC.
Note
Aside from setting the correct bootmode (SYSBOOT[5:0]) for NAND boot, make sure that The Bus width (SYSBOOT[13]) and Muxed-device (SYSBOOT[12:11]) are set as given in the TRM.
Configurations (GPMC Specific)
How to enable OMAP NAND driver in Linux Kernel ?
OMAP NAND driver can be enable/disable via Linux Kernel Configuration tool. Enable below Configs to enable MTD Support along with MTD nand driver support
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
[*] Command line partition table parsing
<*> Direct char device access to MTD devices
<*> Caching block device access to MTD devices
<*> NAND Device Support --->
<*> NAND Flash device on OMAP2 and OMAP3
<*> Enable UBI - Unsorted block images --->
Transfer Modes
Choose correct bus transfer mode
- “prefetch-polled” Prefetch polled mode (default)
- “polled” Polled mode, without prefetch
- “prefetch-dma” Prefetch enabled DMA mode
- “prefetch-irq” Prefetch enabled IRQ mode
Transfer mode can be configured in linux-kernel via DT binding <ti,nand-xfer-type> Refer: Linux kernel_docs @ $LINUX/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
DMA vs Non DMA Mode (PIO Mode)
The current NAND subsystem within Linux currently deals with reading a single page from the NAND at a time. Unfortunately, the page size is small enough that the overhead for using the DMA (including Linux DMA software stack) negatively impacts the performance. Based on nand performance tests done in early 2016 using the DMA reduced NAND read and write performance by 10-20% depending on SOC. However, cpu load when using polling via the same NAND test were around 99%. When using DMA mode the CPU load for reading was around 35%-54% and for writing was around 15%-30% depending on SOC.
Performance optimizations on NAND
Tweak NAND device signal timings
Much of the NAND throughput can be improved by matching GPMC signal timings with NAND device present on the board. Although GPMC signal timing configurations are not same as those given in NAND device datasheets, but they can be easily derived based on details given in GPMC Controller functional specification.
- Details of GPMC Signal Timing configurations and how to use them can be found in TI’s Processor TRM
Chapter General Purpose Memory Controller Section Signal Control
- In Linux, GPMC signal timing configurations are specified via DTB.
Refer kernel_docs $LINUX/Documentation/devicetree/bindings/bus/ti-gpmc.txt Some timing configurations like <gpmc,rd-cycle-ns>, <gpmc,wr-cycle-ns> have larger impact on NAND throughput than others.
- In U-boot, GPMC signal timing configurations are specified during GPMC initialization in arch/arm/cpu/armv7/../... mem.c or mem_common.c
gpmc_init() :: struct gpmc_cfg
Tweaking UBIFS
- Specify -o bulk_read while mounting UBIFS (read ahead)
- Tweak Linux VM (kernel knobs for VM)
Additional Resources