From 34bc3eea1d5faafeaf175b1d3418ceea60276f39 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 25 Nov 2013 12:10:24 -0600 Subject: [PATCH] SAMA5D3x-EK NAND: Integrate SAMA5 NAND support into SAMA5D3x-EK board support --- arch/arm/src/sama5/Kconfig | 8 +- arch/arm/src/sama5/chip/sama5d3x_memorymap.h | 23 +++- arch/arm/src/sama5/sam_boot.c | 2 +- arch/arm/src/sama5/sam_nand.c | 113 ++++++++++--------- arch/arm/src/sama5/sam_pmecc.c | 2 +- 5 files changed, 86 insertions(+), 62 deletions(-) diff --git a/arch/arm/src/sama5/Kconfig b/arch/arm/src/sama5/Kconfig index 7817f64f8f8..a9444325ee8 100644 --- a/arch/arm/src/sama5/Kconfig +++ b/arch/arm/src/sama5/Kconfig @@ -3046,7 +3046,7 @@ endchoice # CS0 Memory Type choice prompt "NAND ECC type" default SAMA5_EBICS0_ECCNONE - depends on SAMA5_EBICS0_NAND + depends on SAMA5_EBICS0_NAND config SAMA5_EBICS0_ECCNONE bool "No ECC" @@ -3129,7 +3129,7 @@ endchoice # CS1 Memory Type choice prompt "NAND ECC type" default SAMA5_EBICS1_ECCNONE - depends on SAMA5_EBICS1_NAND + depends on SAMA5_EBICS1_NAND config SAMA5_EBICS1_ECCNONE bool "No ECC" @@ -3212,7 +3212,7 @@ endchoice # CS2 Memory Type choice prompt "NAND ECC type" default SAMA5_EBICS2_ECCNONE - depends on SAMA5_EBICS2_NAND + depends on SAMA5_EBICS2_NAND config SAMA5_EBICS2_ECCNONE bool "No ECC" @@ -3295,7 +3295,7 @@ endchoice # CS3 Memory Type choice prompt "NAND ECC type" default SAMA5_EBICS3_ECCNONE - depends on SAMA5_EBICS3_NAND + depends on SAMA5_EBICS3_NAND config SAMA5_EBICS3_ECCNONE bool "No ECC" diff --git a/arch/arm/src/sama5/chip/sama5d3x_memorymap.h b/arch/arm/src/sama5/chip/sama5d3x_memorymap.h index 80c353791b4..ec680516f3e 100644 --- a/arch/arm/src/sama5/chip/sama5d3x_memorymap.h +++ b/arch/arm/src/sama5/chip/sama5d3x_memorymap.h @@ -263,25 +263,46 @@ #define SAM_AXIMX_MMUFLAGS MMU_IOFLAGS #define SAM_DAP_MMUFLAGS MMU_IOFLAGS +/* SDRAM is a special case because it requires non-cached access of its + * initial configuration, then caached access thereafter. + */ + #define SAM_DDRCS_MMUFLAGS MMU_MEMFLAGS -#if defined(CONFIG_SAMA5_EBICS0_SRAM) || defined(CONFIG_SAMA5_EBICS0_PSRAM) +/* The external memory regions may support all access if they host SRAM, + * PSRAM, or SDRAM. NAND memory requires write access for NAND control and + * so should be uncached. + */ + +#if defined(CONFIG_SAMA5_EBICS0_SRAM) || defined(CONFIG_SAMA5_EBICS0_PSRAM) || \ + defined(CONFIG_SAMA5_EBICS0_NAND) # define SAM_EBICS0_MMUFLAGS MMU_MEMFLAGS +#elif defined(CONFIG_SAMA5_EBICS0_NAND) +# define SAM_EBICS0_MMUFLAGS MMU_IOFLAGS #else # define SAM_EBICS0_MMUFLAGS MMU_ROMFLAGS #endif + #if defined(CONFIG_SAMA5_EBICS1_SRAM) || defined(CONFIG_SAMA5_EBICS1_PSRAM) # define SAM_EBICS1_MMUFLAGS MMU_MEMFLAGS +#elif defined(CONFIG_SAMA5_EBICS1_NAND) +# define SAM_EBICS2_MMUFLAGS MMU_IOFLAGS #else # define SAM_EBICS1_MMUFLAGS MMU_ROMFLAGS #endif + #if defined(CONFIG_SAMA5_EBICS2_SRAM) || defined(CONFIG_SAMA5_EBICS2_PSRAM) # define SAM_EBICS2_MMUFLAGS MMU_MEMFLAGS +#elif defined(CONFIG_SAMA5_EBICS2_NAND) +# define SAM_EBICS2_MMUFLAGS MMU_IOFLAGS #else # define SAM_EBICS2_MMUFLAGS MMU_ROMFLAGS #endif + #if defined(CONFIG_SAMA5_EBICS3_SRAM) || defined(CONFIG_SAMA5_EBICS3_PSRAM) # define SAM_EBICS3_MMUFLAGS MMU_MEMFLAGS +#elif defined(CONFIG_SAMA5_EBICS3_NAND) +# define SAM_EBICS3_MMUFLAGS MMU_IOFLAGS #else # define SAM_EBICS3_MMUFLAGS MMU_ROMFLAGS #endif diff --git a/arch/arm/src/sama5/sam_boot.c b/arch/arm/src/sama5/sam_boot.c index cedddefebe2..2351e26daa5 100644 --- a/arch/arm/src/sama5/sam_boot.c +++ b/arch/arm/src/sama5/sam_boot.c @@ -235,7 +235,7 @@ static const struct section_mapping_s section_mapping[] = SAM_EBICS3_MMUFLAGS, SAM_EBICS3_NSECTIONS }, #endif -#ifdef CONFIG_SAMA5_NFCCR +#ifdef CONFIG_SAMA5_HAVE_NAND { SAM_NFCCR_PSECTION, SAM_NFCCR_VSECTION, SAM_NFCCR_MMUFLAGS, SAM_NFCCR_NSECTIONS }, diff --git a/arch/arm/src/sama5/sam_nand.c b/arch/arm/src/sama5/sam_nand.c index 89fcd4cb969..07933477adf 100644 --- a/arch/arm/src/sama5/sam_nand.c +++ b/arch/arm/src/sama5/sam_nand.c @@ -359,7 +359,7 @@ static void nand_cmdsend(struct sam_nandcs_s *priv, uint32_t cmd, /* Wait until host controller is not busy. */ - while ((nand_getreg(NFCCMD_BASE + NFCADDR_CMD_NFCCMD) & 0x8000000) != 0); + while ((nand_getreg(NFCCMD_BASE + NFCADDR_CMD_NFCCMD) & 0x08000000) != 0); nand_setup_cmddone(priv); /* Send the command plus the ADDR_CYCLE */ @@ -604,11 +604,9 @@ static void nand_nfc_configure(struct sam_nandcs_s *priv, uint8_t mode, regval = NFCADDR_CMD_DATADIS; } - if (((mode & HSMC_ALE_COL_EN) == HSMC_ALE_COL_EN) || - ((mode & HSMC_ALE_ROW_EN) == HSMC_ALE_ROW_EN)) + if (((mode & HSMC_ALE_COL_EN) != 0) || ((mode & HSMC_ALE_ROW_EN) != 0)) { - bool rowonly = (((mode & HSMC_ALE_COL_EN) == 0) && - ((mode & HSMC_ALE_ROW_EN) == HSMC_ALE_ROW_EN)); + bool rowonly = ((mode & HSMC_ALE_COL_EN) == 0); nand_translate_address(priv, coladdr, rowaddr, &acycle0, &acycle1234, rowonly); acycle = nand_get_acycle(ncycles); } @@ -643,7 +641,7 @@ static void nand_wait_cmddone(struct sam_nandcs_s *priv) irqstate_t flags; int ret; - /* Wait for the XFRDONE interrupt to occur */ + /* Wait for the CMDDONE interrupt to occur */ flags = irqsave(); while (!g_nand.cmddone) @@ -655,6 +653,8 @@ static void nand_wait_cmddone(struct sam_nandcs_s *priv) } } + /* Disable further CMDDONE interrupts */ + g_nand.cmddone = false; nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_CMDDONE); irqrestore(flags); @@ -689,7 +689,7 @@ static void nand_setup_cmddone(struct sam_nandcs_s *priv) /* Enable the CMDDONE interrupt */ - nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_CMDDONE); + nand_putreg(SAM_HSMC_IER, HSMC_NFCINT_CMDDONE); irqrestore(flags); } @@ -724,6 +724,8 @@ static void nand_wait_xfrdone(struct sam_nandcs_s *priv) } } + /* Disable further XFRDONE interrupts */ + g_nand.xfrdone = false; nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_XFRDONE); irqrestore(flags); @@ -758,7 +760,7 @@ static void nand_setup_xfrdone(struct sam_nandcs_s *priv) /* Enable the XFRDONE interrupt */ - nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_XFRDONE); + nand_putreg(SAM_HSMC_IER, HSMC_NFCINT_XFRDONE); irqrestore(flags); } @@ -793,6 +795,8 @@ static void nand_wait_rbedge(struct sam_nandcs_s *priv) } } + /* Disable further RBEDGE interrupts */ + g_nand.rbedge = false; nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_RBEDGE0); irqrestore(flags); @@ -827,7 +831,7 @@ static void nand_setup_rbedge(struct sam_nandcs_s *priv) /* Enable the EBEDGE0 interrupt */ - nand_putreg(SAM_HSMC_IDR, HSMC_NFCINT_RBEDGE0); + nand_putreg(SAM_HSMC_IER, HSMC_NFCINT_RBEDGE0); irqrestore(flags); } @@ -1714,6 +1718,8 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block, off_t rowaddr; int ret = OK; + fvdbg("Block %d Page %d\n", block, page); + /* Get page and spare sizes */ pagesize = nandmodel_getpagesize(&priv->raw.model); @@ -1765,7 +1771,6 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block, /* Calculate physical address of the page */ rowaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page; - fvdbg("Block %d Page %d\n", block, page); /* Handle the case where we use NFC SRAM */ @@ -2448,51 +2453,7 @@ struct mtd_dev_s *sam_nand_initialize(int cs) sem_init(&priv->waitsem, 0, 0); - /* Initialize the NAND hardware */ - /* Perform board-specific SMC intialization for this CS */ - - ret = board_nandflash_config(cs); - if (ret < 0) - { - fdbg("ERROR: board_nandflash_config failed for CS%d: %d\n", - cs, ret); - return NULL; - } - - /* Reset the NAND FLASH part */ - - nand_reset(priv); - - /* Probe the NAND part. On success, an MTD interface that wraps - * our raw NAND interface is returned. - */ - - mtd = nand_initialize(&priv->raw); - if (!mtd) - { - fdbg("ERROR: CS%d nand_initialize failed %d\n", cs); - return NULL; - } - - /* Allocate a DMA channel for NAND transfers - * REVISIT: Need DMA channel setup. - */ - - if (nandmodel_getbuswidth(&priv->raw.model) == 16) - { - priv->dma = sam_dmachannel(1, DMA_FLAGS16); - } - else - { - priv->dma = sam_dmachannel(1, DMA_FLAGS8); - } - - if (!priv->dma) - { - fdbg("ERROR: Failed to allocate the DMA channel for CS%d\n", cs); - } - - /* Enable the NAND FLASH controller */ + /* Perform one-time, global NFC/PMECC initialization */ if (!g_nand.initialized) { @@ -2537,6 +2498,48 @@ struct mtd_dev_s *sam_nand_initialize(int cs) g_nand.initialized = true; } + /* Initialize the NAND hardware for this CS */ + /* Perform board-specific SMC intialization for this CS */ + + ret = board_nandflash_config(cs); + if (ret < 0) + { + fdbg("ERROR: board_nandflash_config failed for CS%d: %d\n", + cs, ret); + return NULL; + } + + /* Reset the NAND FLASH part */ + + nand_reset(priv); + + /* Probe the NAND part. On success, an MTD interface that wraps + * our raw NAND interface is returned. + */ + + mtd = nand_initialize(&priv->raw); + if (!mtd) + { + fdbg("ERROR: CS%d nand_initialize failed %d\n", cs); + return NULL; + } + + /* Allocate a DMA channel for NAND transfers */ + + if (nandmodel_getbuswidth(&priv->raw.model) == 16) + { + priv->dma = sam_dmachannel(1, DMA_FLAGS16); + } + else + { + priv->dma = sam_dmachannel(1, DMA_FLAGS8); + } + + if (!priv->dma) + { + fdbg("ERROR: Failed to allocate the DMA channel for CS%d\n", cs); + } + /* Return the MTD wrapper interface as the MTD device */ return mtd; diff --git a/arch/arm/src/sama5/sam_pmecc.c b/arch/arm/src/sama5/sam_pmecc.c index 4b23493e198..f08c9b3d732 100644 --- a/arch/arm/src/sama5/sam_pmecc.c +++ b/arch/arm/src/sama5/sam_pmecc.c @@ -702,7 +702,7 @@ static uint32_t pmecc_correctionalgo(uint32_t isr, uint32_t data) } #define HSMC_PAGESIZE \ - ((1 << ((nand_getreg(SAM_HSMC_PMECCFG) & HSMC_PMECCFG_PAGESIZE_MASK) >> \ + (1 << ((nand_getreg(SAM_HSMC_PMECCFG) & HSMC_PMECCFG_PAGESIZE_MASK) >> \ HSMC_PMECCFG_PAGESIZE_SHIFT)) while (sector < (uint32_t)HSMC_PAGESIZE && isr != 0)