Mainline NAND Howto
MLC NANDs are not well supported right now. You can enable MLC NAND support, but remember that you risk data loss. |
This page describes how to enable NAND support in u-boot and kernel. Just remember that this is incompatible with the legacy (Android) NAND layout. (see "== Known Issues ==" below)
NAND support in u-boot
Follow the u-boot README
NAND support in kernel
Current status
See MTD Driver
Prerequisites
- Mainline kernel >= 4.10.0-rc1
- NAND detection/initialization patchset patch-v5
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
Patch to disable nand bad block check from here https://lkml.org/lkml/2014/10/21/546
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 1ef937b..65ac8af 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -33,6 +33,7 @@ nand-ecc-mode = "hw"; nand-rnd-mode = "hw"; + /* nand-on-flash-bbt; boot0@0 { @@ -74,6 +75,7 @@ 0x2d2e 0x1aea 0x2e17 0x173d 0x3a6e 0x71bf 0x25f9 0x0a5d 0x7c57 0x0fbe 0x46ce 0x4939 0x6b17 0x37bb 0x3e91 0x76db>; }; + */ }; }; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 7311063..153b323 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3312,8 +3312,10 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, chip->page_shift, 0, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", __func__, page); + /* instr->state = MTD_ERASE_FAILED; goto erase_exit; + */ }
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 = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_cs0_pins_a: nand_cs@0 { allwinner,pins = "PC4"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_cs1_pins_a: nand_cs@1 { allwinner,pins = "PC3"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_cs2_pins_a: nand_cs@2 { allwinner,pins = "PC17"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_cs3_pins_a: nand_cs@3 { allwinner,pins = "PC18"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_rb0_pins_a: nand_rb@0 { allwinner,pins = "PC6"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; nand_rb1_pins_a: nand_rb@1 { allwinner,pins = "PC7"; allwinner,function = "nand0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; };
Note: Enable only the pin groups that are actually used by boards.
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 = <0x01c03000 0x1000>; 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 = <0x01c03000 0x1000>; interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;; 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:
Note: This partition table is example and can be changed in feature.
Partition | Partition name | Partition size | Uses |
---|---|---|---|
/dev/mtd0 | boot0 | 2M | SPL |
/dev/mtd1 | boot0-rescue | 2M | SPL Backup |
/dev/mtd2 | uboot | 2M | U-Boot |
/dev/mtd3 | uboot-rescue | 2M | U-Boot Backup |
/dev/mtd4 | main | 4G | User data |
This lines should be placed in NFC node of your board's DTS.
boot0@0 { label = "boot0"; reg = /bits/ 64 <0x0 0x200000>; }; boot0-rescue@200000 { label = "boot0-rescue"; reg = /bits/ 64 <0x200000 0x200000>; }; uboot@400000 { label = "uboot"; reg = /bits/ 64 <0x400000 0x200000>; }; uboot-rescue@600000 { label = "uboot-rescue"; reg = /bits/ 64 <0x600000 0x200000>; }; main@800000 { label = "main"; reg = /bits/ 64 <0x800000 0xff800000>; };
Armbian has a full device tree definition in their dt-overlay git repo https://github.com/armbian/sunxi-DT-overlays/blob/e4dfea8304d66cb3403e5e1b73d2f346349124ec/sun7i-a20/sun7i-a20-nand.dts