Mainline NAND Howto

From linux-sunxi.org
Jump to: navigation, search
MBOX icon important.png 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 Linux mainline kernel.

Contents

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

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: [email protected] {
				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: [email protected] {
				allwinner,pins = "PC4";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

			nand_cs1_pins_a: [email protected] {
				allwinner,pins = "PC3";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

			nand_cs2_pins_a: [email protected] {
				allwinner,pins = "PC17";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

			nand_cs3_pins_a: [email protected] {
				allwinner,pins = "PC18";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

			nand_rb0_pins_a: [email protected] {
				allwinner,pins = "PC6";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

			nand_rb1_pins_a: [email protected] {
				allwinner,pins = "PC7";
				allwinner,function = "nand0";
				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
			};

Sticky-note-pin.png 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: [email protected] {
			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: [email protected] {
			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";

	[email protected] {
		#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:
Sticky-note-pin.png 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.

		[email protected] {
			label = "boot0";
			reg = /bits/ 64 <0x0 0x200000>;
		};

		[email protected] {
			label = "boot0-rescue";
			reg = /bits/ 64 <0x200000 0x200000>;
		};

		[email protected] {
			label = "uboot";
			reg = /bits/ 64 <0x400000 0x200000>;
		};

		[email protected] {
			label = "uboot-rescue";
			reg = /bits/ 64 <0x600000 0x200000>;
		};

		[email protected] {
			label = "main";
			reg = /bits/ 64 <0x800000 0xff800000>;
		};

Booting from NAND

TODO

Personal tools
Namespaces

Variants
Actions
Navigation
Tools