Mainline NAND Howto

This page describes how to enable NAND support in Linux mainline kernel.

= Current status = See MTD Driver

= Prerequisites =


 * Mainline kernel >= 4.7-rc1
 * Sunxi NFC DMA support patches ,
 * NAND detection/initialization patchset

= Kernel Configuration = To use MTD driver with Linux mainline kernel you should enable: Device Drivers ---> <*> Memory Technology Device (MTD) support ---> <*>  OpenFirmware partitioning information support <*>  NAND Device Support  ---> <*>  Support for NAND on Allwinner SoCs

= Known issues =

Many bad blocks
To fix many bad blocks issue you should: 1. Disable nand-on-flash-bbt in your dts 2. Remove this test: http://lxr.free-electrons.com/source/drivers/mtd/nand/nand_base.c?v=4.7#L2940 3. Boot your new kernel and erase chip with flash_erase /dev/mtd[0-X] 4. Re-introduce the bad block check removed in 2, re-enable nand-on-flash-bbt and boot the new kernel

= Adding a new device =

Add NAND controller pin definitions
Most of boards use the same pins for NAND controller, so you should add pin definitions in SoC's DTSI

For example, Allwinner A10/A20 have the same pins used for NAND: nand_pins_a: nand_base0@0 { allwinner,pins = "PC0", "PC1", "PC2", "PC5", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", "PC14", "PC15", "PC16"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_cs0_pins_a: nand_cs@0 { allwinner,pins = "PC4"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_cs1_pins_a: nand_cs@1 { allwinner,pins = "PC3"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_cs2_pins_a: nand_cs@2 { allwinner,pins = "PC17"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_cs3_pins_a: nand_cs@3 { allwinner,pins = "PC18"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_rb0_pins_a: nand_rb@0 { allwinner,pins = "PC6"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

nand_rb1_pins_a: nand_rb@1 { allwinner,pins = "PC7"; allwinner,function = "nand0"; allwinner,drive = ; allwinner,pull = ; };

Add NFC node to SoC's DTSI
Once you define pins, you should add NFC node.

Example for Allwinner A10: nfc: nand@01c03000 { compatible = "allwinner,sun4i-a10-nand"; reg = ; interrupts = <37>; clocks = <&ahb_gates 13>, <&nand_clk>; clock-names = "ahb", "mod"; dmas = <&dma SUN4I_DMA_DEDICATED 3>; dma-names = "rxtx"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; }; Since Allwinner A20 SoCs have it's own interrupt controller, interrupts line should be changed.

Example for A20: nfc: nand@01c03000 { compatible = "allwinner,sun4i-a10-nand"; reg = ; interrupts = ;; clocks = <&ahb_gates 13>, <&nand_clk>; clock-names = "ahb", "mod"; dmas = <&dma SUN4I_DMA_DEDICATED 3>; dma-names = "rxtx"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; };

Enable NAND in board's DTS
Once you have done with SoC's DTSI changes, you should enable NAND in your board DTS file.

In a single-chip configuration, chip usually connected to base nand pins, cs0(Chip Select) and rb0(Ready/Busy) pins. &nfc { pinctrl-names = "default"; pinctrl-0 = <&nand_pins_a>, <&nand_cs0_pins_a>, <&nand_rb0_pins_a>; status = "okay";

nand@0 { #address-cells = <2>; #size-cells = <2>; reg = <0>; allwinner,rb = <0>;

nand-ecc-mode = "hw"; nand-on-flash-bbt; }; };

Define NAND partitions in DTS
If you want, you can define partitions on your NAND. See mtd partitions documentation

For example, if your board have 4G NAND chip, you can split it to 5 partitions:

This lines should be placed in NFC node of your board's DTS. boot0@0 { label = "boot0"; reg = /bits/ 64 ; };

boot0-rescue@200000 { label = "boot0-rescue"; reg = /bits/ 64 ; };

uboot@400000 { label = "uboot"; reg = /bits/ 64 ; };

uboot-rescue@600000 { label = "uboot-rescue"; reg = /bits/ 64 ; };

main@800000 { label = "main"; reg = /bits/ 64 ; }; = Booting from NAND = TODO