SAMA5 NAND: bugfixes

This commit is contained in:
Gregory Nutt
2013-12-06 11:34:29 -06:00
parent 1b21322f06
commit e92d493d8e
3 changed files with 131 additions and 98 deletions
+63 -63
View File
@@ -79,31 +79,31 @@
#define SAM_HSMC_PMECCIMR_OFFSET 0x0094 /* PMECC Interrupt Mask Register */
#define SAM_HSMC_PMECCISR_OFFSET 0x0098 /* PMECC Interrupt Status Register */
/* 0x009c-0x00ac Reserved */
#define SAM_HSMC_PMECC_OFFSET(sec) (0x00b0+((sec) << 6)) /* PMECC sector offset */
#define SAM_HSMC_PMECC0_OFFSET(sec) (0x00b0+((sec) << 6)) /* PMECC Redundancy 0 Register */
#define SAM_HSMC_PMECC1_OFFSET(sec) (0x00b4+((sec) << 6)) /* PMECC Redundancy 1 Register */
#define SAM_HSMC_PMECC2_OFFSET(sec) (0x00b8+((sec) << 6)) /* PMECC Redundancy 2 Register */
#define SAM_HSMC_PMECC3_OFFSET(sec) (0x00bc+((sec) << 6)) /* PMECC Redundancy 3 Register */
#define SAM_HSMC_PMECC4_OFFSET(sec) (0x00c0+((sec) << 6)) /* PMECC Redundancy 4 Register */
#define SAM_HSMC_PMECC5_OFFSET(sec) (0x00c4+((sec) << 6)) /* PMECC Redundancy 5 Register */
#define SAM_HSMC_PMECC6_OFFSET(sec) (0x00c8+((sec) << 6)) /* PMECC Redundancy 6 Register */
#define SAM_HSMC_PMECC7_OFFSET(sec) (0x00cc+((sec) << 6)) /* PMECC Redundancy 7 Register */
#define SAM_HSMC_PMECC8_OFFSET(sec) (0x00d0+((sec) << 6)) /* PMECC Redundancy 8 Register */
#define SAM_HSMC_PMECC9_OFFSET(sec) (0x00d4+((sec) << 6)) /* PMECC Redundancy 9 Register */
#define SAM_HSMC_PMECC10_OFFSET(sec) (0x00d8+((sec) << 6)) /* PMECC Redundancy 10 Register */
#define SAM_HSMC_PEM_OFFSET(sec) (0x02b0+((sec) << 6)) /* PMECC Remainder offset */
#define SAM_HSMC_REM0_OFFSET(sec) (0x02b0+((sec) << 6)) /* PMECC Remainder 0 Register */
#define SAM_HSMC_REM1_OFFSET(sec) (0x02b4+((sec) << 6)) /* PMECC Remainder 1 Register */
#define SAM_HSMC_REM2_OFFSET(sec) (0x02b8+((sec) << 6)) /* PMECC Remainder 2 Register */
#define SAM_HSMC_REM3_OFFSET(sec) (0x02bc+((sec) << 6)) /* PMECC Remainder 3 Register */
#define SAM_HSMC_REM4_OFFSET(sec) (0x02b0+((sec) << 6)) /* PMECC Remainder 4 Register */
#define SAM_HSMC_REM5_OFFSET(sec) (0x02b4+((sec) << 6)) /* PMECC Remainder 5 Register */
#define SAM_HSMC_REM6_OFFSET(sec) (0x02b8+((sec) << 6)) /* PMECC Remainder 6 Register */
#define SAM_HSMC_REM7_OFFSET(sec) (0x02bc+((sec) << 6)) /* PMECC Remainder 7 Register */
#define SAM_HSMC_REM8_OFFSET(sec) (0x02b0+((sec) << 6)) /* PMECC Remainder 8 Register */
#define SAM_HSMC_REM9_OFFSET(sec) (0x02b4+((sec) << 6)) /* PMECC Remainder 9 Register */
#define SAM_HSMC_REM10_OFFSET(sec) (0x02b8+((sec) << 6)) /* PMECC Remainder 10 Register */
#define SAM_HSMC_REM11_OFFSET(sec) (0x02bc+((sec) << 6)) /* PMECC Remainder 11 Register */
#define SAM_HSMC_PMECC_OFFSET(n) (0x00b0 + ((n) << 6)) /* PMECC sector offset */
# define SAM_HSMC_PMECC0_OFFSET(n) (0x00b0 + ((n) << 6)) /* PMECC Redundancy 0 Register */
# define SAM_HSMC_PMECC1_OFFSET(n) (0x00b4 + ((n) << 6)) /* PMECC Redundancy 1 Register */
# define SAM_HSMC_PMECC2_OFFSET(n) (0x00b8 + ((n) << 6)) /* PMECC Redundancy 2 Register */
# define SAM_HSMC_PMECC3_OFFSET(n) (0x00bc + ((n) << 6)) /* PMECC Redundancy 3 Register */
# define SAM_HSMC_PMECC4_OFFSET(n) (0x00c0 + ((n) << 6)) /* PMECC Redundancy 4 Register */
# define SAM_HSMC_PMECC5_OFFSET(n) (0x00c4 + ((n) << 6)) /* PMECC Redundancy 5 Register */
# define SAM_HSMC_PMECC6_OFFSET(n) (0x00c8 + ((n) << 6)) /* PMECC Redundancy 6 Register */
# define SAM_HSMC_PMECC7_OFFSET(n) (0x00cc + ((n) << 6)) /* PMECC Redundancy 7 Register */
# define SAM_HSMC_PMECC8_OFFSET(n) (0x00d0 + ((n) << 6)) /* PMECC Redundancy 8 Register */
# define SAM_HSMC_PMECC9_OFFSET(n) (0x00d4 + ((n) << 6)) /* PMECC Redundancy 9 Register */
# define SAM_HSMC_PMECC10_OFFSET(n) (0x00d8 + ((n) << 6)) /* PMECC Redundancy 10 Register */
#define SAM_HSMC_REM_OFFSET(n) (0x02b0 + ((n) << 6)) /* PMECC Remainder offset */
# define SAM_HSMC_REM0_OFFSET(n) (0x02b0 + ((n) << 6)) /* PMECC Remainder 0 Register */
# define SAM_HSMC_REM1_OFFSET(n) (0x02b4 + ((n) << 6)) /* PMECC Remainder 1 Register */
# define SAM_HSMC_REM2_OFFSET(n) (0x02b8 + ((n) << 6)) /* PMECC Remainder 2 Register */
# define SAM_HSMC_REM3_OFFSET(n) (0x02bc + ((n) << 6)) /* PMECC Remainder 3 Register */
# define SAM_HSMC_REM4_OFFSET(n) (0x02b0 + ((n) << 6)) /* PMECC Remainder 4 Register */
# define SAM_HSMC_REM5_OFFSET(n) (0x02b4 + ((n) << 6)) /* PMECC Remainder 5 Register */
# define SAM_HSMC_REM6_OFFSET(n) (0x02b8 + ((n) << 6)) /* PMECC Remainder 6 Register */
# define SAM_HSMC_REM7_OFFSET(n) (0x02bc + ((n) << 6)) /* PMECC Remainder 7 Register */
# define SAM_HSMC_REM8_OFFSET(n) (0x02b0 + ((n) << 6)) /* PMECC Remainder 8 Register */
# define SAM_HSMC_REM9_OFFSET(n) (0x02b4 + ((n) << 6)) /* PMECC Remainder 9 Register */
# define SAM_HSMC_REM10_OFFSET(n) (0x02b8 + ((n) << 6)) /* PMECC Remainder 10 Register */
# define SAM_HSMC_REM11_OFFSET(n) (0x02bc + ((n) << 6)) /* PMECC Remainder 11 Register */
/* 0x04a0-0x04fc Reserved */
#define SAM_HSMC_ELCFG_OFFSET 0x0500 /* PMECC Error Location Configuration Register */
#define SAM_HSMC_ELPRIM_OFFSET 0x0504 /* PMECC Error Location Primitive Register */
@@ -115,7 +115,7 @@
#define SAM_HSMC_ELIMR_OFFSET 0x051c /* PMECC Error Location Interrupt Mask Register */
#define SAM_HSMC_ELISR_OFFSET 0x0520 /* PMECC Error Location Interrupt Status Register */
/* 0x0524-0x052c Reserved */
#define SAM_HSMC_SIGMA_OFFSET(n) (0x0528+((n)<<2)) /* PMECC Error Location SIGMA n Register */
#define SAM_HSMC_SIGMA_OFFSET(n) (0x0528 + ((n) << 2)) /* PMECC Error Location SIGMA n Register */
# define SAM_HSMC_SIGMA0_OFFSET 0x0528 /* PMECC Error Location SIGMA 0 Register */
# define SAM_HSMC_SIGMA1_OFFSET 0x052c /* PMECC Error Location SIGMA 1 Register */
# define SAM_HSMC_SIGMA2_OFFSET 0x0530 /* PMECC Error Location SIGMA 2 Register */
@@ -141,7 +141,7 @@
# define SAM_HSMC_SIGMA22_OFFSET 0x0580 /* PMECC Error Location SIGMA 22 Register */
# define SAM_HSMC_SIGMA23_OFFSET 0x0584 /* PMECC Error Location SIGMA 23 Register */
# define SAM_HSMC_SIGMA24_OFFSET 0x0588 /* PMECC Error Location SIGMA 24 Register */
#define SAM_HSMC_ERRLOC_OFFSET(n) (0x058c+((n)<<2)) /* PMECC Error Location n Register */
#define SAM_HSMC_ERRLOC_OFFSET(n) (0x058c + ((n) << 2)) /* PMECC Error Location n Register */
# define SAM_HSMC_ERRLOC0_OFFSET 0x058c /* PMECC Error Location 0 Register */
# define SAM_HSMC_ERRLOC1_OFFSET 0x0590 /* PMECC Error Location 1 Register */
# define SAM_HSMC_ERRLOC2_OFFSET 0x0594 /* PMECC Error Location 2 Register */
@@ -167,11 +167,11 @@
# define SAM_HSMC_ERRLOC22_OFFSET 0x05e4 /* PMECC Error Location 22 Register */
# define SAM_HSMC_ERRLOC23_OFFSET 0x05e8 /* PMECC Error Location 23 Register */
/* 0x05ec-0x05fc Reserved */
#define SAM_HSMC_SETUP_OFFSET(cs) (0x0600+0x14*(cs)) /* HSMC Setup Register */
#define SAM_HSMC_PULSE_OFFSET(cs) (0x0604+0x14*(cs)) /* HSMC Pulse Register */
#define SAM_HSMC_CYCLE_OFFSET(cs) (0x0608+0x14*(cs)) /* HSMC Cycle Register */
#define SAM_HSMC_TIMINGS_OFFSET(cs) (0x060c+0x14*(cs)) /* HSMC Timings Register */
#define SAM_HSMC_MODE_OFFSET(cs) (0x0610+0x14*(cs)) /* HSMC Mode Register */
#define SAM_HSMC_SETUP_OFFSET(n) (0x0600 + 0x14 * (n)) /* HSMC Setup Register */
#define SAM_HSMC_PULSE_OFFSET(n) (0x0604 + 0x14 * (n)) /* HSMC Pulse Register */
#define SAM_HSMC_CYCLE_OFFSET(n) (0x0608 + 0x14 * (n)) /* HSMC Cycle Register */
#define SAM_HSMC_TIMINGS_OFFSET(n) (0x060c + 0x14 * (n)) /* HSMC Timings Register */
#define SAM_HSMC_MODE_OFFSET(n) (0x0610 + 0x14 * (n)) /* HSMC Mode Register */
#define SAM_HSMC_OCMS_OFFSET 0x06a0 /* HSMC OCMS Register */
#define SAM_HSMC_KEY1_OFFSET 0x06a4 /* HSMC OCMS KEY1 Register */
#define SAM_HSMC_KEY2_OFFSET 0x06a8 /* HSMC OCMS KEY2 Register */
@@ -200,31 +200,31 @@
#define SAM_HSMC_PMECCIDR (SAM_HSMC_VBASE+SAM_HSMC_PMECCIDR_OFFSET)
#define SAM_HSMC_PMECCIMR (SAM_HSMC_VBASE+SAM_HSMC_PMECCIMR_OFFSET)
#define SAM_HSMC_PMECCISR (SAM_HSMC_VBASE+SAM_HSMC_PMECCISR_OFFSET)
#define SAM_HSMC_PMECC_BASE(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC_OFFSET(sec))
# define SAM_HSMC_PMECC0(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC0_OFFSET(sec))
# define SAM_HSMC_PMECC1(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC1_OFFSET(sec))
# define SAM_HSMC_PMECC2(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC2_OFFSET(sec))
# define SAM_HSMC_PMECC3(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC3_OFFSET(sec))
# define SAM_HSMC_PMECC4(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC4_OFFSET(sec))
# define SAM_HSMC_PMECC5(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC5_OFFSET(sec))
# define SAM_HSMC_PMECC6(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC6_OFFSET(sec))
# define SAM_HSMC_PMECC7(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC7_OFFSET(sec))
# define SAM_HSMC_PMECC8(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC8_OFFSET(sec))
# define SAM_HSMC_PMECC9(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC9_OFFSET(sec))
# define SAM_HSMC_PMECC10(sec) (SAM_HSMC_VBASE+SAM_HSMC_PMECC10_OFFSET(sec))
#define SAM_HSMC_REM_BASE(sec) (SAM_HSMC_VBASE+SAM_HSMC_PEM_OFFSET(sec))
# define SAM_HSMC_REM0(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM0_OFFSET(sec))
# define SAM_HSMC_REM1(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM1_OFFSET(sec))
# define SAM_HSMC_REM2(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM2_OFFSET(sec))
# define SAM_HSMC_REM3(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM3_OFFSET(sec))
# define SAM_HSMC_REM4(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM4_OFFSET(sec))
# define SAM_HSMC_REM5(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM5_OFFSET(sec))
# define SAM_HSMC_REM6(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM6_OFFSET(sec))
# define SAM_HSMC_REM7(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM7_OFFSET(sec))
# define SAM_HSMC_REM8(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM8_OFFSET(sec))
# define SAM_HSMC_REM9(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM9_OFFSET(sec))
# define SAM_HSMC_REM10(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM10_OFFSET(sec))
# define SAM_HSMC_REM11(sec) (SAM_HSMC_VBASE+SAM_HSMC_REM11_OFFSET(sec))
#define SAM_HSMC_PMECC_BASE(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC_OFFSET(n))
# define SAM_HSMC_PMECC0(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC0_OFFSET(n))
# define SAM_HSMC_PMECC1(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC1_OFFSET(n))
# define SAM_HSMC_PMECC2(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC2_OFFSET(n))
# define SAM_HSMC_PMECC3(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC3_OFFSET(n))
# define SAM_HSMC_PMECC4(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC4_OFFSET(n))
# define SAM_HSMC_PMECC5(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC5_OFFSET(n))
# define SAM_HSMC_PMECC6(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC6_OFFSET(n))
# define SAM_HSMC_PMECC7(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC7_OFFSET(n))
# define SAM_HSMC_PMECC8(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC8_OFFSET(n))
# define SAM_HSMC_PMECC9(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC9_OFFSET(n))
# define SAM_HSMC_PMECC10(n) (SAM_HSMC_VBASE+SAM_HSMC_PMECC10_OFFSET(n))
#define SAM_HSMC_REM_BASE(n) (SAM_HSMC_VBASE+SAM_HSMC_REM_OFFSET(n))
# define SAM_HSMC_REM0(n) (SAM_HSMC_VBASE+SAM_HSMC_REM0_OFFSET(n))
# define SAM_HSMC_REM1(n) (SAM_HSMC_VBASE+SAM_HSMC_REM1_OFFSET(n))
# define SAM_HSMC_REM2(n) (SAM_HSMC_VBASE+SAM_HSMC_REM2_OFFSET(n))
# define SAM_HSMC_REM3(n) (SAM_HSMC_VBASE+SAM_HSMC_REM3_OFFSET(n))
# define SAM_HSMC_REM4(n) (SAM_HSMC_VBASE+SAM_HSMC_REM4_OFFSET(n))
# define SAM_HSMC_REM5(n) (SAM_HSMC_VBASE+SAM_HSMC_REM5_OFFSET(n))
# define SAM_HSMC_REM6(n) (SAM_HSMC_VBASE+SAM_HSMC_REM6_OFFSET(n))
# define SAM_HSMC_REM7(n) (SAM_HSMC_VBASE+SAM_HSMC_REM7_OFFSET(n))
# define SAM_HSMC_REM8(n) (SAM_HSMC_VBASE+SAM_HSMC_REM8_OFFSET(n))
# define SAM_HSMC_REM9(n) (SAM_HSMC_VBASE+SAM_HSMC_REM9_OFFSET(n))
# define SAM_HSMC_REM10(n) (SAM_HSMC_VBASE+SAM_HSMC_REM10_OFFSET(n))
# define SAM_HSMC_REM11(n) (SAM_HSMC_VBASE+SAM_HSMC_REM11_OFFSET(n))
#define SAM_HSMC_ELCFG (SAM_HSMC_VBASE+SAM_HSMC_ELCFG_OFFSET)
#define SAM_HSMC_ELPRIM (SAM_HSMC_VBASE+SAM_HSMC_ELPRIM_OFFSET)
#define SAM_HSMC_ELEN (SAM_HSMC_VBASE+SAM_HSMC_ELEN_OFFSET)
@@ -285,11 +285,11 @@
# define SAM_HSMC_ERRLOC21 (SAM_HSMC_VBASE+SAM_HSMC_ERRLOC21_OFFSET)
# define SAM_HSMC_ERRLOC22 (SAM_HSMC_VBASE+SAM_HSMC_ERRLOC22_OFFSET)
# define SAM_HSMC_ERRLOC23 (SAM_HSMC_VBASE+SAM_HSMC_ERRLOC23_OFFSET)
#define SAM_HSMC_SETUP(cs) (SAM_HSMC_VBASE+SAM_HSMC_SETUP_OFFSET(cs))
#define SAM_HSMC_PULSE(cs) (SAM_HSMC_VBASE+SAM_HSMC_PULSE_OFFSET(cs))
#define SAM_HSMC_CYCLE(cs) (SAM_HSMC_VBASE+SAM_HSMC_CYCLE_OFFSET(cs))
#define SAM_HSMC_TIMINGS(cs) (SAM_HSMC_VBASE+SAM_HSMC_TIMINGS_OFFSET(cs))
#define SAM_HSMC_MODE(cs) (SAM_HSMC_VBASE+SAM_HSMC_MODE_OFFSET(cs))
#define SAM_HSMC_SETUP(n) (SAM_HSMC_VBASE+SAM_HSMC_SETUP_OFFSET(n))
#define SAM_HSMC_PULSE(n) (SAM_HSMC_VBASE+SAM_HSMC_PULSE_OFFSET(n))
#define SAM_HSMC_CYCLE(n) (SAM_HSMC_VBASE+SAM_HSMC_CYCLE_OFFSET(n))
#define SAM_HSMC_TIMINGS(n) (SAM_HSMC_VBASE+SAM_HSMC_TIMINGS_OFFSET(n))
#define SAM_HSMC_MODE(n) (SAM_HSMC_VBASE+SAM_HSMC_MODE_OFFSET(n))
#define SAM_HSMC_OCMS (SAM_HSMC_VBASE+SAM_HSMC_OCMS_OFFSET)
#define SAM_HSMC_KEY1 (SAM_HSMC_VBASE+SAM_HSMC_KEY1_OFFSET)
#define SAM_HSMC_KEY2 (SAM_HSMC_VBASE+SAM_HSMC_KEY2_OFFSET)
@@ -428,7 +428,7 @@
/* PMECC Interrupt Status Register */
#define HSMC_PMECCISR_ERRIS(sec) (1 << (sec)) /* Bits 0-7: Error Interrupt Status */
#define HSMC_PMECCISR_ERRIS(n) (1 << (n)) /* Bits 0-7: Error Interrupt Status */
/* PMECC Redundancy x Register (32-bit ECC value) */
+1
View File
@@ -58,6 +58,7 @@
#include "chip.h"
#include "sam_dmac.h"
#include "sam_periphclks.h"
#include "sam_memories.h"
#include "chip/sam_pmc.h"
#include "chip/sam_dmac.h"
+67 -35
View File
@@ -220,7 +220,7 @@ static int nand_dma_write(struct sam_nandcs_s *priv,
/* Raw Data Transfer Helpers */
static int nand_nfcsram_read(struct sam_nandcs_s *priv,
uint8_t *buffer, uint16_t buflen);
uint8_t *buffer, uint16_t buflen, uint16_t offset);
#ifdef CONFIG_SAMA5_HAVE_PMECC
static int nand_read(struct sam_nandcs_s *priv, uint8_t *buffer,
uint16_t buflen);
@@ -1466,13 +1466,18 @@ static int nand_dma_write(struct sam_nandcs_s *priv,
****************************************************************************/
static int nand_nfcsram_read(struct sam_nandcs_s *priv, uint8_t *buffer,
uint16_t buflen)
uint16_t buflen, uint16_t offset)
{
uintptr_t src;
int remaining;
int ret;
fvdbg("buffer=%p buflen=%d\n", buffer, buflen);
/* Get the offset data source address */
src = NFCSRAM_BASE + (uintptr_t)offset;
#ifdef CONFIG_SAMA5_NAND_DMA
/* Then perform the transfer via memory-to-memory DMA or not, depending
* on if we have a DMA channel assigned and if the transfer is
@@ -1493,8 +1498,7 @@ static int nand_nfcsram_read(struct sam_nandcs_s *priv, uint8_t *buffer,
/* Transfer using DMA */
ret = nand_dma_read(priv, NFCSRAM_BASE, (uintptr_t)buffer, buflen,
dmaflags);
ret = nand_dma_read(priv, src, (uintptr_t)buffer, buflen, dmaflags);
}
else
#endif
@@ -1502,7 +1506,7 @@ static int nand_nfcsram_read(struct sam_nandcs_s *priv, uint8_t *buffer,
/* Transfer without DMA */
{
uint8_t *src8 = (uint8_t *)NFCSRAM_BASE;
uint8_t *src8 = (uint8_t *)src;
uint8_t *dest8 = buffer;
for (remaining = buflen; remaining > 0; remaining--)
@@ -1699,11 +1703,17 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
nand_putreg(SAM_HSMC_PMECCTRL, HSMC_PMECCTRL_DATA);
#if 0 /* Don't use NFC SRAM */
nand_nfc_cleale(priv,
HSMC_ALE_COL_EN | HSMC_ALE_ROW_EN | HSMC_CLE_VCMD2_EN | HSMC_CLE_DATA_EN,
COMMAND_READ_1, COMMAND_READ_2, 0, rowaddr);
#else
nand_setup_rbedge(priv);
nand_nfc_cleale(priv,
HSMC_ALE_COL_EN | HSMC_ALE_ROW_EN | HSMC_CLE_VCMD2_EN,
COMMAND_READ_1, COMMAND_READ_2, 0, rowaddr);
nand_wait_rbedge(priv);
#endif
/* Reset the PMECC module */
@@ -1718,7 +1728,11 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
* busy below would hang.
*/
#if 0 /* Don't use NFC SRAM */
ret = nand_nfcsram_read(priv, (uint8_t *)data, pagesize, 0);
#else
ret = nand_read(priv, (uint8_t *)data, pagesize);
#endif
if (ret < 0)
{
fdbg("ERROR: nand_read for data region failed: %d\n", ret);
@@ -1727,7 +1741,11 @@ static int nand_read_pmecc(struct sam_nandcs_s *priv, off_t block,
/* Now read the spare area into priv->raw.spare (sparesize bytes). */
#if 0 /* Don't use NFC SRAM */
ret = nand_nfcsram_read(priv, priv->raw.spare, sparesize, pagesize);
#else
ret = nand_read(priv, priv->raw.spare, sparesize);
#endif
if (ret < 0)
{
fdbg("ERROR: nand_read for spare region failed: %d\n", ret);
@@ -1989,7 +2007,7 @@ static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
if (data)
{
ret = nand_nfcsram_read(priv, (uint8_t *)data, pagesize);
ret = nand_nfcsram_read(priv, (uint8_t *)data, pagesize, 0);
if (ret < 0)
{
fdbg("ERROR: nand_nfcsram_read for data region failed: %d\n", ret);
@@ -2004,7 +2022,7 @@ static int nand_readpage_noecc(struct sam_nandcs_s *priv, off_t block,
if (spare)
{
ret = nand_nfcsram_read(priv, (uint8_t *)spare, sparesize);
ret = nand_nfcsram_read(priv, (uint8_t *)spare, sparesize, 0);
if (ret < 0)
{
fdbg("ERROR: nand_nfcsram_read for spare region failed: %d\n", ret);
@@ -2309,7 +2327,7 @@ static int nand_writepage_noecc(struct sam_nandcs_s *priv, off_t block,
#ifdef CONFIG_SAMA5_HAVE_PMECC
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)
{
uint32_t regval;
volatile uint8_t *pmecc;
@@ -2348,23 +2366,21 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
/* Calculate physical address of the page */
rowaddr = block * nandmodel_pagesperblock(&priv->raw.model) + page;
fvdbg("pagesize=%d eccsaddr=%d rowaddr=%d\n", pagesize, eccsaddr, rowaddr);
/* Write data area if needed */
#if 1 /* Use NFC SRAM */
/* Write the data area to NFC SRAM */
if (data)
ret = nand_nfcsram_write(priv, (uint8_t *)data, pagesize, 0);
if (ret < 0)
{
ret = nand_nfcsram_write(priv, (uint8_t *)data, pagesize, 0);
if (ret < 0)
{
fdbg("ERROR: Block %d page %d nand_nfcsram_write for data region failed: %d\n",
block, page, ret);
goto errout;
}
fdbg("ERROR: Block %d page %d nand_nfcsram_write for data region failed: %d\n",
block, page, ret);
goto errout;
}
#endif
/* Get the number of sectors per page */
/* Get the encoded number of sectors per page */
switch (pmecc_get_pagesize())
{
@@ -2402,7 +2418,8 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
regval |= HSMC_PMECCFG_NANDWR_WRITE;
nand_putreg(SAM_HSMC_PMECCFG, regval);
/* Configure the NFC */
#if 1 /* Use NFC SRAM */
/* Setup the NFC and wait for the transfer to complete */
nand_setup_xfrdone(priv);
nand_nfc_cleale(priv,
@@ -2410,16 +2427,34 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
HSMC_ALE_ROW_EN | HSMC_CLE_DATA_EN,
COMMAND_WRITE_1, 0, 0, rowaddr);
nand_wait_xfrdone(priv);
#else
/* Setup the for the data transfer */
nand_nfc_cleale(priv,
HSMC_CLE_WRITE_EN | HSMC_ALE_COL_EN,
HSMC_CLE_WRITE_EN | HSMC_ALE_COL_EN | HSMC_ALE_ROW_EN,
COMMAND_WRITE_1, 0, 0, rowaddr);
/* Transfer the data via the NAND */
ret = nand_write(priv, (uint8_t *)data, pagesize, 0);
if (ret < 0)
{
fdbg("ERROR: Block %d page %d nand_write for data region failed: %d\n",
block, page, ret);
goto errout;
}
#endif
/* Set up for the ECC transfer */
nand_nfc_cleale(priv, HSMC_CLE_WRITE_EN | HSMC_ALE_COL_EN,
COMMAND_RANDOM_IN, 0, eccsaddr, 0);
/* Wait until the kernel of the PMECC is not busy */
while ((nand_getreg(SAM_HSMC_PMECCSR) & HSMC_PMECCSR_BUSY) != 0);
/* Write the ECC */
/* Get the ECC values from the PMECC */
eccpersector = (pmecc_get_eccsize()) / sectersperpage;
eccsize = sectersperpage * eccpersector;
@@ -2430,8 +2465,9 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
#ifdef CONFIG_SAMA5_PMECC_TRIMPAGE
if (nand_trrimffs(priv) && page >= nand_get_trimpage(priv))
{
/* This behaviour was found to fix both UBI and JFFS2 images written to
* cleanly erased NAND partitions
/* Comments in the Atmel sample say that this behavior was found to
* fix both UBI and JFFS2 images written to cleanly erased NAND
* partitions
*/
memset(g_nand.ecctab, 0xff, eccsize);
@@ -2455,6 +2491,8 @@ static int nand_writepage_pmecc(struct sam_nandcs_s *priv, off_t block,
}
}
/* Write the ECC to NAND */
ret = nand_write(priv, (uint8_t *)g_nand.ecctab, eccsize, 0);
if (ret < 0)
{
@@ -3017,20 +3055,14 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
return NULL;
}
#ifdef CONFIG_SAMA5_NAND_DMA
/* Allocate a DMA channel for NAND transfers. The channels will be
* configured as needed on-the-fly
* configured as needed on-the-fly. NOTE that no failure is declared
* if we fail to allocate DMA channel; in that case, only non-DMA
* transfers will be performed.
*/
#ifdef CONFIG_SAMA5_NAND_DMA
if (nandmodel_getbuswidth(&priv->raw.model) == 16)
{
priv->dma = sam_dmachannel(NAND_DMAC, 0);
}
else
{
priv->dma = sam_dmachannel(NAND_DMAC, 0);
}
priv->dma = sam_dmachannel(NAND_DMAC, 0);
if (!priv->dma)
{
fdbg("ERROR: Failed to allocate the DMA channel for CS%d\n", cs);