SAMA5 NAND: Fix a few race conditions
This commit is contained in:
parent
45a4eba015
commit
2be17cd41f
@ -678,10 +678,12 @@ static void nand_setup_cmddone(struct sam_nandcs_s *priv)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Clear all pending interrupts */
|
||||
/* Clear all pending interrupts. This must be done with interrupts
|
||||
* enabled or we could lose interrupts.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
nand_getreg(SAM_HSMC_SR);
|
||||
flags = irqsave();
|
||||
|
||||
/* Mark CMDDONE not received */
|
||||
|
||||
@ -749,10 +751,12 @@ static void nand_setup_xfrdone(struct sam_nandcs_s *priv)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Clear all pending interrupts */
|
||||
/* Clear all pending interrupts. This must be done with interrupts
|
||||
* enabled or we could lose interrupts.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
nand_getreg(SAM_HSMC_SR);
|
||||
flags = irqsave();
|
||||
|
||||
/* Mark XFRDONE not received */
|
||||
|
||||
@ -820,10 +824,12 @@ static void nand_setup_rbedge(struct sam_nandcs_s *priv)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Clear all pending interrupts */
|
||||
/* Clear all pending interrupts. This must be done with interrupts
|
||||
* enabled or we could lose interrupts.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
nand_getreg(SAM_HSMC_SR);
|
||||
flags = irqsave();
|
||||
|
||||
/* Mark RBEDGE0 not received */
|
||||
|
||||
@ -915,6 +921,7 @@ static int nand_wait_dma(struct sam_nandcs_s *priv)
|
||||
}
|
||||
}
|
||||
|
||||
fvdbg("Awakened: result=%d\n", priv->result);
|
||||
priv->dmadone = false;
|
||||
return priv->result;
|
||||
}
|
||||
@ -967,6 +974,9 @@ static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
|
||||
DEBUGASSERT(priv->dma);
|
||||
|
||||
fvdbg("vsrc=%08x vdest=%08x nbytes=%d\n",
|
||||
(int)vsrc, (int)vdest, (int)nbytes);
|
||||
|
||||
/* Invalidate the destination memory buffer before performing the DMA (so
|
||||
* that nothing gets flushed later, corrupting the DMA transfer, and so
|
||||
* that memory will be re-cached after the DMA completes).
|
||||
@ -1254,7 +1264,7 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||
unsigned int page, void *data)
|
||||
{
|
||||
uint32_t rawaddr;
|
||||
uint32_t rowaddr;
|
||||
uint32_t regval;
|
||||
uint16_t pagesize;
|
||||
uint16_t sparesize;
|
||||
@ -1305,7 +1315,7 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||
|
||||
/* Calculate actual address of the page */
|
||||
|
||||
rawaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
|
||||
rowaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
|
||||
|
||||
/* Reset and enable the PMECC */
|
||||
|
||||
@ -1323,7 +1333,7 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
|
||||
|
||||
nand_nfc_configure(priv,
|
||||
HSMC_ALE_COL_EN | HSMC_ALE_ROW_EN | HSMC_CLE_VCMD2_EN | HSMC_CLE_DATA_EN,
|
||||
COMMAND_READ_1, COMMAND_READ_2, 0, rawaddr);
|
||||
COMMAND_READ_1, COMMAND_READ_2, 0, rowaddr);
|
||||
|
||||
/* Reset the ECC module*/
|
||||
|
||||
|
@ -200,13 +200,14 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block)
|
||||
ret = NAND_RAWREAD(raw, block, 0, 0, spare);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: Cannot read page #0 of block #%d\n", block);
|
||||
fdbg("ERROR: Failed to read page 0 of block %d\n", block);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nandscheme_readbadblockmarker(scheme, spare, &marker);
|
||||
if (marker != 0xff)
|
||||
{
|
||||
fvdbg("Page 0 block %d marker=%02x\n", block, marker);
|
||||
return BADBLOCK;
|
||||
}
|
||||
|
||||
@ -215,13 +216,14 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block)
|
||||
ret = NAND_RAWREAD(raw, block, 1, 0, spare);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: Cannot read page #1 of block #%d\n", block);
|
||||
fdbg("ERROR: Failed to read page 1 of block %d\n", block);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nandscheme_readbadblockmarker(scheme, spare, &marker);
|
||||
if (marker != 0xff)
|
||||
{
|
||||
fvdbg("Page 1 block %d marker=%02x\n", block, marker);
|
||||
return BADBLOCK;
|
||||
}
|
||||
|
||||
@ -239,7 +241,7 @@ static int nand_checkblock(FAR struct nand_dev_s *nand, off_t block)
|
||||
* nand - Pointer to a struct nand_dev_s instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* OK (always)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -250,6 +252,10 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
|
||||
FAR struct nand_model_s *model;
|
||||
off_t nblocks;
|
||||
off_t block;
|
||||
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
off_t good;
|
||||
unsigned int ngood;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(nand && nand->raw);
|
||||
@ -263,10 +269,14 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
|
||||
|
||||
/* Initialize block statuses */
|
||||
|
||||
fvdbg("Retrieving bad block information ...\n");
|
||||
fvdbg("Retrieving bad block information. nblocks=%d\n", nblocks);
|
||||
|
||||
/* Retrieve block status from their first page spare area */
|
||||
|
||||
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
ngood = 0;
|
||||
#endif
|
||||
|
||||
for (block = 0; block < nblocks; block++)
|
||||
{
|
||||
/* Read spare of first page */
|
||||
@ -274,6 +284,13 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
|
||||
ret = nand_checkblock(nand, block);
|
||||
if (ret != GOODBLOCK)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
if (ngood > 0)
|
||||
{
|
||||
fvdbg("Good blocks: %u - %u\n", good, good + ngood);
|
||||
ngood = 0;
|
||||
}
|
||||
#endif
|
||||
if (ret == BADBLOCK)
|
||||
{
|
||||
fvdbg("Block %u is bad\n", (unsigned int)block);
|
||||
@ -284,8 +301,26 @@ static int nand_devscan(FAR struct nand_dev_s *nand)
|
||||
(unsigned int)block, ret);
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
else
|
||||
{
|
||||
if (ngood == 0)
|
||||
{
|
||||
good = block;
|
||||
}
|
||||
|
||||
ngood++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
if (ngood > 0)
|
||||
{
|
||||
fvdbg("Good blocks: %u - %u\n", good, good + ngood);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_MTD_NAND_BLOCKCHECK */
|
||||
@ -918,13 +953,7 @@ FAR struct mtd_dev_s *nand_initialize(FAR struct nand_raw_s *raw)
|
||||
|
||||
/* Scan the device for bad blocks */
|
||||
|
||||
ret = nand_devscan(nand);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: nandspare_intialize failed\n", ret);
|
||||
kfree(nand);
|
||||
return NULL;
|
||||
}
|
||||
(void)nand_devscan(nand);
|
||||
|
||||
/* Return the implementation-specific state structure as the MTD device */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user