arch/arm/imxrt: Support imxrt118x in the uSDHC driver

- Add the missing clock gating macros for imxrt118x
- Change sw_cd_gpio from int32_t to gpio_pinset_t (64-bits on 118x)
- Invalidate cache again after the data has been received. Cache might
  be refilled by a prefetch or, in theory, by cpu read touching the same
  cache line - even though the latter should not happen.
- Map any DMA accesses to/from DTCM to the shadow address window, which
  gives the uSDHC DMA access to the DTCM.

Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
Jukka Laitinen 2026-10-05 14:47:59 +03:00 • committed by Xiang Xiao
parent 87ae65fa6e
commit f5edfc61df
2 changed files with 32 additions and 6 deletions

View file

@ -275,6 +275,9 @@ EXTERN const struct clock_configuration_s g_initial_clkconfig;
#define imxrt_clockoff_lpspi5() imxrt_ccm_gate_on(CCM_LPCG_LPSPI5, false)
#define imxrt_clockoff_lpspi6() imxrt_ccm_gate_on(CCM_LPCG_LPSPI6, false)
#define imxrt_clockall_usdhc1() imxrt_ccm_gate_on(CCM_LPCG_USDHC1, true)
#define imxrt_clockall_usdhc2() imxrt_ccm_gate_on(CCM_LPCG_USDHC2, true)
#define imxrt_clockall_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, true)
#define imxrt_clockoff_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, false)
#define imxrt_clockrun_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, true)

View file

@ -49,6 +49,7 @@
#include "arm_internal.h"
#include "imxrt_config.h"
#include "imxrt_gpio.h"
#include "imxrt_dtcm.h"
#include "hardware/imxrt_pinmux.h"
#include "hardware/imxrt_ccm.h"
#include "imxrt_periphclks.h"
@ -198,7 +199,7 @@ struct imxrt_dev_s
void *do_sdio_arg; /* arg for SDIO card ISR */
uint32_t addr; /* Base address of this instances */
uint32_t sw_cd_gpio; /* If a non USDHCx CD pin is used,
gpio_pinset_t sw_cd_gpio; /* If a non USDHCx CD pin is used,
* this is its GPIO */
uint32_t cd_invert; /* If true invert the CD pin */
};
@ -1037,6 +1038,9 @@ static void imxrt_recvdma(struct imxrt_dev_s *priv)
{
/* In an aligned case, we have always received all blocks */
up_invalidate_dcache((uintptr_t)priv->buffer,
(uintptr_t)priv->buffer + priv->remaining);
priv->remaining = 0;
}
@ -3005,6 +3009,8 @@ static int imxrt_dmarecvsetup(struct sdio_dev_s *dev,
uint8_t *buffer, size_t buflen)
{
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev;
uint32_t dma_address;
bool ok;
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
#if defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
@ -3062,19 +3068,28 @@ static int imxrt_dmarecvsetup(struct sdio_dev_s *dev,
/* Configure the RX DMA */
imxrt_configxfrints(priv, USDHC_DMADONE_INTS);
#if defined(CONFIG_ARMV7M_DCACHE)
if (priv->unaligned_rx)
{
putreg32((uint32_t) priv->rxbuffer,
priv->addr + IMXRT_USDHC_DSADDR_OFFSET);
ok = imxrt_dma_address(priv->rxbuffer, priv->blocksize,
&dma_address);
}
else
#endif
{
putreg32((uint32_t) priv->buffer,
priv->addr + IMXRT_USDHC_DSADDR_OFFSET);
ok = imxrt_dma_address(priv->buffer, buflen, &dma_address);
}
if (!ok)
{
mcerr("ERROR: buffer %p (len %zu) is not DMA-reachable\n",
priv->buffer, buflen);
return -EFAULT;
}
putreg32(dma_address, priv->addr + IMXRT_USDHC_DSADDR_OFFSET);
/* Sample the register state */
imxrt_sample(priv, SAMPLENDX_AFTER_SETUP);
@ -3106,6 +3121,7 @@ static int imxrt_dmasendsetup(struct sdio_dev_s *dev,
const uint8_t *buffer, size_t buflen)
{
struct imxrt_dev_s *priv = (struct imxrt_dev_s *)dev;
uint32_t dma_address;
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
DEBUGASSERT(((uint32_t) buffer & 3) == 0);
@ -3136,7 +3152,14 @@ static int imxrt_dmasendsetup(struct sdio_dev_s *dev,
/* Configure the TX DMA */
putreg32((uint32_t) buffer, priv->addr + IMXRT_USDHC_DSADDR_OFFSET);
if (!imxrt_dma_address(buffer, buflen, &dma_address))
{
mcerr("ERROR: buffer %p (len %zu) is not DMA-reachable\n",
buffer, buflen);
return -EFAULT;
}
putreg32(dma_address, priv->addr + IMXRT_USDHC_DSADDR_OFFSET);
/* Sample the register state */