Linux NAND flash support
Enabling NAND support in the kernel
NAND flash support should work out of the box in upstream version 2.6.27 and later, as well as in v2.6.25.6.atmel.1 and later.
To enable the low-level driver, first enable it in the kernel configuration:
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index b002a46..82da75c 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -340,7 +358,15 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_NAND_ATMEL_ECC_HW=y
+# CONFIG_MTD_NAND_ATMEL_ECC_SOFT is not set
+# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
# CONFIG_MTD_ONENAND is not set
You may want to try disabling CONFIG_MTD_NAND_VERIFY_WRITE for better performance when you've verified that everything works as expected. Also note that if you switch from ECC_HW to ECC_SOFT or vice versa, you need to completely erase and reprogram the flash due to different ECC layouts.
Older versions
For older kernel versions, you need the following patches:
- 0001-MTD-Add-NAND-driver-for-AT32-chips.patch
- 0002-AVR32-move-hsmc_init-to-core_initcall.patch
- 0003-AVR32-Implement-at32_add_device_nand.patch
128-byte OOB support
For adding support for K9GAG08 2GByte nand from samsung:
- 0004-NAND-Implement-opp_128.patch:
Board support
The code for adding the support for the nand in the board code:
static struct smc_timing nand_timing __initdata = {
.ncs_read_setup = 0,
.nrd_setup = 20,
.ncs_write_setup = 0,
.nwe_setup = 20,
.ncs_read_pulse = 100,
.nrd_pulse = 60,
.ncs_write_pulse = 100,
.nwe_pulse = 60,
.read_cycle = 120,
.write_cycle = 120,
}; |
static struct smc_config nand_config __initdata = {
.bus_width = 1,
.nrd_controlled = 1,
.nwe_controlled = 1,
.nwait_mode = 0,
.byte_write = 0,
.tdf_cycles = 2,
.tdf_mode = 0,
};
static struct mtd_partition nand_parts[] = {
{
.name = "main",
.offset = 0x000000000,
.size = 0x080000000,/* 2 GByte */
},
};
static struct at32_nand_data board_nand_data __initdata = {
.enable_pin = GPIO_PIN_PA(12),
.rdy_pin = GPIO_PIN_PA(10),
.ale = 22,
.cle = 21,
.nr_parts = ARRAY_SIZE(nand_parts),
.parts = nand_parts,
};
And the add this to the board init code:
smc_set_timing(&nand_config, &nand_timing);
smc_set_configuration(3, &nand_config);
at32_add_device_nand(0, &board_nand_data);
I have also added the includes:
#include
#include
#include