SAMA5 NAND: Fix some DMA related issues
This commit is contained in:
parent
2f0326033b
commit
e8c0512ea6
@ -211,7 +211,8 @@ static inline uintptr_t sdram_physramaddr(uintptr_t virtramaddr)
|
||||
*
|
||||
* Description:
|
||||
* Given the virtual address of an NFC SRAM memory location, return the
|
||||
* physical address of that location
|
||||
* physical address of that location. If NFC SRAM is not being used by
|
||||
* the NAND logic, then it may be used a general purpose SRAM.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -465,10 +466,12 @@ static inline uintptr_t sdram_virtramaddr(uintptr_t physramaddr)
|
||||
*
|
||||
* Description:
|
||||
* Given the physical address of an NFC SRAM memory location, return the
|
||||
* virtual address of that location
|
||||
* virtual address of that location. If NFC SRAM is not being used by
|
||||
* the NAND logic, then it may be used a general purpose SRAM.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SAMA5_HAVE_NAND
|
||||
static inline uintptr_t nfcsram_virtramaddr(uintptr_t physramaddr)
|
||||
{
|
||||
#if SAM_NFCSRAM_PSECTION != SAM_NFCSRAM_VSECTION
|
||||
@ -489,6 +492,7 @@ static inline uintptr_t nfcsram_virtramaddr(uintptr_t physramaddr)
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udphsram_virtramaddr
|
||||
@ -691,6 +695,18 @@ uintptr_t sam_physregaddr(uintptr_t virtregaddr)
|
||||
return sysc_physregaddr(virtregaddr);
|
||||
}
|
||||
|
||||
/* Check for NFCS SRAM. If NFC SRAM is being used by the NAND logic,
|
||||
* then it will be treated as peripheral space.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SAMA5_HAVE_NAND
|
||||
if (virtregaddr >= SAM_NFCSRAM_VSECTION &&
|
||||
virtregaddr < (SAM_NFCSRAM_VSECTION + SAM_NFCSRAM_SIZE))
|
||||
{
|
||||
return nfcsram_physramaddr(virtregaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We will not get here unless we are called with an invalid register
|
||||
* address
|
||||
*/
|
||||
@ -731,13 +747,17 @@ uintptr_t sam_physramaddr(uintptr_t virtramaddr)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for NFCS SRAM. */
|
||||
/* Check for NFCS SRAM. If NFC SRAM is not being used by the NAND logic,
|
||||
* then it may be used a general purpose SRAM.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SAMA5_HAVE_NAND
|
||||
if (virtramaddr >= SAM_NFCSRAM_VSECTION &&
|
||||
virtramaddr < (SAM_NFCSRAM_VSECTION + SAM_NFCSRAM_SIZE))
|
||||
{
|
||||
return nfcsram_physramaddr(virtramaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for UDPH SRAM. */
|
||||
|
||||
@ -835,13 +855,17 @@ uintptr_t sam_virtramaddr(uintptr_t physramaddr)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for NFCS SRAM. */
|
||||
/* Check for NFCS SRAM. If NFC SRAM is not being used by the NAND logic,
|
||||
* then it may be used a general purpose SRAM.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SAMA5_HAVE_NAND
|
||||
if (physramaddr >= SAM_NFCSRAM_PSECTION &&
|
||||
physramaddr < (SAM_NFCSRAM_PSECTION + SAM_NFCSRAM_SIZE))
|
||||
{
|
||||
return nfcsram_virtramaddr(physramaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for UDPH SRAM. */
|
||||
|
||||
|
@ -107,7 +107,7 @@
|
||||
|
||||
/* DMA Configuration */
|
||||
|
||||
#define DMA_FLAGS8 \
|
||||
#define NFCSRAM_DMA_FLAGS8 \
|
||||
DMACH_FLAG_FIFOCFG_LARGEST | \
|
||||
(((0x3f) << DMACH_FLAG_PERIPHPID_SHIFT) | DMACH_FLAG_PERIPHAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_PERIPHWIDTH_8BITS | DMACH_FLAG_PERIPHINCREMENT | \
|
||||
@ -116,7 +116,15 @@
|
||||
DMACH_FLAG_MEMWIDTH_8BITS | DMACH_FLAG_MEMINCREMENT | \
|
||||
DMACH_FLAG_MEMCHUNKSIZE_1)
|
||||
|
||||
#define DMA_FLAGS16 \
|
||||
#define NAND_DMA_FLAGS8 \
|
||||
DMACH_FLAG_FIFOCFG_LARGEST | \
|
||||
(((0x3f) << DMACH_FLAG_PERIPHPID_SHIFT) | DMACH_FLAG_PERIPHAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_PERIPHWIDTH_8BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \
|
||||
((0x3f) << DMACH_FLAG_MEMPID_SHIFT) | DMACH_FLAG_MEMAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_MEMWIDTH_8BITS | DMACH_FLAG_MEMINCREMENT | \
|
||||
DMACH_FLAG_MEMCHUNKSIZE_1)
|
||||
|
||||
#define NFCSRAM_DMA_FLAGS16 \
|
||||
DMACH_FLAG_FIFOCFG_LARGEST | \
|
||||
(((0x3f) << DMACH_FLAG_PERIPHPID_SHIFT) | DMACH_FLAG_PERIPHAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_PERIPHWIDTH_16BITS | DMACH_FLAG_PERIPHINCREMENT | \
|
||||
@ -125,6 +133,14 @@
|
||||
DMACH_FLAG_MEMWIDTH_16BITS | DMACH_FLAG_MEMINCREMENT | \
|
||||
DMACH_FLAG_MEMCHUNKSIZE_1)
|
||||
|
||||
#define NAND_DMA_FLAGS16 \
|
||||
DMACH_FLAG_FIFOCFG_LARGEST | \
|
||||
(((0x3f) << DMACH_FLAG_PERIPHPID_SHIFT) | DMACH_FLAG_PERIPHAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_PERIPHWIDTH_16BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \
|
||||
((0x3f) << DMACH_FLAG_MEMPID_SHIFT) | DMACH_FLAG_MEMAHB_AHB_IF0 | \
|
||||
DMACH_FLAG_MEMWIDTH_16BITS | DMACH_FLAG_MEMINCREMENT | \
|
||||
DMACH_FLAG_MEMCHUNKSIZE_1)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -170,9 +186,11 @@ static int hsmc_interrupt(int irq, void *context);
|
||||
static int nand_wait_dma(struct sam_nandcs_s *priv);
|
||||
static void nand_dmacallback(DMA_HANDLE handle, void *arg, int result);
|
||||
static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes);
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes,
|
||||
uint32_t dmaflags);
|
||||
static int nand_dma_write(struct sam_nandcs_s *priv,
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes)
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes,
|
||||
uint32_t dmaflags)
|
||||
#endif
|
||||
|
||||
/* Raw Data Transfer Helpers */
|
||||
@ -972,10 +990,11 @@ static void nand_dmacallback(DMA_HANDLE handle, void *arg, int result)
|
||||
* Transfer data to NAND from the provided buffer via DMA.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Lower-half, private NAND FLASH device state
|
||||
* vsrc - NAND data destination address.
|
||||
* vdest - Buffer where data read from NAND will be returned.
|
||||
* nbytes - The number of bytes to transfer
|
||||
* priv - Lower-half, private NAND FLASH device state
|
||||
* vsrc - NAND data destination address.
|
||||
* vdest - Buffer where data read from NAND will be returned.
|
||||
* nbytes - The number of bytes to transfer
|
||||
* dmaflags - Describes the DMA configuration
|
||||
*
|
||||
* Returned Value
|
||||
* OK on success; a negated errno value on failure.
|
||||
@ -984,7 +1003,8 @@ static void nand_dmacallback(DMA_HANDLE handle, void *arg, int result)
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes)
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes,
|
||||
uint32_t dmaflags)
|
||||
{
|
||||
uint32_t psrc;
|
||||
uint32_t pdest;
|
||||
@ -1007,6 +1027,10 @@ static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
psrc = sam_physregaddr(vsrc); /* Source is NAND */
|
||||
pdest = sam_physramaddr(vdest); /* Destination is normal memory */
|
||||
|
||||
/* Configure the DMA: 8- vs 16-bit, NFC SRAM or NAND */
|
||||
|
||||
sam_dmaconfig(priv->dma, dmaflags);
|
||||
|
||||
/* Setup the Memory-to-Memory DMA. The semantics of the DMA module are
|
||||
* awkward here. We will treat the NAND (src) as the peripheral source
|
||||
* and memory as the destination. Internally, the DMA module will realize
|
||||
@ -1046,10 +1070,11 @@ static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
* Transfer data to NAND from the provided buffer via DMA.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Lower-half, private NAND FLASH device state
|
||||
* vsrc - Buffer that provides the data for the write
|
||||
* vdest - NAND data destination address
|
||||
* nbytes - The number of bytes to transfer
|
||||
* priv - Lower-half, private NAND FLASH device state
|
||||
* vsrc - Buffer that provides the data for the write
|
||||
* vdest - NAND data destination address
|
||||
* nbytes - The number of bytes to transfer
|
||||
* dmaflags - Describes the DMA configuration
|
||||
*
|
||||
* Returned Value
|
||||
* OK on success; a negated errno value on failure.
|
||||
@ -1058,7 +1083,8 @@ static int nand_dma_read(struct sam_nandcs_s *priv,
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
static int nand_dma_write(struct sam_nandcs_s *priv,
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes)
|
||||
uintptr_t vsrc, uintptr_t vdest, size_t nbytes,
|
||||
uint32_t dmaflags)
|
||||
{
|
||||
uint32_t psrc;
|
||||
uint32_t pdest;
|
||||
@ -1077,6 +1103,10 @@ static int nand_dma_write(struct sam_nandcs_s *priv,
|
||||
psrc = sam_physramaddr(vsrc); /* Source is normal memory */
|
||||
pdest = sam_physregaddr(vdest); /* Destination is NAND (or NAND host SRAM) */
|
||||
|
||||
/* Configure the DMA: 8- vs 16-bit, NFC SRAM or NAND */
|
||||
|
||||
sam_dmaconfig(priv->dma, dmaflags);
|
||||
|
||||
/* Setup the Memory-to-Memory DMA. The semantics of the DMA module are
|
||||
* awkward here. We will treat the NAND (dest) as the peripheral destination
|
||||
* and memory as the source. Internally, the DMA module will realize taht
|
||||
@ -1216,17 +1246,40 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
uintptr_t src;
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
uint32_t dmaflags;
|
||||
#endif
|
||||
int buswidth;
|
||||
|
||||
/* Pick the data destination: The NFC SRAM or the NAND data address */
|
||||
/* Get the buswidth */
|
||||
|
||||
buswidth = nandmodel_getbuswidth(&priv->raw.model);
|
||||
|
||||
/* Pick the data source: The NFC SRAM or the NAND data address */
|
||||
|
||||
if (nfcsram)
|
||||
{
|
||||
/* Source is NFC SRAM */
|
||||
|
||||
src = NFCSRAM_BASE;
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
/* Select NFC SRAM DMA */
|
||||
|
||||
dmaflags = (buswidth == 16 ? NFCSRAM_DMA_FLAGS16 : NFCSRAM_DMA_FLAGS8);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Source is NFC NAND */
|
||||
|
||||
src = priv->raw.dataaddr;
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
/* Select NAND DMA */
|
||||
|
||||
dmaflags = (buswidth == 16 ? NAND_DMA_FLAGS16 : NAND_DMA_FLAGS8);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
@ -1238,7 +1291,7 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
{
|
||||
/* Transfer using DMA */
|
||||
|
||||
return nand_dma_read(priv, src, (uintptr_t)buffer, buflen);
|
||||
return nand_dma_read(priv, src, (uintptr_t)buffer, buflen, dmaflags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1253,7 +1306,6 @@ static int nand_read(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
{
|
||||
/* Check the data bus width of the NAND FLASH */
|
||||
|
||||
buswidth = nandmodel_getbuswidth(&priv->raw.model);
|
||||
if (buswidth == 16)
|
||||
{
|
||||
return nand_smc_read16(src, buffer, buflen);
|
||||
@ -1493,17 +1545,40 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
uint8_t *buffer, size_t buflen, off_t offset)
|
||||
{
|
||||
uintptr_t dest;
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
uint32_t dmaflags;
|
||||
#endif
|
||||
int buswidth;
|
||||
|
||||
/* Pick the data source: The NFC SRAM or the NAND data address */
|
||||
/* Get the buswidth */
|
||||
|
||||
buswidth = nandmodel_getbuswidth(&priv->raw.model);
|
||||
|
||||
/* Pick the data destination: The NFC SRAM or the NAND data address */
|
||||
|
||||
if (nfcsram)
|
||||
{
|
||||
/* Destination is NFC SRAM */
|
||||
|
||||
dest = NFCSRAM_BASE;
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
/* Select NFC SRAM DMA */
|
||||
|
||||
dmaflags = (buswidth == 16 ? NFCSRAM_DMA_FLAGS16 : NFCSRAM_DMA_FLAGS8);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Destination is NFC NAND */
|
||||
|
||||
dest = priv->raw.dataaddr;
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
/* Select NAND DMA */
|
||||
|
||||
dmaflags = (buswidth == 16 ? NAND_DMA_FLAGS16 : NAND_DMA_FLAGS8);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Apply the offset to the source address */
|
||||
@ -1519,7 +1594,7 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
{
|
||||
/* Transfer using DMA */
|
||||
|
||||
return nand_dma_write(priv, (uintptr_t)buffer, dest, buflen);
|
||||
return nand_dma_write(priv, (uintptr_t)buffer, dest, buflen, dmaflags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1534,7 +1609,6 @@ static int nand_write(struct sam_nandcs_s *priv, bool nfcsram,
|
||||
{
|
||||
/* Check the data bus width of the NAND FLASH */
|
||||
|
||||
buswidth = nandmodel_getbuswidth(&priv->raw.model);
|
||||
if (buswidth == 16)
|
||||
{
|
||||
return nand_smc_write16(buffer, dest, buflen);
|
||||
@ -2611,16 +2685,18 @@ struct mtd_dev_s *sam_nand_initialize(int cs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate a DMA channel for NAND transfers */
|
||||
/* Allocate a DMA channel for NAND transfers. The channels will be
|
||||
* configured as needed on-the-fly
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SAMA5_NAND_DMA
|
||||
if (nandmodel_getbuswidth(&priv->raw.model) == 16)
|
||||
{
|
||||
priv->dma = sam_dmachannel(NAND_DMAC, DMA_FLAGS16);
|
||||
priv->dma = sam_dmachannel(NAND_DMAC, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->dma = sam_dmachannel(NAND_DMAC, DMA_FLAGS8);
|
||||
priv->dma = sam_dmachannel(NAND_DMAC, 0);
|
||||
}
|
||||
|
||||
if (!priv->dma)
|
||||
|
Loading…
Reference in New Issue
Block a user