This commit adds a new function arch_invalidate_dcache_by_addr(). It takes the same parameters as arch_invalidate_dcache(), but performs invalidation of only the lines in cache that need to be invalidated. This new function could be used as a a direct replacement for arch_invalidate_dcache().
The user of this invalidation are mmcsd_sdio currently. The mmcsd_sdio driver makes calls for dcache invalidation through the chip specific architecture function SDIO_DMARECVSETUP(). I changed the arch/arm/stm32f7 chips to use arch_invalidate_dcache_by_addr() instead of arch_invalidate_dcache(). This commit includes additional changes to mmcsd_sdio.c. I created SDIO_DMADELYDINVLDT() (DMA delayed invalidate) to invalidate store-into mode dcaches after the DMA transfer. I have been using SDIO_DMADELYDINVLDT() for several weeks now and it has fixed the problems that I previously reported regarding non-cache aligned buffer invalidation errors (for my store-through dcache). However, it does not permit use of unaligned DMA buffers for store-into mode dcaches. SDIO_DMADELYDINVLDT() is a NoOp unless the chip specific Kconfig file selects CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT. I have modified all the stm32f7 chips to select it.
This commit is contained in:
parent
5499c884a5
commit
c6851201c0
@ -1,8 +1,9 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv7-m/arch_invalidate_dcache.c
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Bob Feretich <bob.feretich@rafresearch.com>
|
||||
*
|
||||
* Some logic in this header file derives from the ARM CMSIS core_cm7.h
|
||||
* header file which has a compatible 3-clause BSD license:
|
||||
@ -48,10 +49,6 @@
|
||||
|
||||
#ifdef CONFIG_ARMV7M_DCACHE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -62,7 +59,9 @@
|
||||
* Description:
|
||||
* Invalidate the data cache within the specified region; we will be
|
||||
* performing a DMA operation in this region and we want to purge old data
|
||||
* in the cache.
|
||||
* in the cache. Note that this function invalidates all cache ways
|
||||
* in sets that could be associated with the address range, regardless of
|
||||
* whether the address range is contained in the cache or not.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
@ -147,4 +146,72 @@ void arch_invalidate_dcache(uintptr_t start, uintptr_t end)
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arch_invalidate_dcache_by_addr
|
||||
*
|
||||
* Description:
|
||||
* Invalidate the data cache within the specified region; we will be
|
||||
* performing a DMA operation in this region and we want to purge old data
|
||||
* in the cache. Note that this function only invalidates cache sets that
|
||||
* contain data from this address range.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void arch_invalidate_dcache_by_addr(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
uint32_t ccsidr;
|
||||
uint32_t sshift;
|
||||
uint32_t ssize;
|
||||
|
||||
/* Get the characteristics of the D-Cache */
|
||||
|
||||
ccsidr = getreg32(NVIC_CCSIDR);
|
||||
sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */
|
||||
|
||||
/* Invalidate the D-Cache containing this range of addresses */
|
||||
|
||||
ssize = (1 << sshift);
|
||||
|
||||
/* Round down the start address to the nearest cache line boundary.
|
||||
*
|
||||
* sshift = 5 : Offset to the beginning of the set field
|
||||
* (ssize - 1) = 0x007f : Mask of the set field
|
||||
*/
|
||||
|
||||
start &= ~(ssize - 1);
|
||||
ARM_DSB();
|
||||
|
||||
do
|
||||
{
|
||||
/* The below store causes the cache to check its directory and
|
||||
* determine if this address is contained in the cache. If so, it
|
||||
* invalidate that cache line. Only the cache way containing the
|
||||
* address is invalidated. If the address is not in the cache, then
|
||||
* nothing is invalidated.
|
||||
*/
|
||||
|
||||
putreg32(start, NVIC_DCIMVAC);
|
||||
|
||||
/* Increment the address by the size of one cache line. */
|
||||
|
||||
start += ssize;
|
||||
}
|
||||
while (start < end);
|
||||
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7M_DCACHE */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv7-m/cache.h
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Some logic in this header file derives from the ARM CMSIS core_cm7.h
|
||||
@ -300,7 +300,9 @@ void arch_disable_dcache(void);
|
||||
* Description:
|
||||
* Invalidate the data cache within the specified region; we will be
|
||||
* performing a DMA operation in this region and we want to purge old data
|
||||
* in the cache.
|
||||
* in the cache. Note that this function invalidates all cache ways
|
||||
* in sets that could be associated with the address range, regardless of
|
||||
* whether the address range is contained in the cache or not.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
@ -322,6 +324,35 @@ void arch_invalidate_dcache(uintptr_t start, uintptr_t end);
|
||||
# define arch_invalidate_dcache(s,e)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arch_invalidate_dcache_by_addr
|
||||
*
|
||||
* Description:
|
||||
* Invalidate the data cache within the specified region; we will be
|
||||
* performing a DMA operation in this region and we want to purge old data
|
||||
* in the cache. Note that this function only invalidates cache sets that
|
||||
* contain data from this address range.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARMV7M_DCACHE
|
||||
void arch_invalidate_dcache_by_addr(uintptr_t start, uintptr_t end);
|
||||
#else
|
||||
# define arch_invalidate_dcache_by_addr(s,e)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arch_invalidate_dcache_all
|
||||
*
|
||||
|
@ -240,7 +240,7 @@
|
||||
#define NVIC_MVFR2_OFFSET 0x0f48 /* Media and VFP Feature Register 2 */
|
||||
#define NVIC_ICIALLU_OFFSET 0x0f50 /* I-Cache Invalidate All to PoU (Cortex-M7) */
|
||||
#define NVIC_ICIMVAU_OFFSET 0x0f58 /* I-Cache Invalidate by MVA to PoU (Cortex-M7) */
|
||||
#define NVIC_DCIMVAU_OFFSET 0x0f5c /* D-Cache Invalidate by MVA to PoC (Cortex-M7) */
|
||||
#define NVIC_DCIMVAC_OFFSET 0x0f5c /* D-Cache Invalidate by MVA to PoC (Cortex-M7) */
|
||||
#define NVIC_DCISW_OFFSET 0x0f60 /* D-Cache Invalidate by Set-way (Cortex-M7) */
|
||||
#define NVIC_DCCMVAU_OFFSET 0x0f64 /* D-Cache Clean by MVA to PoU (Cortex-M7) */
|
||||
#define NVIC_DCCMVAC_OFFSET 0x0f68 /* D-Cache Clean by MVA to PoC (Cortex-M7) */
|
||||
@ -429,6 +429,7 @@
|
||||
#define NVIC_ICIALLU (ARMV7M_NVIC_BASE + NVIC_ICIALLU_OFFSET)
|
||||
#define NVIC_ICIMVAU (ARMV7M_NVIC_BASE + NVIC_ICIMVAU_OFFSET)
|
||||
#define NVIC_DCIMVAU (ARMV7M_NVIC_BASE + NVIC_DCIMVAU_OFFSET)
|
||||
#define NVIC_DCIMVAC (ARMV7M_NVIC_BASE + NVIC_DCIMVAC_OFFSET)
|
||||
#define NVIC_DCISW (ARMV7M_NVIC_BASE + NVIC_DCISW_OFFSET)
|
||||
#define NVIC_DCCMVAU (ARMV7M_NVIC_BASE + NVIC_DCCMVAU_OFFSET)
|
||||
#define NVIC_DCCMVAC (ARMV7M_NVIC_BASE + NVIC_DCCMVAC_OFFSET)
|
||||
|
@ -655,6 +655,7 @@ config STM32F7_STM32F722XX
|
||||
default n
|
||||
select STM32F7_STM32F72XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -671,6 +672,7 @@ config STM32F7_STM32F723XX
|
||||
default n
|
||||
select STM32F7_STM32F72XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -687,6 +689,7 @@ config STM32F7_STM32F745XX
|
||||
default n
|
||||
select STM32F7_STM32F74XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -706,6 +709,7 @@ config STM32F7_STM32F746XX
|
||||
default n
|
||||
select STM32F7_STM32F74XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -748,6 +752,7 @@ config STM32F7_STM32F765XX
|
||||
select STM32F7_STM32F76XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -797,6 +802,7 @@ config STM32F7_STM32F768XX # Revisit Wehn parts released
|
||||
select STM32F7_STM32F76XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -823,6 +829,7 @@ config STM32F7_STM32F768AX # Revisit When parts released
|
||||
select STM32F7_STM32F76XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -848,6 +855,7 @@ config STM32F7_STM32F769XX
|
||||
select STM32F7_STM32F76XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -874,6 +882,7 @@ config STM32F7_STM32F769AX # Revisit When parts released
|
||||
select STM32F7_STM32F76XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -899,6 +908,7 @@ config STM32F7_STM32F777XX
|
||||
select STM32F7_STM32F77XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -927,6 +937,7 @@ config STM32F7_STM32F778XX # Revisit when parts released
|
||||
select STM32F7_STM32F77XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -955,6 +966,7 @@ config STM32F7_STM32F778AX
|
||||
select STM32F7_STM32F77XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -982,6 +994,7 @@ config STM32F7_STM32F779XX
|
||||
select STM32F7_STM32F77XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
@ -1010,6 +1023,7 @@ config STM32F7_STM32F779AX
|
||||
select STM32F7_STM32F77XX
|
||||
select ARCH_HAVE_FPU
|
||||
select ARCH_HAVE_DPFPU
|
||||
select ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
select ARMV7M_HAVE_ICACHE
|
||||
select ARMV7M_HAVE_DCACHE
|
||||
select ARMV7M_HAVE_ITCM
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2009, 2011-2018 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
* Bob Feretich <bob.feretich@rafresearch.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -63,6 +64,7 @@
|
||||
#include "chip.h"
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "stm32_dtcm.h"
|
||||
#include "stm32_dma.h"
|
||||
#include "stm32_gpio.h"
|
||||
#include "stm32_sdmmc.h"
|
||||
@ -563,7 +565,11 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
|
||||
FAR uint8_t *buffer, size_t buflen);
|
||||
static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen);
|
||||
#ifdef CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
static int stm32_dmadelydinvldt(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen);
|
||||
#endif
|
||||
#endif /* CONFIG_STM32F7_SDMMC_DMA */
|
||||
|
||||
/* Initialization/uninitialization/reset ************************************/
|
||||
|
||||
@ -612,14 +618,17 @@ struct stm32_dev_s g_sdmmcdev1 =
|
||||
#endif
|
||||
.dmarecvsetup = stm32_dmarecvsetup,
|
||||
.dmasendsetup = stm32_dmasendsetup,
|
||||
#else
|
||||
#ifdef CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
.dmadelydinvldt = stm32_dmadelydinvldt,
|
||||
#endif
|
||||
#lse
|
||||
#ifdef CONFIG_ARCH_HAVE_SDIO_PREFLIGHT
|
||||
.dmapreflight = NULL,
|
||||
#endif
|
||||
.dmarecvsetup = stm32_recvsetup,
|
||||
.dmasendsetup = stm32_sendsetup,
|
||||
#endif
|
||||
#endif
|
||||
#endif /* CONFIG_STM32F7_SDMMC_DMA */
|
||||
#endif /* CONFIG_SDIO_DMA*/
|
||||
},
|
||||
.base = STM32_SDMMC1_BASE,
|
||||
.nirq = STM32_IRQ_SDMMC1,
|
||||
@ -687,6 +696,9 @@ struct stm32_dev_s g_sdmmcdev2 =
|
||||
#endif
|
||||
.dmarecvsetup = stm32_dmarecvsetup,
|
||||
.dmasendsetup = stm32_dmasendsetup,
|
||||
#ifdef CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
.dmadelydinvldt = stm32_dmadelydinvldt,
|
||||
#endif
|
||||
#endif
|
||||
},
|
||||
.base = STM32_SDMMC2_BASE,
|
||||
@ -2524,7 +2536,7 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
|
||||
else if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1_RESPONSE &&
|
||||
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1B_RESPONSE &&
|
||||
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R5_RESPONSE &&
|
||||
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R5_RESPONSE &&
|
||||
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R6_RESPONSE)
|
||||
{
|
||||
mcerr("ERROR: Wrong response CMD=%08x\n", cmd);
|
||||
@ -3055,7 +3067,12 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
|
||||
/* Force RAM reread */
|
||||
|
||||
arch_invalidate_dcache((uintptr_t)buffer,(uintptr_t)buffer + buflen);
|
||||
if ((uintptr_t)buffer < DTCM_START || (uintptr_t)buffer + buflen > DTCM_END)
|
||||
{
|
||||
#if !defined(CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT)
|
||||
arch_invalidate_dcache_by_addr((uintptr_t)buffer,(uintptr_t)buffer + buflen);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Start the DMA */
|
||||
|
||||
@ -3121,9 +3138,16 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||
stm32_sampleinit();
|
||||
stm32_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
|
||||
/* Flush cache to physical memory */
|
||||
/* Flush cache to physical memory when not in DTCM memory */
|
||||
|
||||
arch_flush_dcache((uintptr_t)buffer, (uintptr_t)buffer + buflen);
|
||||
if ((uintptr_t)buffer < DTCM_START || (uintptr_t)buffer + buflen > DTCM_END)
|
||||
{
|
||||
#ifdef CONFIG_ARMV7M_DCACHE_WRITETHROUGH
|
||||
arch_invalidate_dcache_by_addr((uintptr_t)buffer, (uintptr_t)buffer + buflen);
|
||||
#else
|
||||
arch_flush_dcache((uintptr_t)buffer, (uintptr_t)buffer + buflen);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Save the source buffer information for use by the interrupt handler */
|
||||
|
||||
@ -3158,6 +3182,42 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dmadelydinvldt
|
||||
*
|
||||
* Description:
|
||||
* Delayed D-cache invalidation.
|
||||
* This function should be called after receive DMA completion to perform
|
||||
* D-cache invalidation. This eliminates the need for cache aligned DMA
|
||||
* buffers when the D-cache is in store-through mode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
* buffer - The memory to DMA into
|
||||
* buflen - The size of the DMA transfer in bytes
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32F7_SDMMC_DMA
|
||||
static int stm32_dmadelydinvldt(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
/* Invaliate cache to physical memory when not in DTCM memory. */
|
||||
|
||||
if ((uintptr_t)buffer < DTCM_START ||
|
||||
(uintptr_t)buffer + buflen > DTCM_END)
|
||||
{
|
||||
arch_invalidate_dcache_by_addr((uintptr_t)buffer,
|
||||
(uintptr_t)buffer + buflen);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Initialization/uninitialization/reset
|
||||
****************************************************************************/
|
||||
|
@ -237,6 +237,10 @@ config ARCH_HAVE_SDIO_PREFLIGHT
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
bool
|
||||
default n
|
||||
|
||||
menuconfig MMCSD
|
||||
bool "MMC/SD Driver Support"
|
||||
default n
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2009-2013, 2016-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Bob Feretich <bob.fereich@rafresearch.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -1408,6 +1409,9 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR,
|
||||
MMCSD_BLOCK_RDATADELAY);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
SDIO_DMADELYDINVLDT(priv->dev, buffer, priv->blocksize);
|
||||
#endif
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: CMD17 transfer failed: %d\n", ret);
|
||||
@ -1550,6 +1554,10 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
|
||||
/* Send STOP_TRANSMISSION */
|
||||
|
||||
ret = mmcsd_stoptransmission(priv);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
SDIO_DMADELYDINVLDT(priv->dev, buffer, priv->blocksize * nblocks);
|
||||
#endif
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
|
||||
@ -1794,6 +1802,8 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
*
|
||||
* Description:
|
||||
* Write multiple, contiguous blocks of data to the physical device.
|
||||
* This function expects that the data to be written is contained in
|
||||
* one large buffer that is pointed to by buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -814,6 +814,31 @@
|
||||
# define SDIO_DMARECVSETUP(dev,buffer,len) (-ENOSYS)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_DMADELYDINVLDT
|
||||
*
|
||||
* Description:
|
||||
* Delayed D-cache invalidation.
|
||||
* This function should be called after receive DMA completion to perform
|
||||
* D-cache invalidation. This eliminates the need for cache aligned DMA
|
||||
* buffers when the D-cache is in store-through mode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
* buffer - The memory to DMA from
|
||||
* buflen - The size of the DMA transfer in bytes
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT)
|
||||
# define SDIO_DMADELYDINVLDT(dev,buffer,len) ((dev)->dmadelydinvldt(dev,buffer,len))
|
||||
#else
|
||||
# define SDIO_DMADELYDINVLDT(dev,buffer,len) (OK)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_DMASENDSETUP
|
||||
*
|
||||
@ -949,7 +974,11 @@ struct sdio_dev_s
|
||||
size_t buflen);
|
||||
int (*dmasendsetup)(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen);
|
||||
#ifdef CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT
|
||||
int (*dmadelydinvldt)(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen);
|
||||
#endif
|
||||
#endif /* CONFIG_SDIO_DMA */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user