SAMA5 NAND: More stuff
This commit is contained in:
parent
3b1928e1f1
commit
25449c2d1f
@ -3042,27 +3042,35 @@ config SAMA5_EBICS0_NAND
|
|||||||
|
|
||||||
endchoice # CS0 Memory Type
|
endchoice # CS0 Memory Type
|
||||||
|
|
||||||
if SAMA5_EBICS0_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
choice
|
||||||
config SAMA5_EBICS0_HWECC
|
prompt "NAND ECC type"
|
||||||
bool "NAND H/W ECC support"
|
default SAMA5_EBICS0_ECCNONE
|
||||||
default n
|
depends on SAMA5_EBICS0_NAND
|
||||||
|
|
||||||
|
config SAMA5_EBICS0_ECCNONE
|
||||||
|
bool "No ECC"
|
||||||
|
---help---
|
||||||
|
Only raw transfers to/from NAND are supported
|
||||||
|
|
||||||
|
config SAMA5_EBICS0_SWECC
|
||||||
|
bool "Software ECC"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_SWECC
|
||||||
|
---help---
|
||||||
|
ECC is performed by higher level software logic
|
||||||
|
|
||||||
|
config SAMA5_EBICS0_PMECC
|
||||||
|
bool "NAND H/W PMECC Support"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
||||||
---help---
|
---help---
|
||||||
Enable hardware assisted support for ECC calculations
|
Enable hardware assisted support for ECC calculations
|
||||||
|
|
||||||
if SAMA5_EBICS0_HWECC
|
config SAMA5_EBICS0_CHIPECC
|
||||||
choice
|
bool "Embedded chip ECC"
|
||||||
prompt "H/W ECC method"
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_EMBEDDEDECC
|
||||||
default SAMA5_EBICS0_PMECC
|
---help---
|
||||||
|
Some NAND devices have internal, embedded ECC function.
|
||||||
|
|
||||||
config SAMA5_EBICS0_PMECC
|
endchoice # NAND ECC type
|
||||||
bool "PMECC"
|
|
||||||
|
|
||||||
config SAMA5_EBICS0_HSIAO
|
|
||||||
bool "HSIAO ECC"
|
|
||||||
|
|
||||||
endchoice # H/W ECC method
|
|
||||||
endif # SAMA5_EBICS0_HWECC
|
|
||||||
endif # SAMA5_EBICS0_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
|
||||||
endif # SAMA5_EBICS0
|
endif # SAMA5_EBICS0
|
||||||
|
|
||||||
config SAMA5_EBICS1
|
config SAMA5_EBICS1
|
||||||
@ -3115,27 +3123,35 @@ config SAMA5_EBICS1_NAND
|
|||||||
|
|
||||||
endchoice # CS1 Memory Type
|
endchoice # CS1 Memory Type
|
||||||
|
|
||||||
if SAMA5_EBICS1_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
choice
|
||||||
config SAMA5_EBICS1_HWECC
|
prompt "NAND ECC type"
|
||||||
bool "NAND H/W ECC support"
|
default SAMA5_EBICS1_ECCNONE
|
||||||
default n
|
depends on SAMA5_EBICS1_NAND
|
||||||
|
|
||||||
|
config SAMA5_EBICS1_ECCNONE
|
||||||
|
bool "No ECC"
|
||||||
|
---help---
|
||||||
|
Only raw transfers to/from NAND are supported
|
||||||
|
|
||||||
|
config SAMA5_EBICS1_SWECC
|
||||||
|
bool "Software ECC"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_SWECC
|
||||||
|
---help---
|
||||||
|
ECC is performed by higher level software logic
|
||||||
|
|
||||||
|
config SAMA5_EBICS1_PMECC
|
||||||
|
bool "NAND H/W PMECC Support"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
||||||
---help---
|
---help---
|
||||||
Enable hardware assisted support for ECC calculations
|
Enable hardware assisted support for ECC calculations
|
||||||
|
|
||||||
if SAMA5_EBICS1_HWECC
|
config SAMA5_EBICS1_CHIPECC
|
||||||
choice
|
bool "Embedded chip ECC"
|
||||||
prompt "H/W ECC method"
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_EMBEDDEDECC
|
||||||
default SAMA5_EBICS1_PMECC
|
---help---
|
||||||
|
Some NAND devices have internal, embedded ECC function.
|
||||||
|
|
||||||
config SAMA5_EBICS1_PMECC
|
endchoice # NAND ECC type
|
||||||
bool "PMECC"
|
|
||||||
|
|
||||||
config SAMA5_EBICS1_HSIAO
|
|
||||||
bool "HSIAO ECC"
|
|
||||||
|
|
||||||
endchoice # H/W ECC method
|
|
||||||
endif # SAMA5_EBICS1_HWECC
|
|
||||||
endif # SAMA5_EBICS1_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
|
||||||
endif # SAMA5_EBICS1
|
endif # SAMA5_EBICS1
|
||||||
|
|
||||||
config SAMA5_EBICS2
|
config SAMA5_EBICS2
|
||||||
@ -3188,27 +3204,35 @@ config SAMA5_EBICS2_NAND
|
|||||||
|
|
||||||
endchoice # CS2 Memory Type
|
endchoice # CS2 Memory Type
|
||||||
|
|
||||||
if SAMA5_EBICS2_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
choice
|
||||||
config SAMA5_EBICS2_HWECC
|
prompt "NAND ECC type"
|
||||||
bool "NAND H/W ECC support"
|
default SAMA5_EBICS2_ECCNONE
|
||||||
default n
|
depends on SAMA5_EBICS2_NAND
|
||||||
|
|
||||||
|
config SAMA5_EBICS2_ECCNONE
|
||||||
|
bool "No ECC"
|
||||||
|
---help---
|
||||||
|
Only raw transfers to/from NAND are supported
|
||||||
|
|
||||||
|
config SAMA5_EBICS2_SWECC
|
||||||
|
bool "Software ECC"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_SWECC
|
||||||
|
---help---
|
||||||
|
ECC is performed by higher level software logic
|
||||||
|
|
||||||
|
config SAMA5_EBICS2_PMECC
|
||||||
|
bool "NAND H/W PMECC Support"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
||||||
---help---
|
---help---
|
||||||
Enable hardware assisted support for ECC calculations
|
Enable hardware assisted support for ECC calculations
|
||||||
|
|
||||||
if SAMA5_EBICS2_HWECC
|
config SAMA5_EBICS2_CHIPECC
|
||||||
choice
|
bool "Embedded chip ECC"
|
||||||
prompt "H/W ECC method"
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_EMBEDDEDECC
|
||||||
default SAMA5_EBICS2_PMECC
|
---help---
|
||||||
|
Some NAND devices have internal, embedded ECC function.
|
||||||
|
|
||||||
config SAMA5_EBICS2_PMECC
|
endchoice # NAND ECC type
|
||||||
bool "PMECC"
|
|
||||||
|
|
||||||
config SAMA5_EBICS2_HSIAO
|
|
||||||
bool "HSIAO ECC"
|
|
||||||
|
|
||||||
endchoice # H/W ECC method
|
|
||||||
endif # SAMA5_EBICS2_HWECC
|
|
||||||
endif # SAMA5_EBICS2_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
|
||||||
endif # SAMA5_EBICS2
|
endif # SAMA5_EBICS2
|
||||||
|
|
||||||
config SAMA5_EBICS3
|
config SAMA5_EBICS3
|
||||||
@ -3261,27 +3285,35 @@ config SAMA5_EBICS3_NAND
|
|||||||
|
|
||||||
endchoice # CS3 Memory Type
|
endchoice # CS3 Memory Type
|
||||||
|
|
||||||
if SAMA5_EBICS3_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
choice
|
||||||
config SAMA5_EBICS3_HWECC
|
prompt "NAND ECC type"
|
||||||
bool "NAND H/W ECC support"
|
default SAMA5_EBICS3_ECCNONE
|
||||||
default n
|
depends on SAMA5_EBICS3_NAND
|
||||||
|
|
||||||
|
config SAMA5_EBICS3_ECCNONE
|
||||||
|
bool "No ECC"
|
||||||
|
---help---
|
||||||
|
Only raw transfers to/from NAND are supported
|
||||||
|
|
||||||
|
config SAMA5_EBICS3_SWECC
|
||||||
|
bool "Software ECC"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_SWECC
|
||||||
|
---help---
|
||||||
|
ECC is performed by higher level software logic
|
||||||
|
|
||||||
|
config SAMA5_EBICS3_PMECC
|
||||||
|
bool "NAND H/W PMECC Support"
|
||||||
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
||||||
---help---
|
---help---
|
||||||
Enable hardware assisted support for ECC calculations
|
Enable hardware assisted support for ECC calculations
|
||||||
|
|
||||||
if SAMA5_EBICS3_HWECC
|
config SAMA5_EBICS3_CHIPECC
|
||||||
choice
|
bool "Embedded chip ECC"
|
||||||
prompt "H/W ECC method"
|
depends on MTD_NAND_BLOCKCHECK && MTD_NAND_EMBEDDEDECC
|
||||||
default SAMA5_EBICS3_PMECC
|
---help---
|
||||||
|
Some NAND devices have internal, embedded ECC function.
|
||||||
|
|
||||||
config SAMA5_EBICS3_PMECC
|
endchoice # NAND ECC type
|
||||||
bool "PMECC"
|
|
||||||
|
|
||||||
config SAMA5_EBICS3_HSIAO
|
|
||||||
bool "HSIAO ECC"
|
|
||||||
|
|
||||||
endchoice # H/W ECC method
|
|
||||||
endif # SAMA5_EBICS3_HWECC
|
|
||||||
endif # SAMA5_EBICS3_NAND && MTD_NAND_BLOCKCHECK && MTD_NAND_HWECC
|
|
||||||
endif # SAMA5_EBICS3
|
endif # SAMA5_EBICS3
|
||||||
|
|
||||||
if SAMA5_EBICS0_NAND || SAMA5_EBICS1_NAND || SAMA5_EBICS2_NAND || SAMA5_EBICS3_NAND
|
if SAMA5_EBICS0_NAND || SAMA5_EBICS1_NAND || SAMA5_EBICS2_NAND || SAMA5_EBICS3_NAND
|
||||||
|
@ -228,16 +228,16 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SAMA5_EBICS0_NAND),y)
|
ifeq ($(CONFIG_SAMA5_EBICS0_NAND),y)
|
||||||
CHIP_CSRCS += sam_nand.c
|
CHIP_CSRCS += sam_nand.c sam_pmecc.c
|
||||||
else
|
else
|
||||||
ifeq ($(CONFIG_SAMA5_EBICS1_NAND),y)
|
ifeq ($(CONFIG_SAMA5_EBICS1_NAND),y)
|
||||||
CHIP_CSRCS += sam_nand.c
|
CHIP_CSRCS += sam_nand.c sam_pmecc.c
|
||||||
else
|
else
|
||||||
ifeq ($(CONFIG_SAMA5_EBICS2_NAND),y)
|
ifeq ($(CONFIG_SAMA5_EBICS2_NAND),y)
|
||||||
CHIP_CSRCS += sam_nand.c
|
CHIP_CSRCS += sam_nand.c sam_pmecc.c
|
||||||
else
|
else
|
||||||
ifeq ($(CONFIG_SAMA5_EBICS3_NAND),y)
|
ifeq ($(CONFIG_SAMA5_EBICS3_NAND),y)
|
||||||
CHIP_CSRCS += sam_nand.c
|
CHIP_CSRCS += sam_nand.c sam_pmecc.c
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -87,16 +87,21 @@
|
|||||||
|
|
||||||
/* Nand flash chip status codes */
|
/* Nand flash chip status codes */
|
||||||
|
|
||||||
#define STATUS_ERROR (1 << 0)
|
#define STATUS_ERROR (1 << 0)
|
||||||
#define STATUS_READY (1 << 6)
|
#define STATUS_READY (1 << 6)
|
||||||
|
|
||||||
/* NFC ALE CLE command parameter */
|
/* NFC ALE CLE command parameter */
|
||||||
|
|
||||||
#define SMC_ALE_COL_EN (1 << 0)
|
#define SMC_ALE_COL_EN (1 << 0)
|
||||||
#define SMC_ALE_ROW_EN (1 << 1)
|
#define SMC_ALE_ROW_EN (1 << 1)
|
||||||
#define SMC_CLE_WRITE_EN (1 << 2)
|
#define SMC_CLE_WRITE_EN (1 << 2)
|
||||||
#define SMC_CLE_DATA_EN (1 << 3)
|
#define SMC_CLE_DATA_EN (1 << 3)
|
||||||
#define SMC_CLE_VCMD2_EN (1 << 4)
|
#define SMC_CLE_VCMD2_EN (1 << 4)
|
||||||
|
|
||||||
|
/* Number of tries for erasing or writing block */
|
||||||
|
|
||||||
|
#define NAND_ERASE_NRETRIES 2
|
||||||
|
#define NAND_WRITE_NRETRIES 2
|
||||||
|
|
||||||
/* DMA Configuration */
|
/* DMA Configuration */
|
||||||
|
|
||||||
@ -178,11 +183,6 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
|||||||
static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, void *data, void *spare);
|
unsigned int page, void *data, void *spare);
|
||||||
|
|
||||||
#ifdef NAND_HAVE_HSIAO
|
|
||||||
static int nand_readpage_hsiao(struct sam_nandcs_s *priv, off_t block,
|
|
||||||
unsigned int page, void *data, void *spare);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NAND_HAVE_PMECC
|
#ifdef NAND_HAVE_PMECC
|
||||||
static int nand_readpage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_readpage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, void *data);
|
unsigned int page, void *data);
|
||||||
@ -191,11 +191,6 @@ static int nand_readpage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, const void *data, const void *spare);
|
unsigned int page, const void *data, const void *spare);
|
||||||
|
|
||||||
#ifdef NAND_HAVE_HSIAO
|
|
||||||
static int nand_writepage_hsiao(struct sam_nandcs_s *priv, off_t block,
|
|
||||||
unsigned int page, const void *data, const void *spare);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NAND_HAVE_PMECC
|
#ifdef NAND_HAVE_PMECC
|
||||||
static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, const void *data);
|
unsigned int page, const void *data);
|
||||||
@ -216,6 +211,10 @@ static int nand_writepage(struct nand_raw_s *raw, off_t block,
|
|||||||
unsigned int page, const void *data, const void *spare);
|
unsigned int page, const void *data, const void *spare);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Initialization */
|
||||||
|
|
||||||
|
static void nand_reset(struct sam_nandcs_s *priv);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -613,7 +612,7 @@ static void nand_nfc_configure(struct sam_nandcs_s *priv, uint8_t mode,
|
|||||||
rw = NFCADDR_CMD_NFCRD;
|
rw = NFCADDR_CMD_NFCRD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode & SMC_CLE_DATA_EN) != 0 && priv->nfcsram)
|
if ((mode & SMC_CLE_DATA_EN) != 0)
|
||||||
{
|
{
|
||||||
regval = NFCADDR_CMD_DATAEN;
|
regval = NFCADDR_CMD_DATAEN;
|
||||||
}
|
}
|
||||||
@ -1042,9 +1041,11 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
|
|||||||
src = priv->raw.dataaddr;
|
src = priv->raw.dataaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then perform the transfer via DMA or not */
|
/* Then perform the transfer via DMA or not, depending on if we have
|
||||||
|
* a DMA channel assigned.
|
||||||
|
*/
|
||||||
|
|
||||||
if (priv->dmaxfr)
|
if (priv->dma)
|
||||||
{
|
{
|
||||||
/* Transfer using DMA */
|
/* Transfer using DMA */
|
||||||
|
|
||||||
@ -1198,9 +1199,11 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
|||||||
|
|
||||||
dest += offset;
|
dest += offset;
|
||||||
|
|
||||||
/* Then perform the transfer via DMA or not */
|
/* Then perform the transfer via DMA or not, depending on if we have
|
||||||
|
* a DMA channel assigned.
|
||||||
|
*/
|
||||||
|
|
||||||
if (priv->dmaxfr)
|
if (priv->dma)
|
||||||
{
|
{
|
||||||
/* Transfer using DMA */
|
/* Transfer using DMA */
|
||||||
|
|
||||||
@ -1252,37 +1255,82 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
|||||||
static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, void *data, void *spare)
|
unsigned int page, void *data, void *spare)
|
||||||
{
|
{
|
||||||
#warning Missing logic
|
uint32_t regval;
|
||||||
return -ENOSYS;
|
uint16_t pagesize;
|
||||||
}
|
uint16_t sparesize;
|
||||||
|
off_t rawaddr;
|
||||||
|
off_t coladdr;
|
||||||
|
|
||||||
/****************************************************************************
|
fvdbg("Block %d Page %d\n", (int)block, page);
|
||||||
* Name: nand_readpage_hsiao
|
DEBUGASSERT(priv && (data || spare));
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Reads the data and/or the spare areas of a page of a NAND FLASH into the
|
|
||||||
* provided buffers. HSIAO ECC is used
|
|
||||||
*
|
|
||||||
* Input parameters:
|
|
||||||
* priv - Lower-half, private NAND FLASH device state
|
|
||||||
* 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 NAND_HAVE_HSIAO
|
/* Get page and spare sizes */
|
||||||
static int nand_readpage_hsiao(struct sam_nandcs_s *priv, off_t block,
|
|
||||||
unsigned int page, void *data, void *spare)
|
pagesize = nandmodel_getpagesize(&priv->raw.model);
|
||||||
{
|
sparesize = nandmodel_getsparesize(&priv->raw.model);
|
||||||
#warning Missing logic
|
|
||||||
return -ENOSYS;
|
/* Convert the page size to something understood by the hardware */
|
||||||
|
|
||||||
|
switch (pagesize)
|
||||||
|
{
|
||||||
|
case 512:
|
||||||
|
regval = HSMC_CFG_PAGESIZE_512;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1024:
|
||||||
|
regval = HSMC_CFG_PAGESIZE_1024;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2048:
|
||||||
|
regval = HSMC_CFG_PAGESIZE_2048;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4096:
|
||||||
|
regval = HSMC_CFG_PAGESIZE_4096;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8192:
|
||||||
|
regval = HSMC_CFG_PAGESIZE_8192;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fdbg("ERROR: Unsupported page size: %d\n", pagesize);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* Configure the SMC */
|
||||||
|
|
||||||
|
regval |= (HSMC_CFG_RBEDGE | HSMC_CFG_DTOCYC(15) | HSMC_CFG_DTOMUL_1048576 |
|
||||||
|
HSMC_CFG_NFCSPARESIZE((sparesize-1) >> 2));
|
||||||
|
|
||||||
|
/* Calculate actual address of the page */
|
||||||
|
|
||||||
|
rawaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
|
||||||
|
coladdr = data ? 0 : pagesize;
|
||||||
|
|
||||||
|
/* Initialize the NFC */
|
||||||
|
|
||||||
|
priv->xfrdone = false;
|
||||||
|
nand_nfc_configure(priv,
|
||||||
|
SMC_ALE_COL_EN | SMC_ALE_ROW_EN | SMC_CLE_VCMD2_EN | SMC_CLE_DATA_EN,
|
||||||
|
COMMAND_READ_1, COMMAND_READ_2, coladdr, rawaddr);
|
||||||
|
nand_wait_xfrdone(priv);
|
||||||
|
|
||||||
|
/* Read data area if so requested */
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
nand_read(priv, true, (uint8_t *)data, pagesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the spare are is so requrest */
|
||||||
|
|
||||||
|
if (spare)
|
||||||
|
{
|
||||||
|
nand_read(priv, true, (uint8_t *)spare, sparesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
#endif /* NAND_HAVE_HSIAO */
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nand_readpage_pmecc
|
* Name: nand_readpage_pmecc
|
||||||
@ -1341,7 +1389,7 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
|
|
||||||
/* Get page and spare sizes */
|
/* Get page and spare sizes */
|
||||||
|
|
||||||
pagesize = nandmodel_getpagesize(&priv->raw.model);
|
pagesize = nandmodel_getpagesize(&priv->raw.model);
|
||||||
sparesize = nandmodel_getsparesize(&priv->raw.model);
|
sparesize = nandmodel_getsparesize(&priv->raw.model);
|
||||||
|
|
||||||
/* Convert the page size to something understood by the hardware */
|
/* Convert the page size to something understood by the hardware */
|
||||||
@ -1394,20 +1442,13 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
|
|
||||||
/* Handle the case where we use NFC SRAM */
|
/* Handle the case where we use NFC SRAM */
|
||||||
|
|
||||||
if (priv->nfcsram)
|
if (data)
|
||||||
{
|
{
|
||||||
if (data)
|
nand_write(priv, true, (uint8_t *)data, pagesize, 0);
|
||||||
{
|
|
||||||
nand_write(priv, true, (uint8_t *)data, pagesize, 0);
|
|
||||||
|
|
||||||
if (spare)
|
if (spare)
|
||||||
{
|
|
||||||
nand_write(priv, true, (uint8_t *)spare, sparesize, pagesize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spare)
|
|
||||||
{
|
{
|
||||||
nand_write(priv, true, (uint8_t *)spare, sparesize, 0);
|
nand_write(priv, true, (uint8_t *)spare, sparesize, pagesize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1417,29 +1458,11 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
{
|
{
|
||||||
/* Start a Data Phase */
|
/* Start a Data Phase */
|
||||||
|
|
||||||
if (priv->nfcsram)
|
priv->xfrdone = false;
|
||||||
{
|
nand_nfc_configure(priv,
|
||||||
priv->xfrdone = false;
|
SMC_CLE_WRITE_EN | SMC_ALE_COL_EN |SMC_ALE_ROW_EN |SMC_CLE_DATA_EN,
|
||||||
nand_nfc_configure(priv,
|
COMMAND_WRITE_1, 0, 0, rawaddr);
|
||||||
SMC_CLE_WRITE_EN | SMC_ALE_COL_EN |SMC_ALE_ROW_EN |SMC_CLE_DATA_EN,
|
nand_wait_xfrdone(priv);
|
||||||
COMMAND_WRITE_1, 0, 0, rawaddr);
|
|
||||||
nand_wait_xfrdone(priv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nand_nfc_configure(priv,
|
|
||||||
SMC_CLE_WRITE_EN | SMC_ALE_COL_EN |SMC_ALE_ROW_EN,
|
|
||||||
COMMAND_WRITE_1, 0, 0, rawaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!priv->nfcsram)
|
|
||||||
{
|
|
||||||
nand_write(priv, false, (uint8_t *)data, pagesize, 0);
|
|
||||||
if (spare)
|
|
||||||
{
|
|
||||||
nand_write(priv, false, (uint8_t *)spare, sparesize, pagesize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nand_nfc_configure(priv, SMC_CLE_WRITE_EN, COMMAND_WRITE_2, 0, 0, 0);
|
nand_nfc_configure(priv, SMC_CLE_WRITE_EN, COMMAND_WRITE_2, 0, 0, 0);
|
||||||
nand_wait_rbedge(priv);
|
nand_wait_rbedge(priv);
|
||||||
@ -1473,42 +1496,6 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: nand_writepage_hsaio
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Writes the data and/or the spare area of a page on a NAND FLASH chip.
|
|
||||||
* HSIAO ECC calculations are performed.
|
|
||||||
*
|
|
||||||
* 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 NAND_HAVE_HSIAO
|
|
||||||
static int nand_writepage_hsiao(struct sam_nandcs_s *priv, off_t block,
|
|
||||||
unsigned int page, const void *data, const void *spare)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Disable the PMECC */
|
|
||||||
|
|
||||||
pmecc_disable();
|
|
||||||
|
|
||||||
/* Perform write operation */
|
|
||||||
# warning Missing logic
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* NAND_HAVE_HSIAO */
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nand_writepage_pmecc
|
* Name: nand_writepage_pmecc
|
||||||
*
|
*
|
||||||
@ -1533,7 +1520,7 @@ static int nand_writepage_hsiao(struct sam_nandcs_s *priv, off_t block,
|
|||||||
static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||||
unsigned int page, const void *data)
|
unsigned int page, const void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = -ENOSYS;
|
||||||
|
|
||||||
/* Perform write operation */
|
/* Perform write operation */
|
||||||
# warning Missing logic
|
# warning Missing logic
|
||||||
@ -1560,19 +1547,14 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int nand_eraseblock(struct nand_raw_s *raw, off_t block)
|
static inline int nand_tryeraseblock(struct sam_nandcs_s *priv, off_t block)
|
||||||
{
|
{
|
||||||
struct sam_nandcs_s *priv = (struct sam_nandcs_s *)raw;
|
|
||||||
uint32_t rawaddr;
|
uint32_t rawaddr;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
DEBUGASSERT(raw);
|
|
||||||
|
|
||||||
fvdbg("Block %d\n", (int)block);
|
|
||||||
|
|
||||||
/* Calculate address used for erase */
|
/* Calculate address used for erase */
|
||||||
|
|
||||||
rawaddr = block * nandmodel_pagesperblock(&raw->model);
|
rawaddr = block * nandmodel_pagesperblock(&priv->raw.model);
|
||||||
|
|
||||||
/* Configure the NFC for the block erase */
|
/* Configure the NFC for the block erase */
|
||||||
|
|
||||||
@ -1591,6 +1573,33 @@ static int nand_eraseblock(struct nand_raw_s *raw, off_t block)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nand_eraseblock(struct nand_raw_s *raw, off_t block)
|
||||||
|
{
|
||||||
|
struct sam_nandcs_s *priv = (struct sam_nandcs_s *)raw;
|
||||||
|
int retries = NAND_ERASE_NRETRIES;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
|
fvdbg("Block %d\n", (int)block);
|
||||||
|
|
||||||
|
while (retries > 0)
|
||||||
|
{
|
||||||
|
ret = nand_tryeraseblock(priv, block);
|
||||||
|
if (ret == OK)
|
||||||
|
{
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
retries--;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdbg("ERROR: Failed to erase %d after %d tries\n",
|
||||||
|
(int)block, NAND_ERASE_NRETRIES);
|
||||||
|
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nand_rawread
|
* Name: nand_rawread
|
||||||
*
|
*
|
||||||
@ -1685,11 +1694,6 @@ static int nand_readpage(struct nand_raw_s *raw, off_t block,
|
|||||||
case NANDECC_CHIPECC:
|
case NANDECC_CHIPECC:
|
||||||
return nand_readpage_noecc(priv, block, page, data, spare);
|
return nand_readpage_noecc(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
|
#ifdef NAND_HAVE_PMECC
|
||||||
case NANDECC_PMECC:
|
case NANDECC_PMECC:
|
||||||
DEBUGASSERT(!spare);
|
DEBUGASSERT(!spare);
|
||||||
@ -1741,11 +1745,6 @@ static int nand_writepage(struct nand_raw_s *raw, off_t block,
|
|||||||
case NANDECC_CHIPECC:
|
case NANDECC_CHIPECC:
|
||||||
return nand_writepage_noecc(priv, block, page, data, spare);
|
return nand_writepage_noecc(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
|
#ifdef NAND_HAVE_PMECC
|
||||||
case NANDECC_PMECC:
|
case NANDECC_PMECC:
|
||||||
DEBUGASSERT(!spare);
|
DEBUGASSERT(!spare);
|
||||||
@ -1760,6 +1759,27 @@ static int nand_writepage(struct nand_raw_s *raw, off_t block,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nand_reset
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Resets a NAND FLASH device
|
||||||
|
*
|
||||||
|
* Input parameters:
|
||||||
|
* priv - Lower-half, private NAND FLASH device state
|
||||||
|
*
|
||||||
|
* Returned value.
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void nand_reset(struct sam_nandcs_s *priv)
|
||||||
|
{
|
||||||
|
fvdbg("Resetting\n");
|
||||||
|
nand_nfc_configure(priv, 0, COMMAND_RESET, 0, 0, 0);
|
||||||
|
nand_wait_ready(priv);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1790,6 +1810,7 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
uintptr_t cmdaddr;
|
uintptr_t cmdaddr;
|
||||||
uintptr_t addraddr;
|
uintptr_t addraddr;
|
||||||
uintptr_t dataaddr;
|
uintptr_t dataaddr;
|
||||||
|
uint8_t ecctype;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fvdbg("CS%d\n", cs);
|
fvdbg("CS%d\n", cs);
|
||||||
@ -1810,6 +1831,11 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
cmdaddr = BOARD_EBICS0_NAND_CMDADDR;
|
cmdaddr = BOARD_EBICS0_NAND_CMDADDR;
|
||||||
addraddr = BOARD_EBICS0_NAND_ADDRADDR;
|
addraddr = BOARD_EBICS0_NAND_ADDRADDR;
|
||||||
dataaddr = BOARD_EBICS0_NAND_DATAADDR;
|
dataaddr = BOARD_EBICS0_NAND_DATAADDR;
|
||||||
|
|
||||||
|
/* Pass on the configured ECC type */
|
||||||
|
|
||||||
|
ecctype = SAMA5_EBICS0_ECCTYPE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SAMA5_EBICS1_NAND
|
#ifdef CONFIG_SAMA5_EBICS1_NAND
|
||||||
@ -1826,6 +1852,10 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
cmdaddr = BOARD_EBICS1_NAND_CMDADDR;
|
cmdaddr = BOARD_EBICS1_NAND_CMDADDR;
|
||||||
addraddr = BOARD_EBICS1_NAND_ADDRADDR;
|
addraddr = BOARD_EBICS1_NAND_ADDRADDR;
|
||||||
dataaddr = BOARD_EBICS1_NAND_DATAADDR;
|
dataaddr = BOARD_EBICS1_NAND_DATAADDR;
|
||||||
|
|
||||||
|
/* Pass on the configured ECC type */
|
||||||
|
|
||||||
|
ecctype = SAMA5_EBICS1_ECCTYPE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -1843,6 +1873,10 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
cmdaddr = BOARD_EBICS2_NAND_CMDADDR;
|
cmdaddr = BOARD_EBICS2_NAND_CMDADDR;
|
||||||
addraddr = BOARD_EBICS2_NAND_ADDRADDR;
|
addraddr = BOARD_EBICS2_NAND_ADDRADDR;
|
||||||
dataaddr = BOARD_EBICS2_NAND_DATAADDR;
|
dataaddr = BOARD_EBICS2_NAND_DATAADDR;
|
||||||
|
|
||||||
|
/* Pass on the configured ECC type */
|
||||||
|
|
||||||
|
ecctype = SAMA5_EBICS2_ECCTYPE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -1860,6 +1894,10 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
cmdaddr = BOARD_EBICS3_NAND_CMDADDR;
|
cmdaddr = BOARD_EBICS3_NAND_CMDADDR;
|
||||||
addraddr = BOARD_EBICS3_NAND_ADDRADDR;
|
addraddr = BOARD_EBICS3_NAND_ADDRADDR;
|
||||||
dataaddr = BOARD_EBICS3_NAND_DATAADDR;
|
dataaddr = BOARD_EBICS3_NAND_DATAADDR;
|
||||||
|
|
||||||
|
/* Pass on the configured ECC type */
|
||||||
|
|
||||||
|
ecctype = SAMA5_EBICS3_ECCTYPE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -1874,6 +1912,7 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
priv->raw.cmdaddr = cmdaddr;
|
priv->raw.cmdaddr = cmdaddr;
|
||||||
priv->raw.addraddr = addraddr;
|
priv->raw.addraddr = addraddr;
|
||||||
priv->raw.dataaddr = dataaddr;
|
priv->raw.dataaddr = dataaddr;
|
||||||
|
priv->raw.ecctype = ecctype;
|
||||||
priv->raw.eraseblock = nand_eraseblock;
|
priv->raw.eraseblock = nand_eraseblock;
|
||||||
priv->raw.rawread = nand_rawread;
|
priv->raw.rawread = nand_rawread;
|
||||||
priv->raw.rawwrite = nand_rawwrite;
|
priv->raw.rawwrite = nand_rawwrite;
|
||||||
@ -1896,6 +1935,10 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset the NAND FLASH part */
|
||||||
|
|
||||||
|
nand_reset(priv);
|
||||||
|
|
||||||
/* Probe the NAND part. On success, an MTD interface that wraps
|
/* Probe the NAND part. On success, an MTD interface that wraps
|
||||||
* our raw NAND interface is returned.
|
* our raw NAND interface is returned.
|
||||||
*/
|
*/
|
||||||
@ -1929,9 +1972,18 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
|||||||
|
|
||||||
if (!g_nand.initialized)
|
if (!g_nand.initialized)
|
||||||
{
|
{
|
||||||
|
/* Enable the NAND FLASH Controller (The NFC is always used) */
|
||||||
|
|
||||||
nand_putreg(SAM_HSMC_CTRL, HSMC_CTRL_NFCEN);
|
nand_putreg(SAM_HSMC_CTRL, HSMC_CTRL_NFCEN);
|
||||||
|
|
||||||
#warning Missing logic
|
#ifndef NAND_HAVE_PMECC
|
||||||
|
/* Disable the PMECC if it is not being used */
|
||||||
|
|
||||||
|
nand_putreg(SAM_SMC_PMECCTRL, SMC_PMECCTRL_RST);
|
||||||
|
nand_putreg(SAM_SMC_PMECCTRL, SMC_PMECCTRL_DISABLE);
|
||||||
|
nand_putreg(SAM_SMC_PMECCFG, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
g_nand.initialized = true;
|
g_nand.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/mtd/nand_config.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -49,6 +50,7 @@
|
|||||||
|
|
||||||
#include <nuttx/mtd/nand_raw.h>
|
#include <nuttx/mtd/nand_raw.h>
|
||||||
|
|
||||||
|
#include "up_arch.h"
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
#include "chip/sam_hsmc.h"
|
#include "chip/sam_hsmc.h"
|
||||||
|
|
||||||
@ -58,39 +60,6 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/* Configuration ************************************************************/
|
/* 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
|
|
||||||
|
|
||||||
#ifndef CONFIG_SAMA5_DMAC1
|
#ifndef CONFIG_SAMA5_DMAC1
|
||||||
# warning CONFIG_SAMA5_DMAC1 should be enabled for DMA transfers
|
# warning CONFIG_SAMA5_DMAC1 should be enabled for DMA transfers
|
||||||
#endif
|
#endif
|
||||||
@ -100,12 +69,120 @@
|
|||||||
*
|
*
|
||||||
* NANDECC_CHIPECC ECC is performed internal to chip
|
* NANDECC_CHIPECC ECC is performed internal to chip
|
||||||
* NANDECC_PMECC Programmable Multibit Error Correcting Code (PMECC)
|
* NANDECC_PMECC Programmable Multibit Error Correcting Code (PMECC)
|
||||||
* NANDECC_HSIAO HSIAO ECC
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NANDECC_CHIPECC (NANDECC_HWECC + 0)
|
#define NANDECC_CHIPECC (NANDECC_HWECC + 0)
|
||||||
#define NANDECC_PMECC (NANDECC_HWECC + 1)
|
#define NANDECC_PMECC (NANDECC_HWECC + 1)
|
||||||
#define NANDECC_HSIAO (NANDECC_HWECC + 2)
|
|
||||||
|
/* Per NAND bank ECC selections */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SAMA5_EBICS0_NAND)
|
||||||
|
# if defined(CONFIG_SAMA5_EBICS0_ECCNONE)
|
||||||
|
# define SAMA5_EBICS0_ECCTYPE NANDECC_NONE
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS0_SWECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_SWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS0_SWECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS0_ECCTYPE NANDECC_SWECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS0_PMECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_HWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS0_PMECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS0_ECCTYPE NANDECC_PMECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS0_CHIPECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_EMBEDDEDECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS0_CHIPECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS0_ECCTYPE NANDECC_CHIPECC
|
||||||
|
|
||||||
|
# else
|
||||||
|
# error "No ECC type specified for CS0"
|
||||||
|
# endif
|
||||||
|
#endif /* CONFIG_SAMA5_EBICS0_NAND */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SAMA5_EBICS1_NAND)
|
||||||
|
# if defined(CONFIG_SAMA5_EBICS1_ECCNONE)
|
||||||
|
# define SAMA5_EBICS1_ECCTYPE NANDECC_NONE
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS1_SWECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_SWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS1_SWECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS1_ECCTYPE NANDECC_SWECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS1_PMECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_HWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS1_PMECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS1_ECCTYPE NANDECC_PMECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS1_CHIPECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_EMBEDDEDECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS1_CHIPECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS1_ECCTYPE NANDECC_CHIPECC
|
||||||
|
|
||||||
|
# else
|
||||||
|
# error "No ECC type specified for CS1"
|
||||||
|
# endif
|
||||||
|
#endif /* CONFIG_SAMA5_EBICS1_NAND */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SAMA5_EBICS2_NAND)
|
||||||
|
# if defined(CONFIG_SAMA5_EBICS2_ECCNONE)
|
||||||
|
# define SAMA5_EBICS2_ECCTYPE NANDECC_NONE
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS2_SWECC
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_SWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS2_SWECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS2_ECCTYPE NANDECC_SWECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS2_PMECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_HWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS2_PMECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS2_ECCTYPE NANDECC_PMECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS2_CHIPECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_EMBEDDEDECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS2_CHIPECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS2_ECCTYPE NANDECC_CHIPECC
|
||||||
|
|
||||||
|
# else
|
||||||
|
# error "No ECC type specified for CS2"
|
||||||
|
# endif
|
||||||
|
#endif /* CONFIG_SAMA5_EBICS2_NAND */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SAMA5_EBICS3_NAND)
|
||||||
|
# if defined(CONFIG_SAMA5_EBICS3_ECCNONE)
|
||||||
|
# define SAMA5_EBICS3_ECCTYPE NANDECC_NONE
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS3_SWECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_SWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS3_SWECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS3_ECCTYPE NANDECC_SWECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS3_PMECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_HWECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS3_PMECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS3_ECCTYPE NANDECC_PMECC
|
||||||
|
|
||||||
|
# elif defined(CONFIG_SAMA5_EBICS3_CHIPECC)
|
||||||
|
# if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_EMBEDDEDECC)
|
||||||
|
# error CONFIG_SAMA5_EBICS3_CHIPECC is an invalid selection
|
||||||
|
# endif
|
||||||
|
# define SAMA5_EBICS3_ECCTYPE NANDECC_CHIPECC
|
||||||
|
|
||||||
|
# else
|
||||||
|
# error "No ECC type specified for CS3"
|
||||||
|
# endif
|
||||||
|
#endif /* CONFIG_SAMA5_EBICS3_NAND */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
@ -122,9 +199,7 @@ struct sam_nandcs_s
|
|||||||
|
|
||||||
/* Static configuration */
|
/* Static configuration */
|
||||||
|
|
||||||
uint8_t cs :2; /* Chip select number (0..3) */
|
uint8_t cs; /* Chip select number (0..3) */
|
||||||
uint8_t nfcsram :1; /* True: Use NFC SRAM */
|
|
||||||
uint8_t dmaxfr :1; /* True: Use DMA transfers */
|
|
||||||
|
|
||||||
/* Dynamic state */
|
/* Dynamic state */
|
||||||
|
|
||||||
|
274
arch/arm/src/sama5/sam_pmecc.c
Normal file
274
arch/arm/src/sama5/sam_pmecc.c
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/sama5/sam_pmecc.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* References:
|
||||||
|
* SAMA5D3 Series Data Sheet
|
||||||
|
* Atmel NoOS sample code.
|
||||||
|
*
|
||||||
|
* The Atmel sample code has a BSD compatibile license that requires this
|
||||||
|
* copyright notice:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/mtd/nand_config.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "sam_pmecc.h"
|
||||||
|
#include "sam_nand.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define BCH_ERR2 0 /* 2 errors */
|
||||||
|
#define BCH_ERR4 1 /* 4 errors */
|
||||||
|
#define BCH_ERR8 2 /* 8 errors */
|
||||||
|
#define BCH_ERR12 3 /* 12 errors */
|
||||||
|
#define BCH_ERR24 4 /* 24 errors */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* PMECC state data */
|
||||||
|
|
||||||
|
struct sam_pmecc_s
|
||||||
|
{
|
||||||
|
uint8_t nsectors : 4; /* Number of sectors in data */
|
||||||
|
uint8_t bcherr : 3; /* BCH_ERR correctability code */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
/* PMECC state data */
|
||||||
|
|
||||||
|
static struct sam_pmecc_s g_pmecc;
|
||||||
|
|
||||||
|
/* Maps BCH_ERR correctability register value to number of errors per sector */
|
||||||
|
|
||||||
|
static const uint8_t g_correctability[5] = {2, 4, 8, 12, 24};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pmecc_bcherr512
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the correctabity that could be achieved using a 512 byte sector
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pmecc_bcherr512(uint8_t nsectors, uint16_t sparesize)
|
||||||
|
{
|
||||||
|
/* 39-bytes per 512 byte sector are required correctability of 24 errors */
|
||||||
|
|
||||||
|
if (sparesize <= 39 * ((unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR24;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 20-bytes per 512 byte sector are required correctability of 12 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (20 * (unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 13-bytes per 512 byte sector are required correctability of 8 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (13 * (unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7-bytes per 512 byte sector are required correctability of 4 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (7 *(unsigned int) nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4-bytes per 512 byte sector are required correctability of 2 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (4 *(unsigned int) nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pmecc_bcherr512
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the correctabity that could be achieved using a 512 byte sector
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pmecc_bcherr1k(uint8_t nsectors, uint16_t sparesize)
|
||||||
|
{
|
||||||
|
/* 42-bytes per 1024 byte sector are required correctability of 24 errors */
|
||||||
|
|
||||||
|
if (sparesize <= 42 * ((unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR24;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 21-bytes per 1024 byte sector are required correctability of 12 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (20 * (unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 14-bytes per 1024 byte sector are required correctability of 8 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (13 * (unsigned int)nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7-bytes per 1024 byte sector are required correctability of 4 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (7 *(unsigned int) nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4-bytes per 1024 byte sector are required correctability of 2 errors */
|
||||||
|
|
||||||
|
else if (sparesize <= (4 *(unsigned int) nsectors))
|
||||||
|
{
|
||||||
|
return BCH_ERR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pmecc_pagelayout
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Given the data size and the spare size, determine the optimal sector
|
||||||
|
* size and correctability.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void pmecc_pagelayout(uint16_t datasize, uint16_t sparesize,
|
||||||
|
uint16_t offset)
|
||||||
|
{
|
||||||
|
uint16_t correctability512;
|
||||||
|
uint16_t correctability1K;
|
||||||
|
uint8_t nsectors512;
|
||||||
|
uint8_t nsectors1k;
|
||||||
|
uint8_t bcherr512;
|
||||||
|
uint8_t bcherr1k;
|
||||||
|
|
||||||
|
/* Decrease the spare size by the offset */
|
||||||
|
|
||||||
|
sparesize -= offset;
|
||||||
|
|
||||||
|
/* Try for 512 byte sectors */
|
||||||
|
|
||||||
|
DEBUGASSERT((datasize & 0xfffffe00) == 0 && datasize >= 512);
|
||||||
|
|
||||||
|
nsectors512 = (datasize >> 9);
|
||||||
|
bcherr512 = pmecc_bcherr512(nsectors512, sparesize);
|
||||||
|
|
||||||
|
/* Try for 1024 byte sectors */
|
||||||
|
|
||||||
|
if ((datasize & 0xfffffc00) == 0)
|
||||||
|
{
|
||||||
|
nsectors1k = (datasize >> 9);
|
||||||
|
bcherr1k = pmecc_bcherr1k(nsectors1k, sparesize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nsectors1k = 0;
|
||||||
|
bcherr1k = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now pick the best (most likely 1024) */
|
||||||
|
|
||||||
|
DEBUGASSERT(bcherr512 > 0 || bcherr1k > 0);
|
||||||
|
if (bcherr1k == 0)
|
||||||
|
{
|
||||||
|
g_pmecc.nsectors = nsectors512;
|
||||||
|
g_pmecc.bcherr = bcherr512;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
correctability512 = nsectors512 * g_correctability[bcherr512];
|
||||||
|
correctability1K = nsectors1k * g_correctability[bcherr1k];
|
||||||
|
if (correctability512 >= correctability1K)
|
||||||
|
{
|
||||||
|
g_pmecc.nsectors = nsectors512;
|
||||||
|
g_pmecc.bcherr = bcherr512;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pmecc.nsectors = nsectors1k;
|
||||||
|
g_pmecc.bcherr = bcherr1k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pmecc_configure
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure the PMECC for use by this CS
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
@ -55,7 +55,7 @@
|
|||||||
/* Configuration ************************************************************/
|
/* Configuration ************************************************************/
|
||||||
/* Block checking and H/W ECC support must be enabled for PMECC */
|
/* Block checking and H/W ECC support must be enabled for PMECC */
|
||||||
|
|
||||||
#if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(MTD_NAND_HWECC)
|
#if !defined(CONFIG_MTD_NAND_BLOCKCHECK) || !defined(CONFIG_MTD_NAND_HWECC)
|
||||||
# undef CONFIG_SAMA5_EBICS0_PMECC
|
# undef CONFIG_SAMA5_EBICS0_PMECC
|
||||||
# undef CONFIG_SAMA5_EBICS1_PMECC
|
# undef CONFIG_SAMA5_EBICS1_PMECC
|
||||||
# undef CONFIG_SAMA5_EBICS2_PMECC
|
# undef CONFIG_SAMA5_EBICS2_PMECC
|
||||||
@ -64,19 +64,19 @@
|
|||||||
|
|
||||||
/* Disable PMECC support for any banks not enabled or configured for NAND */
|
/* Disable PMECC support for any banks not enabled or configured for NAND */
|
||||||
|
|
||||||
#if !defined(SAMA5_EBICS0) || !defined(SAMA5_EBICS0_NAND)
|
#if !defined(CONFIG_SAMA5_EBICS0) || !defined(CONFIG_SAMA5_EBICS0_NAND)
|
||||||
# undef CONFIG_SAMA5_EBICS0_PMECC
|
# undef CONFIG_SAMA5_EBICS0_PMECC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(SAMA5_EBICS1) || !defined(SAMA5_EBICS1_NAND)
|
#if !defined(CONFIG_SAMA5_EBICS1) || !defined(CONFIG_SAMA5_EBICS1_NAND)
|
||||||
# undef CONFIG_SAMA5_EBICS1_PMECC
|
# undef CONFIG_SAMA5_EBICS1_PMECC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(SAMA5_EBICS2) || !defined(SAMA5_EBICS2_NAND)
|
#if !defined(CONFIG_SAMA5_EBICS2) || !defined(CONFIG_SAMA5_EBICS2_NAND)
|
||||||
# undef CONFIG_SAMA5_EBICS2_PMECC
|
# undef CONFIG_SAMA5_EBICS2_PMECC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(SAMA5_EBICS3) || !defined(SAMA5_EBICS3_NAND)
|
#if !defined(CONFIG_SAMA5_EBICS3) || !defined(CONFIG_SAMA5_EBICS3_NAND)
|
||||||
# undef CONFIG_SAMA5_EBICS3_PMECC
|
# undef CONFIG_SAMA5_EBICS3_PMECC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -88,40 +88,40 @@
|
|||||||
#ifdef CONFIG_SAMA5_EBICS0_PMECC
|
#ifdef CONFIG_SAMA5_EBICS0_PMECC
|
||||||
# undef NAND_HAVE_PMECC
|
# undef NAND_HAVE_PMECC
|
||||||
# define NAND_HAVE_PMECC 1
|
# define NAND_HAVE_PMECC 1
|
||||||
# define NAND_HAVE_EBIS0_PMECC 1
|
# define NAND_HAVE_EBICS0_PMECC 1
|
||||||
#else
|
#else
|
||||||
# define NAND_HAVE_EBIS0_PMECC 0
|
# define NAND_HAVE_EBICS0_PMECC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_EBICS1_PMECC
|
#ifdef CONFIG_SAMA5_EBICS1_PMECC
|
||||||
# undef NAND_HAVE_PMECC
|
# undef NAND_HAVE_PMECC
|
||||||
# define NAND_HAVE_PMECC 1
|
# define NAND_HAVE_PMECC 1
|
||||||
# define NAND_HAVE_EBIS1_PMECC 1
|
# define NAND_HAVE_EBICS1_PMECC 1
|
||||||
#else
|
#else
|
||||||
# define NAND_HAVE_EBIS1_PMECC 0
|
# define NAND_HAVE_EBICS1_PMECC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_EBICS2_PMECC
|
#ifdef CONFIG_SAMA5_EBICS2_PMECC
|
||||||
# undef NAND_HAVE_PMECC
|
# undef NAND_HAVE_PMECC
|
||||||
# define NAND_HAVE_PMECC 1
|
# define NAND_HAVE_PMECC 1
|
||||||
# define NAND_HAVE_EBIS2_PMECC 1
|
# define NAND_HAVE_EBICS2_PMECC 1
|
||||||
#else
|
#else
|
||||||
# define NAND_HAVE_EBIS2_PMECC 0
|
# define NAND_HAVE_EBICS2_PMECC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_EBICS3_PMECC
|
#ifdef CONFIG_SAMA5_EBICS3_PMECC
|
||||||
# undef NAND_HAVE_PMECC
|
# undef NAND_HAVE_PMECC
|
||||||
# define NAND_HAVE_PMECC 1
|
# define NAND_HAVE_PMECC 1
|
||||||
# define NAND_HAVE_EBIS3_PMECC 1
|
# define NAND_HAVE_EBICS3_PMECC 1
|
||||||
#else
|
#else
|
||||||
# define NAND_HAVE_EBIS3_PMECC 0
|
# define NAND_HAVE_EBICS3_PMECC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Count the number of banks using PMECC */
|
/* Count the number of banks using PMECC */
|
||||||
|
|
||||||
#define NAND_NPMECC_BANKS \
|
#define NAND_NPMECC_BANKS \
|
||||||
(NAND_HAVE_EBIS0_PMECC + NAND_HAVE_EBIS1_PMECC + \
|
(NAND_HAVE_EBICS0_PMECC + NAND_HAVE_EBICS1_PMECC + \
|
||||||
NAND_HAVE_EBIS2_PMECC + NAND_HAVE_EBIS3_PMECC
|
NAND_HAVE_EBICS2_PMECC + NAND_HAVE_EBICS3_PMECC)
|
||||||
|
|
||||||
/* Compile this logic only if there is at least one CS configure for NAND
|
/* Compile this logic only if there is at least one CS configure for NAND
|
||||||
* and with PMECC support enabled.
|
* and with PMECC support enabled.
|
||||||
|
Loading…
Reference in New Issue
Block a user