arc/arm/imxrt/imxrt_usbdev.c: Fix for imxrt118x-evk

- Move/make sure that ep0buf is in usb dma capable memory. Especially if
  .data/.bss are in TCM, the buffers need to be placed in another section.
  If the section .dmamemory doesn't exist, they will end up in .data like before
- change "#ifdef CONFIG_ARCH_FAMILY_IMXRT117x" into
  "#if defined(CONFIG_ARCH_FAMILY_IMXRT117x) || defined(CONFIG_ARCH_FAMILY_IMXRT118x)"
- In imxrt_epcomplete dtd->buffer0 must NOT be used to compute the data buffer's
  cache-maintenance address range. The hardware advances buffer0 (and its
  "current offset" low-order bits) as the transfer progresses, so by completion
  time it points *past* the start of the buffer (at start + xfer_len), not at
  the buffer itself. Instead, use the original privreq->req.buf when the transfer
  is complete.

Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
Jukka Laitinen 2026-09-09 12:52:34 +03:00 • committed by Xiang Xiao
parent cb731d7791
commit 3693257175
2 changed files with 56 additions and 7 deletions

View file

@ -36,11 +36,14 @@
#define IMXRT_USBPHY_BASE_OFFSET 0x1000 /* USB1 PHY Base */
/* Simple hack to get iMXRT117x working with same macro */
/* Simple hack to get iMXRT117x/iMXRT118x working with same macro */
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
# define IMXRT_ANATOP_BASE 0x40433000 /* ANATOP doesn't exist on rt117x, it is used this way here only to make the code compatible */
# define IMXRT_USBPHY_SHIFT 0x4000
#elif defined(CONFIG_ARCH_FAMILY_IMXRT118x)
# define IMXRT_ANATOP_BASE (IMXRT_USBPHY1_BASE - IMXRT_USBPHY_BASE_OFFSET) /* ANATOP doesn't exist on rt118x */
# define IMXRT_USBPHY_SHIFT 0x10000
#else
# define IMXRT_USBPHY_SHIFT 0x1000
#endif

View file

