SAMA5 NAND: Fix some PMECC setup logic
This commit is contained in:
parent
9632d2a7f6
commit
8a97561ceb
@ -1739,9 +1739,7 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
|
|
||||||
/* Start a Data Phase */
|
/* Start a Data Phase */
|
||||||
|
|
||||||
regval = nand_getreg(SAM_HSMC_PMECCTRL);
|
nand_putreg(SAM_HSMC_PMECCTRL, HSMC_PMECCTRL_DATA);
|
||||||
regval |= HSMC_PMECCTRL_DATA;
|
|
||||||
nand_putreg(SAM_HSMC_PMECCTRL, regval);
|
|
||||||
|
|
||||||
regval = nand_getreg(SAM_HSMC_PMECCEADDR);
|
regval = nand_getreg(SAM_HSMC_PMECCEADDR);
|
||||||
ret = nand_read(priv, true, (uint8_t *)data, pagesize + (regval + 1));
|
ret = nand_read(priv, true, (uint8_t *)data, pagesize + (regval + 1));
|
||||||
@ -2088,6 +2086,7 @@ static int nand_readpage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
fvdbg("block=%d page=%d data=%p\n", (int)block, page, data);
|
||||||
DEBUGASSERT(priv && data);
|
DEBUGASSERT(priv && data);
|
||||||
|
|
||||||
/* Make sure that we have exclusive access to the PMECC and that the PMECC
|
/* Make sure that we have exclusive access to the PMECC and that the PMECC
|
||||||
@ -2095,7 +2094,12 @@ static int nand_readpage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
pmecc_lock();
|
pmecc_lock();
|
||||||
pmecc_configure(priv, 0, false);
|
ret = pmecc_configure(priv, false);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: pmecc_configure failed: %d\n", ret);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Start by reading the spare data */
|
/* Start by reading the spare data */
|
||||||
|
|
||||||
@ -2340,13 +2344,19 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
fvdbg("block=%d page=%d data=%p\n", (int)block, page, data);
|
fvdbg("block=%d page=%d data=%p\n", (int)block, page, data);
|
||||||
|
DEBUGASSERT(priv && data);
|
||||||
|
|
||||||
/* Make sure that we have exclusive access to the PMECC and that the PMECC
|
/* Make sure that we have exclusive access to the PMECC and that the PMECC
|
||||||
* is properly configured for this CS.
|
* is properly configured for this CS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pmecc_lock();
|
pmecc_lock();
|
||||||
pmecc_configure(priv, 0, false);
|
ret = pmecc_configure(priv, false);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: pmecc_configure failed: %d\n", ret);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the start page address */
|
/* Calculate the start page address */
|
||||||
|
|
||||||
@ -2409,9 +2419,7 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
|
|||||||
|
|
||||||
/* Start a data phase */
|
/* Start a data phase */
|
||||||
|
|
||||||
regval = nand_getreg(SAM_HSMC_PMECCTRL);
|
nand_putreg(SAM_HSMC_PMECCTRL, HSMC_PMECCTRL_DATA);
|
||||||
regval |= HSMC_PMECCTRL_DATA;
|
|
||||||
nand_putreg(SAM_HSMC_PMECCTRL, regval);
|
|
||||||
|
|
||||||
regval = nand_getreg(SAM_HSMC_PMECCFG);
|
regval = nand_getreg(SAM_HSMC_PMECCFG);
|
||||||
regval |= HSMC_PMECCFG_NANDWR_WRITE;
|
regval |= HSMC_PMECCFG_NANDWR_WRITE;
|
||||||
|
@ -57,6 +57,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <nuttx/mtd/nand_model.h>
|
||||||
|
#include <nuttx/mtd/nand_scheme.h>
|
||||||
|
|
||||||
#include "sam_pmecc.h"
|
#include "sam_pmecc.h"
|
||||||
#include "sam_nand.h"
|
#include "sam_nand.h"
|
||||||
|
|
||||||
@ -83,12 +86,6 @@
|
|||||||
|
|
||||||
#define PMECC_MAX_CORRECTABILITY 25
|
#define PMECC_MAX_CORRECTABILITY 25
|
||||||
|
|
||||||
/* Start address of ECC cvalue in spare zone, this must not be 0 since bad
|
|
||||||
* block tags are at address 0.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PMECC_ECC_DEFAULT_STARTOFFSET 2
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -753,44 +750,44 @@ static uint32_t pmecc_correctionalgo(uint32_t isr, uint32_t data)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int pmecc_bcherr512(uint8_t nsectors, uint16_t sparesize)
|
static int pmecc_bcherr512(uint8_t nsectors, uint16_t eccsize)
|
||||||
{
|
{
|
||||||
/* 39-bytes per 512 byte sector are required correctability of 24 errors */
|
/* 39-bytes per 512 byte sector are required correctability of 24 errors */
|
||||||
|
|
||||||
if (sparesize <= 39 * ((unsigned int)nsectors))
|
if (eccsize >= 39 * ((unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR24;
|
return BCH_ERR24;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 20-bytes per 512 byte sector are required correctability of 12 errors */
|
/* 20-bytes per 512 byte sector are required correctability of 12 errors */
|
||||||
|
|
||||||
else if (sparesize <= (20 * (unsigned int)nsectors))
|
else if (eccsize >= (20 * (unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR12;
|
return BCH_ERR12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 13-bytes per 512 byte sector are required correctability of 8 errors */
|
/* 13-bytes per 512 byte sector are required correctability of 8 errors */
|
||||||
|
|
||||||
else if (sparesize <= (13 * (unsigned int)nsectors))
|
else if (eccsize >= (13 * (unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR8;
|
return BCH_ERR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7-bytes per 512 byte sector are required correctability of 4 errors */
|
/* 7-bytes per 512 byte sector are required correctability of 4 errors */
|
||||||
|
|
||||||
else if (sparesize <= (7 *(unsigned int) nsectors))
|
else if (eccsize >= (7 *(unsigned int) nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR4;
|
return BCH_ERR4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4-bytes per 512 byte sector are required correctability of 2 errors */
|
/* 4-bytes per 512 byte sector are required correctability of 2 errors */
|
||||||
|
|
||||||
else if (sparesize <= (4 *(unsigned int) nsectors))
|
else if (eccsize >= (4 *(unsigned int) nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR2;
|
return BCH_ERR2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -801,123 +798,156 @@ static int pmecc_bcherr512(uint8_t nsectors, uint16_t sparesize)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int pmecc_bcherr1k(uint8_t nsectors, uint16_t sparesize)
|
static int pmecc_bcherr1k(uint8_t nsectors, uint16_t eccsize)
|
||||||
{
|
{
|
||||||
/* 42-bytes per 1024 byte sector are required correctability of 24 errors */
|
/* 42-bytes per 1024 byte sector are required correctability of 24 errors */
|
||||||
|
|
||||||
if (sparesize <= 42 * ((unsigned int)nsectors))
|
if (eccsize >= 42 * ((unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR24;
|
return BCH_ERR24;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 21-bytes per 1024 byte sector are required correctability of 12 errors */
|
/* 21-bytes per 1024 byte sector are required correctability of 12 errors */
|
||||||
|
|
||||||
else if (sparesize <= (20 * (unsigned int)nsectors))
|
else if (eccsize >= (21 * (unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR12;
|
return BCH_ERR12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 14-bytes per 1024 byte sector are required correctability of 8 errors */
|
/* 14-bytes per 1024 byte sector are required correctability of 8 errors */
|
||||||
|
|
||||||
else if (sparesize <= (13 * (unsigned int)nsectors))
|
else if (eccsize >= (14 * (unsigned int)nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR8;
|
return BCH_ERR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7-bytes per 1024 byte sector are required correctability of 4 errors */
|
/* 7-bytes per 1024 byte sector are required correctability of 4 errors */
|
||||||
|
|
||||||
else if (sparesize <= (7 *(unsigned int) nsectors))
|
else if (eccsize >= (7 *(unsigned int) nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR4;
|
return BCH_ERR4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4-bytes per 1024 byte sector are required correctability of 2 errors */
|
/* 4-bytes per 1024 byte sector are required correctability of 2 errors */
|
||||||
|
|
||||||
else if (sparesize <= (4 *(unsigned int) nsectors))
|
else if (eccsize >= (4 *(unsigned int) nsectors))
|
||||||
{
|
{
|
||||||
return BCH_ERR2;
|
return BCH_ERR2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pmecc_pagelayout
|
* Name: pmecc_pagelayout
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Given the data size and the spare size, determine the optimal sector
|
* Given the size of the data region and the size of the ECC region,
|
||||||
* size and correctability.
|
* determine the optimal sector size and correctability.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void pmecc_pagelayout(uint16_t datasize, uint16_t sparesize,
|
static int pmecc_pagelayout(uint16_t datasize, uint16_t eccsize)
|
||||||
uint16_t offset)
|
|
||||||
{
|
{
|
||||||
uint16_t correctability512;
|
uint16_t correctability512;
|
||||||
uint16_t correctability1K;
|
uint16_t correctability1K;
|
||||||
uint8_t nsectors512;
|
uint8_t nsectors512;
|
||||||
uint8_t nsectors1k;
|
uint8_t nsectors1k;
|
||||||
uint8_t bcherr512;
|
|
||||||
uint8_t bcherr1k;
|
|
||||||
uint8_t bcherr;
|
uint8_t bcherr;
|
||||||
|
int bcherr512;
|
||||||
|
int bcherr1k;
|
||||||
|
int selector;
|
||||||
|
|
||||||
fvdbg("datasize=%d sparesize=%d offset=%d\n", datasize, sparesize, offset);
|
fvdbg("datasize=%d eccsize=%d\n", datasize, eccsize);
|
||||||
|
DEBUGASSERT(datasize > 0 && eccsize > 0);
|
||||||
/* ECC must not start at address zero, since bad block tags are at offset
|
|
||||||
* zero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEBUGASSERT(datasize != 0 && offset > 0);
|
|
||||||
|
|
||||||
/* Decrease the spare size by the offset */
|
|
||||||
|
|
||||||
sparesize -= offset;
|
|
||||||
|
|
||||||
/* Try for 512 byte sectors */
|
/* Try for 512 byte sectors */
|
||||||
|
|
||||||
DEBUGASSERT((datasize & 0x000001ff) == 0 && datasize >= 512);
|
DEBUGASSERT((datasize & 0x000001ff) == 0 && datasize >= 512);
|
||||||
|
|
||||||
|
selector = 0;
|
||||||
nsectors512 = (datasize >> 9);
|
nsectors512 = (datasize >> 9);
|
||||||
bcherr512 = pmecc_bcherr512(nsectors512, sparesize);
|
bcherr512 = pmecc_bcherr512(nsectors512, eccsize);
|
||||||
|
if (bcherr512 < 0)
|
||||||
|
{
|
||||||
|
fdbg("WARNING: Cannot realize 512B sectors\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selector = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fvdbg("nsectors512=%d bcherr512=%d selector=%d\n",
|
||||||
|
nsectors512, bcherr512, selector);
|
||||||
|
|
||||||
/* Try for 1024 byte sectors */
|
/* Try for 1024 byte sectors */
|
||||||
|
|
||||||
if ((datasize & 0x000003ff) == 0)
|
if ((datasize & 0x000003ff) == 0)
|
||||||
{
|
{
|
||||||
nsectors1k = (datasize >> 9);
|
nsectors1k = (datasize >> 10);
|
||||||
bcherr1k = pmecc_bcherr1k(nsectors1k, sparesize);
|
bcherr1k = pmecc_bcherr1k(nsectors1k, eccsize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nsectors1k = 0;
|
nsectors1k = 0;
|
||||||
bcherr1k = 0;
|
bcherr1k = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bcherr1k < 0)
|
||||||
|
{
|
||||||
|
fdbg("WARNING: Cannot realize 1KB sectors\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selector |= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fvdbg("nsectors1k=%d bcherr1k=%d selector=%d\n",
|
||||||
|
nsectors1k, bcherr1k, selector);
|
||||||
|
|
||||||
/* Now pick the best (most likely 1024) */
|
/* Now pick the best (most likely 1024) */
|
||||||
|
|
||||||
DEBUGASSERT(bcherr512 > 0 || bcherr1k > 0);
|
DEBUGASSERT(bcherr512 >= 0 || bcherr1k >= 0);
|
||||||
if (bcherr1k == 0)
|
switch (selector)
|
||||||
|
{
|
||||||
|
case 1: /* 512B sectors possible; 1KB sectors not possible */
|
||||||
{
|
{
|
||||||
g_pmecc.sector1k = false;
|
g_pmecc.sector1k = false;
|
||||||
g_pmecc.nsectors = nsectors512;
|
g_pmecc.nsectors = nsectors512;
|
||||||
bcherr = bcherr512;
|
bcherr = bcherr512;
|
||||||
|
DEBUGASSERT(bcherr512 >= 0);
|
||||||
}
|
}
|
||||||
else
|
break;
|
||||||
|
|
||||||
|
case 3: /* Both 512B and 1KB sectors possible */
|
||||||
{
|
{
|
||||||
correctability512 = nsectors512 * g_correctability[bcherr512];
|
correctability512 = nsectors512 * g_correctability[bcherr512];
|
||||||
correctability1K = nsectors1k * g_correctability[bcherr1k];
|
correctability1K = nsectors1k * g_correctability[bcherr1k];
|
||||||
if (correctability512 >= correctability1K)
|
|
||||||
|
/* Use 1K sectors unless we can do better with 512B sectors */
|
||||||
|
|
||||||
|
if (correctability512 > correctability1K)
|
||||||
{
|
{
|
||||||
g_pmecc.sector1k = false;
|
g_pmecc.sector1k = false;
|
||||||
g_pmecc.nsectors = nsectors512;
|
g_pmecc.nsectors = nsectors512;
|
||||||
bcherr = bcherr512;
|
bcherr = bcherr512;
|
||||||
|
DEBUGASSERT(bcherr512 >= 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
} /* Otherwise, fall through for the 1KB sectors */
|
||||||
|
|
||||||
|
case 2: /* 512B sectors not possible; 1KB sectors possible */
|
||||||
{
|
{
|
||||||
g_pmecc.sector1k = true;
|
g_pmecc.sector1k = true;
|
||||||
g_pmecc.nsectors = nsectors1k;
|
g_pmecc.nsectors = nsectors1k;
|
||||||
bcherr = bcherr1k;
|
bcherr = bcherr1k;
|
||||||
|
DEBUGASSERT(bcherr1k >= 0);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0: /* Either 512B and 1KB sectors possible */
|
||||||
|
default:
|
||||||
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the correctability value */
|
/* Save the correctability value */
|
||||||
@ -927,6 +957,11 @@ static void pmecc_pagelayout(uint16_t datasize, uint16_t sparesize,
|
|||||||
/* And the correctly shifted BCH_ERR register value */
|
/* And the correctly shifted BCH_ERR register value */
|
||||||
|
|
||||||
g_pmecc.desc.bcherr = ((uint32_t)bcherr << HSMC_PMECCFG_BCHERR_SHIFT);
|
g_pmecc.desc.bcherr = ((uint32_t)bcherr << HSMC_PMECCFG_BCHERR_SHIFT);
|
||||||
|
|
||||||
|
fvdbg("sector1k=%d nsectors=%d bcherr=%d correctability=%d\n",
|
||||||
|
g_pmecc.sector1k, g_pmecc.nsectors, bcherr, g_pmecc.correctability);
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -963,7 +998,6 @@ void pmecc_initialize(void)
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* priv - Pointer to a struct sam_nandcs_s instance.
|
* priv - Pointer to a struct sam_nandcs_s instance.
|
||||||
* eccoffset - offset of the first ecc byte in spare zone.
|
|
||||||
* protected - True: The spare area is protected with the last sector of
|
* protected - True: The spare area is protected with the last sector of
|
||||||
* data.
|
* data.
|
||||||
* False: The spare area is skipped in read or write mode.
|
* False: The spare area is skipped in read or write mode.
|
||||||
@ -973,11 +1007,16 @@ void pmecc_initialize(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
int pmecc_configure(struct sam_nandcs_s *priv, bool protected)
|
||||||
bool protected)
|
|
||||||
{
|
{
|
||||||
|
struct nand_model_s *model;
|
||||||
unsigned int sectorsperpage = 0;
|
unsigned int sectorsperpage = 0;
|
||||||
|
uint16_t eccoffset;
|
||||||
|
uint16_t eccsize;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
fvdbg("protected=%d configured=%d\n", protected, g_pmecc.configured);
|
||||||
|
|
||||||
/* Check if we need to re-configure */
|
/* Check if we need to re-configure */
|
||||||
|
|
||||||
@ -989,19 +1028,21 @@ int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
|||||||
{
|
{
|
||||||
/* No, we are already configured */
|
/* No, we are already configured */
|
||||||
|
|
||||||
|
fvdbg("Already configured\n");
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure that the requested offset greater than or equal to the
|
/* Get a convenience pointer to the NAND model */
|
||||||
* minimum. The first few bytes of the spare ares is reserved for
|
|
||||||
* bad block indications. Therefore, ECC data must begin at an offset
|
model = &priv->raw.model;
|
||||||
* to skip over the bad block indicators.
|
|
||||||
|
/* Get the offset and size of the ECC information in the spare area from
|
||||||
|
* the NAND scheme.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (eccoffset < PMECC_ECC_DEFAULT_STARTOFFSET)
|
DEBUGASSERT(model->scheme);
|
||||||
{
|
eccoffset = nandscheme_eccoffset(model->scheme);
|
||||||
eccoffset = PMECC_ECC_DEFAULT_STARTOFFSET;
|
eccsize = nandscheme_eccsize(model->scheme);
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the number of sectors and the error correction per sector. This
|
/* Get the number of sectors and the error correction per sector. This
|
||||||
* function will set the following structure values in order to get the
|
* function will set the following structure values in order to get the
|
||||||
@ -1013,7 +1054,12 @@ int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
|||||||
* g_pmecc.desc.bcherr : The BCH_ERR value for the PMECC CFG register
|
* g_pmecc.desc.bcherr : The BCH_ERR value for the PMECC CFG register
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pmecc_pagelayout(priv->raw.model.pagesize, priv->raw.model.sparesize, eccoffset);
|
ret = pmecc_pagelayout(priv->raw.model.pagesize, eccsize);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: pmecc_pagelayout failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Number of Sectors in one Page */
|
/* Number of Sectors in one Page */
|
||||||
|
|
||||||
@ -1048,6 +1094,9 @@ int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fvdbg("sectorsz=%08x sectorsperpage=%d mm=%d\n",
|
||||||
|
g_pmecc.desc.sectorsz, sectorsperpage, g_pmecc.desc.mm);
|
||||||
|
|
||||||
switch (sectorsperpage)
|
switch (sectorsperpage)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -1069,22 +1118,37 @@ int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
|||||||
|
|
||||||
g_pmecc.desc.nn = (1 << g_pmecc.desc.mm) - 1;
|
g_pmecc.desc.nn = (1 << g_pmecc.desc.mm) - 1;
|
||||||
|
|
||||||
|
fvdbg("pagesize=%08x nn=%d\n", g_pmecc.desc.pagesize, g_pmecc.desc.nn);
|
||||||
|
|
||||||
/* Real value of ECC bit number correction (2, 4, 8, 12, 24) */
|
/* Real value of ECC bit number correction (2, 4, 8, 12, 24) */
|
||||||
|
|
||||||
g_pmecc.desc.tt = g_pmecc.correctability;
|
g_pmecc.desc.tt = g_pmecc.correctability;
|
||||||
if (((g_pmecc.desc.mm * g_pmecc.correctability) % 8) == 0)
|
if (((g_pmecc.desc.mm * g_pmecc.correctability) & 7) == 0)
|
||||||
{
|
{
|
||||||
g_pmecc.desc.eccsize = ((g_pmecc.desc.mm * g_pmecc.correctability) / 8) * sectorsperpage;
|
g_pmecc.desc.eccsize =
|
||||||
|
((g_pmecc.desc.mm * g_pmecc.correctability) >> 3) * sectorsperpage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_pmecc.desc.eccsize = (((g_pmecc.desc.mm * g_pmecc.correctability) / 8) + 1) * sectorsperpage;
|
g_pmecc.desc.eccsize =
|
||||||
|
(((g_pmecc.desc.mm * g_pmecc.correctability) >> 3) + 1) * sectorsperpage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fvdbg("mm=%d correctability=%d eccsize=%d\n",
|
||||||
|
g_pmecc.desc.mm, g_pmecc.correctability, g_pmecc.desc.eccsize);
|
||||||
|
|
||||||
g_pmecc.desc.eccstart = eccoffset;
|
g_pmecc.desc.eccstart = eccoffset;
|
||||||
g_pmecc.desc.eccend = eccoffset + g_pmecc.desc.eccsize;
|
g_pmecc.desc.eccend = eccoffset + g_pmecc.desc.eccsize;
|
||||||
|
|
||||||
|
fvdbg("eccstart=%d eccend=%d sparesize=%d\n",
|
||||||
|
g_pmecc.desc.eccstart, g_pmecc.desc.eccend,
|
||||||
|
priv->raw.model.sparesize);
|
||||||
|
|
||||||
if (g_pmecc.desc.eccend > priv->raw.model.sparesize)
|
if (g_pmecc.desc.eccend > priv->raw.model.sparesize)
|
||||||
{
|
{
|
||||||
|
fdbg("ERROR: No room for ECC in spare bytes %d > %d\n",
|
||||||
|
g_pmecc.desc.eccend, priv->raw.model.sparesize);
|
||||||
|
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,7 +1208,7 @@ int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
|||||||
#if NAND_NPMECC_BANKS > 1
|
#if NAND_NPMECC_BANKS > 1
|
||||||
g_pmecc.cs = priv->cs;
|
g_pmecc.cs = priv->cs;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -65,6 +65,16 @@
|
|||||||
# undef CONFIG_SAMA5_EBICS3_PMECC
|
# undef CONFIG_SAMA5_EBICS3_PMECC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Only CS3 can support NAND. The rest of what follows is a fantasy */
|
||||||
|
|
||||||
|
# undef CONFIG_SAMA5_EBICS0_NAND
|
||||||
|
# undef CONFIG_SAMA5_EBICS1_NAND
|
||||||
|
# undef CONFIG_SAMA5_EBICS2_NAND
|
||||||
|
|
||||||
|
# undef CONFIG_SAMA5_EBICS0_PMECC
|
||||||
|
# undef CONFIG_SAMA5_EBICS1_PMECC
|
||||||
|
# undef CONFIG_SAMA5_EBICS2_PMECC
|
||||||
|
|
||||||
/* 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(CONFIG_SAMA5_EBICS0) || !defined(CONFIG_SAMA5_EBICS0_NAND)
|
#if !defined(CONFIG_SAMA5_EBICS0) || !defined(CONFIG_SAMA5_EBICS0_NAND)
|
||||||
@ -310,7 +320,6 @@ void pmecc_initialize(void);
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* priv - Pointer to a struct sam_nandcs_s instance.
|
* priv - Pointer to a struct sam_nandcs_s instance.
|
||||||
* eccoffset - offset of the first ecc byte in spare zone.
|
|
||||||
* protected - True: The spare area is protected with the last sector of
|
* protected - True: The spare area is protected with the last sector of
|
||||||
* data.
|
* data.
|
||||||
* False: The spare area is skipped in read or write mode.
|
* False: The spare area is skipped in read or write mode.
|
||||||
@ -321,8 +330,7 @@ void pmecc_initialize(void);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct sam_nandcs_s;
|
struct sam_nandcs_s;
|
||||||
int pmecc_configure(struct sam_nandcs_s *priv, uint16_t eccoffset,
|
int pmecc_configure(struct sam_nandcs_s *priv, bool protected);
|
||||||
bool protected);
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pmecc_correction
|
* Name: pmecc_correction
|
||||||
@ -405,7 +413,7 @@ void pmecc_buildgf(uint32_t mm, int16_t* indexof, int16_t* alphato);
|
|||||||
# define pmecc_enable()
|
# define pmecc_enable()
|
||||||
# define pmecc_disable()
|
# define pmecc_disable()
|
||||||
# define pmecc_initialize()
|
# define pmecc_initialize()
|
||||||
# define pmecc_configure(a,b,c) (0)
|
# define pmecc_configure(a,b) (0)
|
||||||
# define pmecc_get_eccsize() (0)
|
# define pmecc_get_eccsize() (0)
|
||||||
# define pmecc_get_pagesize() (0)
|
# define pmecc_get_pagesize() (0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user