From 448c8572cd90387232d074398242e7092e153335 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 19 Nov 2013 08:50:12 -0600 Subject: [PATCH] Rethinking some NAND interfaces --- ChangeLog | 3 + arch/arm/src/sama5/chip/sam_hsmc.h | 38 +++-- arch/arm/src/sama5/sam_nand.c | 191 ++++++++++++++++++----- arch/arm/src/sama5/sam_nand.h | 34 ++++ arch/arm/src/sama5/sam_pmecc.h | 242 +++++++++++++++++++++++++++++ drivers/mtd/mtd_nand.c | 6 +- drivers/mtd/mtd_nandecc.c | 6 +- include/nuttx/mtd/nand_model.h | 1 + include/nuttx/mtd/nand_raw.h | 70 ++++++++- 9 files changed, 531 insertions(+), 60 deletions(-) create mode 100644 arch/arm/src/sama5/sam_pmecc.h diff --git a/ChangeLog b/ChangeLog index aee32e40ee..7a458db4bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6084,3 +6084,6 @@ * drivers/mtd/hamming.c and mtd_nandecc.c and include/nuttx/mtd/hamming.h: Beginning of NAND software ECC calculations. (2013-11-18). + * configs/olimex-lpc-h3131: Add support for the Olimex LPC-H3131 + board. Does not yet boot (2013-11-18). + diff --git a/arch/arm/src/sama5/chip/sam_hsmc.h b/arch/arm/src/sama5/chip/sam_hsmc.h index 769d2a7b3d..fbd6de24a1 100644 --- a/arch/arm/src/sama5/chip/sam_hsmc.h +++ b/arch/arm/src/sama5/chip/sam_hsmc.h @@ -357,19 +357,35 @@ /* PMECC Configuration Register */ -#define HSMC_PMECCFG_BCH_ERR_SHIFT (0) /* Bit 0-2: Error Correcting Capability */ -#define HSMC_PMECCFG_BCH_ERR_MASK (7 << HSMC_PMECCFG_BCH_ERR_SHIFT) -# define HSMC_PMECCFG_BCH_ERR_2 (0 << HSMC_PMECCFG_BCH_ERR_SHIFT) /* 2 errors */ -# define HSMC_PMECCFG_BCH_ERR_4 (1 << HSMC_PMECCFG_BCH_ERR_SHIFT) /* 4 errors */ -# define HSMC_PMECCFG_BCH_ERR_8 (2 << HSMC_PMECCFG_BCH_ERR_SHIFT) /* 8 errors */ -# define HSMC_PMECCFG_BCH_ERR_12 (3 << HSMC_PMECCFG_BCH_ERR_SHIFT) /* 12 errors */ -# define HSMC_PMECCFG_BCH_ERR_24 (4 << HSMC_PMECCFG_BCH_ERR_SHIFT) /* 24 errors */ -#define HSMC_PMECCFG_SECTORSZ (1 << 4) /* Bit 4: Sector Size */ +#define HSMC_PMECCFG_BCHERR_SHIFT (0) /* Bit 0-2: Error Correcting Capability */ +#define HSMC_PMECCFG_BCHERR_MASK (7 << HSMC_PMECCFG_BCHERR_SHIFT) +# define HSMC_PMECCFG_BCHERR_2 (0 << HSMC_PMECCFG_BCHERR_SHIFT) /* 2 errors */ +# define HSMC_PMECCFG_BCHERR_4 (1 << HSMC_PMECCFG_BCHERR_SHIFT) /* 4 errors */ +# define HSMC_PMECCFG_BCHERR_8 (2 << HSMC_PMECCFG_BCHERR_SHIFT) /* 8 errors */ +# define HSMC_PMECCFG_BCHERR_12 (3 << HSMC_PMECCFG_BCHERR_SHIFT) /* 12 errors */ +# define HSMC_PMECCFG_BCHERR_24 (4 << HSMC_PMECCFG_BCHERR_SHIFT) /* 24 errors */ +#define HSMC_PMECCFG_SECTORSZ_SHIFT (4) /* Bit 4: Sector Size */ +#define HSMC_PMECCFG_SECTORSZ_MASK (1 << HSMC_PMECCFG_SECTORSZ_SHIFT) +# define HSMC_PMECCFG_SECTORSZ_512 (0 << HSMC_PMECCFG_SECTORSZ_SHIFT) +# define HSMC_PMECCFG_SECTORSZ_1024 (1 << HSMC_PMECCFG_SECTORSZ_SHIFT) #define HSMC_PMECCFG_PAGESIZE_SHIFT (8) /* Bit 8-9: Number of Sectors in the Page */ #define HSMC_PMECCFG_PAGESIZE_MASK (3 << HSMC_PMECCFG_PAGESIZE_SHIFT) -#define HSMC_PMECCFG_NANDWR (1 << 12) /* Bit 12: NAND Write Access */ -#define HSMC_PMECCFG_SPAREEN (1 << 16) /* Bit 16: Spare Enable */ -#define HSMC_PMECCFG_AUTO (1 << 20) /* Bit 20: Automatic Mode Enable */ +# define HSMC_PMECCFG_PAGESIZE_1SEC (0 << HSMC_PMECCFG_PAGESIZE_SHIFT) /* 1 sector (5121K) */ +# define HSMC_PMECCFG_PAGESIZE_2SEC (1 << HSMC_PMECCFG_PAGESIZE_SHIFT) /* 2 sectors (1/2K) */ +# define HSMC_PMECCFG_PAGESIZE_4SEC (2 << HSMC_PMECCFG_PAGESIZE_SHIFT) /* 4 sectors (2/4K) */ +# define HSMC_PMECCFG_PAGESIZE_8SEC (3 << HSMC_PMECCFG_PAGESIZE_SHIFT) /* 8 sectors (4/8K) */ +#define HSMC_PMECCFG_NANDWR_SHIFT (12) /* Bit 12: NAND Write Access */ +#define HSMC_PMECCFG_NANDWR_MASK (1 << HSMC_PMECCFG_NANDWR_SHIFT) +# define HSMC_PMECCFG_NANDWR_READ (0 << HSMC_PMECCFG_NANDWR_SHIFT) +# define HSMC_PMECCFG_NANDWR_WRITE (1 << HSMC_PMECCFG_NANDWR_SHIFT) +#define HSMC_PMECCFG_SPAREEN_SHIFT (16) /* Bit 16: Spare Enable */ +#define HSMC_PMECCFG_SPAREEN_MASK (1 << HSMC_PMECCFG_SPAREEN_SHIFT) +# define HSMC_PMECCFG_SPARE_DISABLE (0 << HSMC_PMECCFG_SPAREEN_SHIFT) +# define HSMC_PMECCFG_SPARE_ENABLE (1 << HSMC_PMECCFG_SPAREEN_SHIFT) +#define HSMC_PMECCFG_AUTO_SHIFT (20) /* Bit 20: Automatic Mode Enable */ +#define HSMC_PMECCFG_AUTO_MASK (1 << HSMC_PMECCFG_AUTO_SHIFT) +# define HSMC_PMECCFG_AUTO_DISABLE (0 << HSMC_PMECCFG_AUTO_SHIFT) +# define HSMC_PMECCFG_AUTO_ENABLE (1 << HSMC_PMECCFG_AUTO_SHIFT) /* PMECC Spare Area Size Register */ diff --git a/arch/arm/src/sama5/sam_nand.c b/arch/arm/src/sama5/sam_nand.c index 77c7c1cb8c..0bac4bb998 100644 --- a/arch/arm/src/sama5/sam_nand.c +++ b/arch/arm/src/sama5/sam_nand.c @@ -64,6 +64,7 @@ #include +#include "sam_pmecc.h" #include "sam_nand.h" /**************************************************************************** @@ -92,28 +93,44 @@ struct sam_rawnand_s static int nand_readpage_noecc(struct sam_rawnand_s *priv, off_t block, unsigned int page, void *data, void *spare); -#ifdef CONFIG_MTD_NAND_BLOCKCHECK -static int nand_readpage_hwecc(struct sam_rawnand_s *priv, off_t block, - unsigned int page, void *data, void *spare); -static int nand_readpage_pmecc(struct sam_rawnand_s *priv, off_t block, + +#ifdef NAND_HAVE_HSIAO +static int nand_readpage_hsiao(struct sam_rawnand_s *priv, off_t block, unsigned int page, void *data, void *spare); #endif + +#ifdef NAND_HAVE_PMECC +static int nand_readpage_pmecc(struct sam_rawnand_s *priv, off_t block, + unsigned int page, void *data); +#endif + static int nand_writepage_noecc(struct sam_rawnand_s *priv, off_t block, unsigned int page, const void *data, const void *spare); -#ifdef CONFIG_MTD_NAND_BLOCKCHECK -static int nand_writepage_hwecc(struct sam_rawnand_s *priv, off_t block, + +#ifdef NAND_HAVE_HSIAO +static int nand_writepage_hsiao(struct sam_rawnand_s *priv, off_t block, unsigned int page, const void *data, const void *spare); +#endif + +#ifdef NAND_HAVE_PMECC static int nand_writepage_pmecc(struct sam_rawnand_s *priv, off_t block, - unsigned int page, const void *data, const void *spare); + unsigned int page, const void *data); #endif /* MTD driver methods */ static int nand_eraseblock(struct nand_raw_s *raw, off_t block); +static int nand_rawread(struct nand_raw_s *raw, off_t block, + unsigned int page, void *data, void *spare); +static int nand_rawwrite(struct nand_raw_s *raw, off_t block, + unsigned int page, const void *data, const void *spare); + +#ifdef CONFIG_MTD_NAND_HWECC static int nand_readpage(struct nand_raw_s *raw, off_t block, unsigned int page, void *data, void *spare); static int nand_writepage(struct nand_raw_s *raw, off_t block, unsigned int page, const void *data, const void *spare); +#endif /**************************************************************************** * Private Data @@ -167,7 +184,7 @@ static int nand_readpage_noecc(struct sam_rawnand_s *priv, off_t block, } /**************************************************************************** - * Name: nand_readpage_hwecc + * Name: nand_readpage_hsiao * * Description: * Reads the data and/or the spare areas of a page of a NAND FLASH into the @@ -185,14 +202,14 @@ static int nand_readpage_noecc(struct sam_rawnand_s *priv, off_t block, * ****************************************************************************/ -#ifdef CONFIG_MTD_NAND_BLOCKCHECK -static int nand_readpage_hwecc(struct sam_rawnand_s *priv, off_t block, +#ifdef NAND_HAVE_HSIAO +static int nand_readpage_hsiao(struct sam_rawnand_s *priv, off_t block, unsigned int page, void *data, void *spare) { #warning Missing logic return -ENOSYS; } -#endif /* CONFIG_MTD_NAND_BLOCKCHECK */ +#endif /* NAND_HAVE_HSIAO */ /**************************************************************************** * Name: nand_readpage_pmecc @@ -206,21 +223,20 @@ static int nand_readpage_hwecc(struct sam_rawnand_s *priv, off_t block, * block - Number of the block where the page to read resides. * page - Number of the page to read inside the given block. * data - Buffer where the data area will be stored. - * spare - Buffer where the spare area will be stored. * * Returned value. * OK is returned in succes; a negated errno value is returned on failure. * ****************************************************************************/ -#ifdef CONFIG_MTD_NAND_BLOCKCHECK +#ifdef NAND_HAVE_PMECC static int nand_readpage_pmecc(struct sam_rawnand_s *priv, off_t block, - unsigned int page, void *data, void *spare) + unsigned int page, void *data) { #warning Missing logic return -ENOSYS; } -#endif /* CONFIG_MTD_NAND_BLOCKCHECK */ +#endif /* NAND_HAVE_PMECC */ /**************************************************************************** * Name: nand_writepage_noecc @@ -249,7 +265,7 @@ static int nand_writepage_noecc(struct sam_rawnand_s *priv, off_t block, } /**************************************************************************** - * Name: nand_writepage_noecc + * Name: nand_writepage_hsaio * * Description: * Writes the data and/or the spare area of a page on a NAND FLASH chip. @@ -267,42 +283,58 @@ static int nand_writepage_noecc(struct sam_rawnand_s *priv, off_t block, * ****************************************************************************/ -#ifdef CONFIG_MTD_NAND_BLOCKCHECK -static int nand_writepage_hwecc(struct sam_rawnand_s *priv, off_t block, +#ifdef NAND_HAVE_HSIAO +static int nand_writepage_hsiao(struct sam_rawnand_s *priv, off_t block, unsigned int page, const void *data, const void *spare) { -#warning Missing logic - return -ENOSYS; + int ret; + + /* Disable the PMECC */ + + pmecc_disable(); + + /* Perform write operation */ +# warning Missing logic + + return ret; } -#endif /* CONFIG_MTD_NAND_BLOCKCHECK */ +#endif /* NAND_HAVE_HSIAO */ /**************************************************************************** - * Name: nand_writepage_noecc + * Name: nand_writepage_pmecc * * Description: - * Writes the data and/or the spare area of a page on a NAND FLASH chip. - * PMECC calculations are performed. + * Writes the data area of a NAND FLASH page, The PMECC module generates + * redundancy at encoding time. When a NAND write page operation is + * performed. The redundancy is appended to the page and written in the + * spare area. * * Input parameters: * priv - Lower-half, private NAND FLASH device state * block - Number of the block where the page to write resides. * page - Number of the page to write inside the given block. * data - Buffer containing the data to be writting - * spare - Buffer conatining the spare data to be written. * * Returned value. * OK is returned in succes; a negated errno value is returned on failure. * ****************************************************************************/ -#ifdef CONFIG_MTD_NAND_BLOCKCHECK +#ifdef NAND_HAVE_PMECC static int nand_writepage_pmecc(struct sam_rawnand_s *priv, off_t block, - unsigned int page, const void *data, const void *spare) + unsigned int page, const void *data) { -#warning Missing logic - return -ENOSYS; + int ret; + + /* Perform write operation */ +# warning Missing logic + + /* Disable the PMECC */ + + pmecc_disable(); + return ret; } -#endif /* CONFIG_MTD_NAND_BLOCKCHECK */ +#endif /* NAND_HAVE_PMECC */ /**************************************************************************** * Name: nand_eraseblock @@ -328,11 +360,11 @@ static int nand_eraseblock(struct nand_raw_s *raw, off_t block) } /**************************************************************************** - * Name: nand_readpage + * Name: nand_rawread * * Description: * Reads the data and/or the spare areas of a page of a NAND FLASH into the - * provided buffers. + * provided buffers. This is a raw read of the flash contents. * * Input parameters: * raw - Lower-half, raw NAND FLASH interface @@ -346,6 +378,65 @@ static int nand_eraseblock(struct nand_raw_s *raw, off_t block) * ****************************************************************************/ +static int nand_rawread(struct nand_raw_s *raw, off_t block, + unsigned int page, void *data, void *spare) +{ + struct sam_rawnand_s *priv = (struct sam_rawnand_s *)raw; + DEBUGASSERT(raw); + + return nand_readpage_noecc(priv, block, page, data, spare); +} + +/**************************************************************************** + * Name: nand_rawwrite + * + * Description: + * Writes the data and/or the spare area of a page on a NAND FLASH chip. + * This is a raw write of the flash contents. + * + * Input parameters: + * raw - Lower-half, raw NAND FLASH interface + * block - Number of the block where the page to write resides. + * page - Number of the page to write inside the given block. + * data - Buffer containing the data to be writting + * spare - Buffer containing the spare data to be written. + * + * Returned value. + * OK is returned in succes; a negated errno value is returned on failure. + * + ****************************************************************************/ + +static int nand_rawwrite(struct nand_raw_s *raw, off_t block, + unsigned int page, const void *data, + const void *spare) +{ + struct sam_rawnand_s *priv = (struct sam_rawnand_s *)raw; + DEBUGASSERT(raw); + + return nand_writepage_noecc(priv, block, page, data, spare); +} + +/**************************************************************************** + * Name: nand_readpage + * + * Description: + * Reads the data and/or the spare areas of a page of a NAND FLASH into the + * provided buffers. Hardware ECC checking will be performed if so + * configured. + * + * Input parameters: + * raw - Lower-half, raw NAND FLASH interface + * block - Number of the block where the page to read resides. + * page - Number of the page to read inside the given block. + * data - Buffer where the data area will be stored. + * spare - Buffer where the spare area will be stored. + * + * Returned value. + * OK is returned in succes; a negated errno value is returned on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_MTD_NAND_HWECC static int nand_readpage(struct nand_raw_s *raw, off_t block, unsigned int page, void *data, void *spare) { @@ -359,11 +450,19 @@ static int nand_readpage(struct nand_raw_s *raw, off_t block, switch (raw->ecctype) { case NANDECC_NONE: + case NANDECC_CHIPECC: return nand_readpage_noecc(priv, block, page, data, spare); - case NANDECC_HWECC: - return nand_readpage_hwecc(priv, block, page, data, spare); + +#ifdef NAND_HAVE_HSIAO + case NANDECC_HSIAO: + return nand_readpage_hsiao(priv, block, page, data, spare); +#endif + +#ifdef NAND_HAVE_PMECC case NANDECC_PMECC: - return nand_readpage_pmecc(priv, block, page, data, spare); + DEBUGASSERT(!spare); + return nand_readpage_pmecc(priv, block, page, data); +#endif case NANDECC_SWECC: default: @@ -371,12 +470,14 @@ static int nand_readpage(struct nand_raw_s *raw, off_t block, } #endif } +#endif /**************************************************************************** * Name: nand_writepage * * Description: * Writes the data and/or the spare area of a page on a NAND FLASH chip. + * Hardware ECC checking will be performed if so configured. * * Input parameters: * raw - Lower-half, raw NAND FLASH interface @@ -390,6 +491,7 @@ static int nand_readpage(struct nand_raw_s *raw, off_t block, * ****************************************************************************/ +#ifdef CONFIG_MTD_NAND_HWECC static int nand_writepage(struct nand_raw_s *raw, off_t block, unsigned int page, const void *data, const void *spare) @@ -404,11 +506,19 @@ static int nand_writepage(struct nand_raw_s *raw, off_t block, switch (raw->ecctype) { case NANDECC_NONE: + case NANDECC_CHIPECC: return nand_writepage_noecc(priv, block, page, data, spare); - case NANDECC_HWECC: - return nand_writepage_hwecc(priv, block, page, data, spare); + +#ifdef NAND_HAVE_HSIAO + case NANDECC_HSIAO: + return nand_writepage_hsiao(priv, block, page, data, spare); +#endif + +#ifdef NAND_HAVE_PMECC case NANDECC_PMECC: - return nand_writepage_pmecc(priv, block, page, data, spare); + DEBUGASSERT(!spare); + return nand_writepage_pmecc(priv, block, page, data); +#endif case NANDECC_SWECC: default: @@ -416,6 +526,7 @@ static int nand_writepage(struct nand_raw_s *raw, off_t block, } #endif } +#endif /**************************************************************************** * Public Functions @@ -532,8 +643,12 @@ struct mtd_dev_s *sam_nand_initialize(int cs) priv->raw.addraddr = addraddr; priv->raw.dataaddr = dataaddr; priv->raw.eraseblock = nand_eraseblock; + priv->raw.rawread = nand_rawread; + priv->raw.rawwrite = nand_rawwrite; +#ifdef CONFIG_MTD_NAND_HWECC priv->raw.readpage = nand_readpage; priv->raw.writepage = nand_writepage; +#endif priv->cs = cs; /* Initialize the NAND hardware */ diff --git a/arch/arm/src/sama5/sam_nand.h b/arch/arm/src/sama5/sam_nand.h index fc48123687..6b4cf7a0e3 100644 --- a/arch/arm/src/sama5/sam_nand.h +++ b/arch/arm/src/sama5/sam_nand.h @@ -50,6 +50,40 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ +/* Block checking and H/W ECC support must be enabled for HSIAO ECC */ + +#if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(MTD_NAND_HWECC) +# undef CONFIG_SAMA5_EBICS0_HSIAO +# undef CONFIG_SAMA5_EBICS1_HSIAO +# undef CONFIG_SAMA5_EBICS2_HSIAO +# undef CONFIG_SAMA5_EBICS3_HSIAO +#endif + +/* Disable HSIAO support for any banks not enabled or configured for NAND */ + +#if !defined(SAMA5_EBICS0) || !defined(SAMA5_EBICS0_NAND) +# undef CONFIG_SAMA5_EBICS0_HSIAO +#endif + +#if !defined(SAMA5_EBICS1) || !defined(SAMA5_EBICS1_NAND) +# undef CONFIG_SAMA5_EBICS1_HSIAO +#endif + +#if !defined(SAMA5_EBICS2) || !defined(SAMA5_EBICS2_NAND) +# undef CONFIG_SAMA5_EBICS2_HSIAO +#endif + +#if !defined(SAMA5_EBICS3) || !defined(SAMA5_EBICS3_NAND) +# undef CONFIG_SAMA5_EBICS3_HSIAO +#endif + +#undef NAND_HAVE_HSIAO +#if defined(CONFIG_SAMA5_EBICS0_HSIAO) || defined(CONFIG_SAMA5_EBICS1_HSIAO) || \ + defined(CONFIG_SAMA5_EBICS2_HSIAO) || defined(CONFIG_SAMA5_EBICS3_HSIAO) +# define NAND_HAVE_HSIAO +#endif + /* Hardware ECC types. These are extensions to the NANDECC_HWECC value * defined in include/nuttx/mtd/nand_raw.h. * diff --git a/arch/arm/src/sama5/sam_pmecc.h b/arch/arm/src/sama5/sam_pmecc.h new file mode 100644 index 0000000000..53c31eba61 --- /dev/null +++ b/arch/arm/src/sama5/sam_pmecc.h @@ -0,0 +1,242 @@ +/**************************************************************************** + * arch/arm/src/sama5/sam_pmecc.h + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This logic was based largely on Atmel sample code with modifications for + * better integration with NuttX. The Atmel sample code has a BSD + * compatibile license that requires this copyright notice: + * + * Copyright (c) 2010, Atmel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the names NuttX nor Atmel nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMA5_PMECC_H +#define __ARCH_ARM_SRC_SAMA5_PMECC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Block checking and H/W ECC support must be enabled for PMECC */ + +#if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(MTD_NAND_HWECC) +# undef CONFIG_SAMA5_EBICS0_PMECC +# undef CONFIG_SAMA5_EBICS1_PMECC +# undef CONFIG_SAMA5_EBICS2_PMECC +# undef CONFIG_SAMA5_EBICS3_PMECC +#endif + +/* Disable PMECC support for any banks not enabled or configured for NAND */ + +#if !defined(SAMA5_EBICS0) || !defined(SAMA5_EBICS0_NAND) +# undef CONFIG_SAMA5_EBICS0_PMECC +#endif + +#if !defined(SAMA5_EBICS1) || !defined(SAMA5_EBICS1_NAND) +# undef CONFIG_SAMA5_EBICS1_PMECC +#endif + +#if !defined(SAMA5_EBICS2) || !defined(SAMA5_EBICS2_NAND) +# undef CONFIG_SAMA5_EBICS2_PMECC +#endif + +#if !defined(SAMA5_EBICS3) || !defined(SAMA5_EBICS3_NAND) +# undef CONFIG_SAMA5_EBICS3_PMECC +#endif + +/* Count the number of banks that confaigured for NAND with PMECC support + * enabled. + */ + +#undef NAND_HAVE_PMECC +#ifdef CONFIG_SAMA5_EBICS0_PMECC +# undef NAND_HAVE_PMECC +# define NAND_HAVE_PMECC 1 +# define NAND_HAVE_EBIS0_PMECC 1 +#else +# define NAND_HAVE_EBIS0_PMECC 0 +#endif + +#ifdef CONFIG_SAMA5_EBICS1_PMECC +# undef NAND_HAVE_PMECC +# define NAND_HAVE_PMECC 1 +# define NAND_HAVE_EBIS1_PMECC 1 +#else +# define NAND_HAVE_EBIS1_PMECC 0 +#endif + +#ifdef CONFIG_SAMA5_EBICS2_PMECC +# undef NAND_HAVE_PMECC +# define NAND_HAVE_PMECC 1 +# define NAND_HAVE_EBIS2_PMECC 1 +#else +# define NAND_HAVE_EBIS2_PMECC 0 +#endif + +#ifdef CONFIG_SAMA5_EBICS3_PMECC +# undef NAND_HAVE_PMECC +# define NAND_HAVE_PMECC 1 +# define NAND_HAVE_EBIS3_PMECC 1 +#else +# define NAND_HAVE_EBIS3_PMECC 0 +#endif + +/* Count the number of banks using PMECC */ + +#define NAND_NPMECC_BANKS \ + (NAND_HAVE_EBIS0_PMECC + NAND_HAVE_EBIS1_PMECC + \ + NAND_HAVE_EBIS2_PMECC + NAND_HAVE_EBIS3_PMECC + +/* Compile this logic only if there is at least one CS configure for NAND + * and with PMECC support enabled. + */ + +#ifdef NAND_HAVE_PMECC + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pmecc_lock + * + * Description: + * Get exclusive access to PMECC hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if NAND_NPMECC_BANKS > 1 +void pmecc_lock(void); +#else +# define pmecc_lock() +#endif + +/**************************************************************************** + * Name: pmecc_unlock + * + * Description: + * Relinquish exclusive access to PMECC hardware + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if NAND_NPMECC_BANKS > 1 +void pmecc_unlock(void); +#else +# define pmecc_unlock() +#endif + +/**************************************************************************** + * Name: pmecc_enable + * + * Description: + * Enable PMECC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void pmecc_enable(void); + +/**************************************************************************** + * Name: pmecc_disable + * + * Description: + * Enable PMECC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void pmecc_disable(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#else /* NAND_HAVE_PMECC */ +/****************************************************************************/ +/* Stub definitions to minimize conditional compilation when PMECC is + * disabled + */ + +# define pmecc_lock() +# define pmecc_unlock() +# define pmecc_enable() +# define pmecc_disable() + +#endif /* NAND_HAVE_PMECC */ +#endif /* __ARCH_ARM_SRC_SAMA5_PMECC_H */ diff --git a/drivers/mtd/mtd_nand.c b/drivers/mtd/mtd_nand.c index 97fcbf8942..c090da9d19 100755 --- a/drivers/mtd/mtd_nand.c +++ b/drivers/mtd/mtd_nand.c @@ -197,7 +197,7 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block) /* Read spare area of first page of block */ - ret = NAND_READPAGE(raw, block, 0, 0, spare); + ret = NAND_RAWREAD(raw, block, 0, 0, spare); if (ret < 0) { fdbg("ERROR: Cannot read page #0 of block #%d\n", block); @@ -212,7 +212,7 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block) /* Read spare area of second page of block */ - ret = NAND_READPAGE(raw, block, 1, 0, spare); + ret = NAND_RAWREAD(raw, block, 1, 0, spare); if (ret < 0) { fdbg("ERROR: Cannot read page #1 of block #%d\n", block); @@ -220,7 +220,7 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block) } nandscheme_readbadblockmarker(scheme, spare, &marker); - if (marker != 0xFF) + if (marker != 0xff) { return BADBLOCK; } diff --git a/drivers/mtd/mtd_nandecc.c b/drivers/mtd/mtd_nandecc.c index d1796b0ee1..68d5db6bcc 100644 --- a/drivers/mtd/mtd_nandecc.c +++ b/drivers/mtd/mtd_nandecc.c @@ -120,7 +120,7 @@ int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block, /* Start by reading the spare data */ - ret = NAND_READPAGE(raw, block, page, 0, spare); + ret = NAND_RAWREAD(raw, block, page, 0, spare); if (ret < 0) { fdbg("ERROR: Failed to read page:d\n", ret); @@ -129,7 +129,7 @@ int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block, /* Then reading the data */ - ret = NAND_READPAGE(nand->raw, block, page, data, 0); + ret = NAND_RAWREAD(nand->raw, block, page, data, 0); if (ret < 0) { fdbg("ERROR: Failed to read page:d\n", ret); @@ -228,7 +228,7 @@ int nandecc_writepage(FAR struct nand_dev_s *nand, off_t block, /* Perform page write operation */ - ret = NAND_WRITEPAGE(nand->raw, block, page, data, spare); + ret = NAND_RAWWRITE(nand->raw, block, page, data, spare); if (ret < 0) { fdbg("ERROR: Failed to write page:d\n", ret); diff --git a/include/nuttx/mtd/nand_model.h b/include/nuttx/mtd/nand_model.h index 71a3037967..b0c058dcd1 100644 --- a/include/nuttx/mtd/nand_model.h +++ b/include/nuttx/mtd/nand_model.h @@ -53,6 +53,7 @@ #include +#include #include #include diff --git a/include/nuttx/mtd/nand_raw.h b/include/nuttx/mtd/nand_raw.h index 0c828dc773..881596d9db 100644 --- a/include/nuttx/mtd/nand_raw.h +++ b/include/nuttx/mtd/nand_raw.h @@ -140,11 +140,11 @@ #define NAND_ERASEBLOCK(r,b) ((r)->eraseblock(r,b)) /**************************************************************************** - * Name: NAND_READPAGE + * Name: NAND_RAWREAD * * Description: * Reads the data and/or the spare areas of a page of a NAND FLASH into the - * provided buffers. + * provided buffers. This is a raw read of the flash contents. * * Input parameters: * raw - Lower-half, raw NAND FLASH interface @@ -158,13 +158,14 @@ * ****************************************************************************/ -#define NAND_READPAGE(r,b,p,d,s) ((r)->readpage(r,b,p,d,s)) +#define NAND_RAWREAD(r,b,p,d,s) ((r)->rawread(r,b,p,d,s)) /**************************************************************************** - * Name: NAND_WRITEPAGE + * Name: NAND_RAWWRITE * * Description: * Writes the data and/or the spare area of a page on a NAND FLASH chip. + * This is a raw write of the flash contents. * * Input parameters: * raw - Lower-half, raw NAND FLASH interface @@ -178,7 +179,58 @@ * ****************************************************************************/ -#define NAND_WRITEPAGE(r,b,p,d,s) ((r)->writepage(r,b,p,d,s)) +#define NAND_RAWWRITE(r,b,p,d,s) ((r)->rawwrite(r,b,p,d,s)) + +/**************************************************************************** + * Name: NAND_READPAGE + * + * Description: + * Reads the data and/or the spare areas of a page of a NAND FLASH into the + * provided buffers. Hardware ECC checking will be performed if so + * configured. + * + * Input parameters: + * raw - Lower-half, raw NAND FLASH interface + * block - Number of the block where the page to read resides. + * page - Number of the page to read inside the given block. + * data - Buffer where the data area will be stored. + * spare - Buffer where the spare area will be stored. + * + * Returned value. + * OK is returned in succes; a negated errno value is returned on failure. + * + ****************************************************************************/ + +#ifdef MTD_NAND_HWECC +# define NAND_READPAGE(r,b,p,d,s) ((r)->readpage(r,b,p,d,s)) +#else +# define NAND_READPAGE(r,b,p,d,s) ((r)->rawread(r,b,p,d,s)) +#endif + +/**************************************************************************** + * Name: NAND_WRITEPAGE + * + * Description: + * Writes the data and/or the spare area of a page on a NAND FLASH chip. + * Hardware ECC checking will be performed if so configured. + * + * Input parameters: + * raw - Lower-half, raw NAND FLASH interface + * block - Number of the block where the page to write resides. + * page - Number of the page to write inside the given block. + * data - Buffer containing the data to be writting + * spare - Buffer containing the spare data to be written. + * + * Returned value. + * OK is returned in succes; a negated errno value is returned on failure. + * + ****************************************************************************/ + +#ifdef MTD_NAND_HWECC +# define NAND_WRITEPAGE(r,b,p,d,s) ((r)->writepage(r,b,p,d,s)) +#else +# define NAND_WRITEPAGE(r,b,p,d,s) ((r)->rawwrite(r,b,p,d,s)) +#endif /**************************************************************************** * Public Types @@ -201,11 +253,19 @@ struct nand_raw_s /* NAND operations */ CODE int (*eraseblock)(FAR struct nand_raw_s *raw, off_t block); + CODE int (*rawread)(FAR struct nand_raw_s *raw, off_t block, + unsigned int page, FAR void *data, FAR void *spare); + CODE int (*rawwrite)(FAR struct nand_raw_s *raw, off_t block, + unsigned int page, FAR const void *data, + FAR const void *spare); + +#ifdef CONFIG_MTD_NAND_HWECC CODE int (*readpage)(FAR struct nand_raw_s *raw, off_t block, unsigned int page, FAR void *data, FAR void *spare); CODE int (*writepage)(FAR struct nand_raw_s *raw, off_t block, unsigned int page, FAR const void *data, FAR const void *spare); +#endif #ifdef CONFIG_MTD_NAND_BLOCKCHECK /* ECC */