@ -207,11 +207,21 @@ const struct trace_msg_t g_usb_trace_strings_intdecode[] =
#endif
#if defined(CONFIG_ARMV7M_DCACHE)
# define cache_aligned_alloc(s) kmm_memalign(ARMV7M_DCACHE_LINESIZE,(s))
# define cache_aligned_alloc(s) \
kmm_memalign(ARMV7M_DCACHE_LINESIZE, \
(((s) + ARMV7M_DCACHE_LINESIZE - 1) & \
~(ARMV7M_DCACHE_LINESIZE - 1)))
# define CACHE_ALIGNED_DATA aligned_data(ARMV7M_DCACHE_LINESIZE)
# define DCACHE_LINEMASK (ARMV7M_DCACHE_LINESIZE - 1)
# define DCACHE_ALIGN_UP(a) (((a) + DCACHE_LINEMASK) & ~DCACHE_LINEMASK)
# define IS_CACHE_ALIGNED(x,y) \
(((uintptr_t)(x) & DCACHE_LINEMASK) == 0 && \
((y) & DCACHE_LINEMASK) == 0)
#else
# define cache_aligned_alloc kmm_malloc
# define CACHE_ALIGNED_DATA
# define DCACHE_ALIGN_UP(a) (a)
# define IS_CACHE_ALIGNED(x,y) (true)
#endif
/* Hardware interface *******************************************************/
@ -369,7 +379,7 @@ struct imxrt_usbdev_s
uint8_t ep0state; /* State of certain EP0 operations */
/* buffer for EP0 short transfers */
uint8_t ep0buf[64] CACHE_ALIGNED_DATA;
uint8_t *ep0buf;
uint8_t paddr; /* Address assigned by SETADDRESS */
uint8_t stalled:1; /* 1: Protocol stalled */
uint8_t selfpowered:1; /* 1: Device is self powered */
@ -390,6 +400,8 @@ struct imxrt_usbdev_s
struct imxrt_ep_s eplist[IMXRT_NPHYSENDPOINTS];
};
#define IMXRT_EP0BUF_SIZE 64 /* Size of the EP0 short transfer buffer */
#define EP0STATE_IDLE 0 /* Idle State, leave on receiving a setup packet or epsubmit */
#define EP0STATE_SETUP_OUT 1 /* Setup Packet received - SET/CLEAR */
#define EP0STATE_SETUP_IN 2 /* Setup Packet received - GET */
@ -513,12 +525,34 @@ static int imxrt_pullup(struct usbdev_s *dev, bool enable);
static struct imxrt_usbdev_s g_usbdev;
/* Normally g_qh, g_td and g_ep0buf are statically allocated in .bss.
* But they need to be DMA-capable for usb engine to access them. If we
* run with TCM memory as the primary, there has to be another memory
* segment elsewhere, in DMA capable memory (.dmamemory). Also we must have
* USBDEV_DMAMEMORY enabled to be able to dynamically allocate from there.
*/
#ifdef CONFIG_IMXRT_TCM_PRIMARY
# ifndef CONFIG_USBDEV_DMAMEMORY
# error "CONFIG_USBDEV_DMAMEMORY must be defined"
# endif
# define USBDEV_DMA_SECTION locate_data(".dmamemory")
#else
# define USBDEV_DMA_SECTION
#endif
static struct imxrt_dqh_s g_qh[IMXRT_NPHYSENDPOINTS]
USBDEV_DMA_SECTION
aligned_data(2048);
static struct imxrt_dtd_s g_td[IMXRT_NPHYSENDPOINTS]
USBDEV_DMA_SECTION
aligned_data(32);
static uint8_t g_ep0buf[IMXRT_EP0BUF_SIZE]
USBDEV_DMA_SECTION
aligned_data(32);
static const struct usbdev_epops_s g_epops =
{
.configure = imxrt_epconfigure,
@ -751,6 +785,11 @@ static inline void imxrt_writedtd(struct imxrt_dtd_s *dtd,
const uint8_t *data,
uint32_t nbytes)
{
#if defined(CONFIG_ARMV7M_DCACHE)
DEBUGASSERT(data == NULL ||
IS_CACHE_ALIGNED(data, DCACHE_ALIGN_UP(nbytes)));
#endif
dtd->nextdesc = DTD_NEXTDESC_INVALID;
dtd->config = DTD_CONFIG_LENGTH(nbytes) | DTD_CONFIG_IOC |
DTD_CONFIG_ACTIVE;
@ -1752,7 +1791,7 @@ static void imxrt_ep0complete(struct imxrt_usbdev_s *priv, uint8_t epphy)
*/
up_invalidate_dcache((uintptr_t)priv->ep0buf,
(uintptr_t)priv->ep0buf + sizeof(priv->ep0buf));
(uintptr_t)priv->ep0buf + IMXRT_EP0BUF_SIZE);
imxrt_dispatchrequest(priv, &priv->ep0ctrl);
imxrt_ep0state(priv, EP0STATE_WAIT_NAK_IN);
@ -1887,8 +1926,6 @@ bool imxrt_epcomplete(struct imxrt_usbdev_s *priv, uint8_t epphy)
up_invalidate_dcache((uintptr_t)dtd,
(uintptr_t)dtd + sizeof(struct imxrt_dtd_s));
up_invalidate_dcache((uintptr_t)dtd->buffer0,
(uintptr_t)dtd->buffer0 + dtd->xfer_len);
int xfrd = dtd->xfer_len - (dtd->config >> 16);
@ -1903,6 +1940,14 @@ bool imxrt_epcomplete(struct imxrt_usbdev_s *priv, uint8_t epphy)
*/
usbtrace(TRACE_INTDECODE(IMXRT_TRACEINTID_EPIN), complete);
/* Invalidate the RX buffer */
DEBUGASSERT(IS_CACHE_ALIGNED(privreq->req.buf,
DCACHE_ALIGN_UP(privreq->req.xfrd)));
up_invalidate_dcache((uintptr_t)privreq->req.buf,
(uintptr_t)privreq->req.buf +
DCACHE_ALIGN_UP(privreq->req.xfrd));
}
else
{
@ -2896,6 +2941,7 @@ void arm_usbinitialize(void)
priv->usbdev.ops = &g_devops;
priv->usbdev.ep0 = &priv->eplist[IMXRT_EP0_IN].ep;
priv->epavail = IMXRT_EPALLSET & ~IMXRT_EPCTRLSET;
priv->ep0buf = g_ep0buf;
/* Initialize the endpoint list */
@ -2950,7 +2996,7 @@ void arm_usbinitialize(void)
imxrt_clockall_usboh3();
#ifdef CONFIG_ARCH_FAMILY_IMXRT117x
#if defined(CONFIG_ARCH_FAMILY_IMXRT117x) || defined(CONFIG_ARCH_FAMILY_IMXRT118x)
up_mdelay(1);
putreg32(USBPHY_PLL_SIC_PLL_POWER |