arch/arm/imxrt: Initial modification to support two USB Controllers

Many iMXRT MCUs have internally two USB OTG controllers, however
NuttX currently only supports one USB controllers. This patch will
prepare the "house" to support both ports at same time.

Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit is contained in:
Alan Carvalho de Assis 2025-07-29 18:13:36 -03:00 committed by Alin Jerpelea
parent d2282ec26a
commit 59dc9a3884
3 changed files with 139 additions and 41 deletions

View file

@ -15,69 +15,95 @@ choice
config ARCH_CHIP_MIMXRT1021CAG4A
bool "MIMXRT1021CAG4A"
select ARCH_FAMILY_MIMXRT1021C
select IMXRT_HAVE_USBOTG1
config ARCH_CHIP_MIMXRT1021CAF4A
bool "MIMXRT1021CAF4A"
select ARCH_FAMILY_MIMXRT1021C
select IMXRT_HAVE_USBOTG1
config ARCH_CHIP_MIMXRT1021DAF5A
bool "MIMXRT1021DAF5A"
select ARCH_FAMILY_MIMXRT1021D
select IMXRT_HAVE_USBOTG1
config ARCH_CHIP_MIMXRT1021DAG5A
bool "MIMXRT1021DAG5A"
select ARCH_FAMILY_MIMXRT1021D
select IMXRT_HAVE_USBOTG1
config ARCH_CHIP_MIMXRT1051DVL6A
bool "MIMXRT1051DVL6A"
select ARCH_FAMILY_MIMXRT105xDVL6A
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1051CVL5A
bool "MIMXRT1051CVL5A"
select ARCH_FAMILY_MIMXRT105xCVL5A
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1052DVL6A
bool "MIMXRT1052DVL6A"
select ARCH_FAMILY_MIMXRT105xDVL6A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1052CVL5A
bool "MIMXRT1052CVL5A"
select ARCH_FAMILY_MIMXRT105xCVL5A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1061DVL6A
bool "MIMXRT1061DVL6A"
select ARCH_FAMILY_MXRT106xDVL6A
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1061CVL5A
bool "MIMXRT1061CVL5A"
select ARCH_FAMILY_MIMXRT106xCVL5A
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1062DVL6A
bool "MIMXRT1062DVL6A"
select ARCH_FAMILY_MXRT106xDVL6A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1062CVL5A
bool "MIMXRT1062DVL6A"
select ARCH_FAMILY_MIMXRT106xCVL5A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1064DVL6A
bool "MIMXRT1064DVL6A"
select ARCH_FAMILY_MXRT106xDVL6A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1064CVL5A
bool "MIMXRT1064DVL6A"
select ARCH_FAMILY_MIMXRT106xCVL5A
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
config ARCH_CHIP_MIMXRT1176DVMAA
bool "MIMXRT1176DVMAA"
select ARCH_FAMILY_IMXRT117x
select IMXRT_HAVE_LCD
select IMXRT_HAVE_USBOTG1
select IMXRT_HAVE_USBOTG2
endchoice # i.MX RT Chip Selection
@ -333,9 +359,19 @@ config IMXRT_EDMA
default n
select ARCH_DMA
config IMXRT_USBOTG
bool "USB EHCI"
config IMXRT_USBOTG1
bool "USB EHCI OTG1"
default n
depends on IMXRT_HAVE_USBOTG1
select IMXRT_USBOTG
select USBHOST_HAVE_ASYNCH if USBHOST
select USBHOST_ASYNCH
config IMXRT_USBOTG2
bool "USB EHCI OTG2: NOT SUPPORTED YET"
default n
depends on IMXRT_HAVE_USBOTG2
select IMXRT_USBOTG
select USBHOST_HAVE_ASYNCH if USBHOST
select USBHOST_ASYNCH
@ -3088,25 +3124,25 @@ endif # SCHED_TICKLESS
endmenu # Timer Configuration
if IMXRT_USBOTG && USBHOST
if IMXRT_USBOTG1 && USBHOST
menu "USB host controller driver (HCD) options"
menu "USB OTG1 Host Controller Driver (HCD) options"
config IMXRT_EHCI_NQHS
config IMXRT_EHCI_USB1_NQHS
int "Number of Queue Head (QH) structures"
default 4
---help---
Configurable number of Queue Head (QH) structures. The default is
one per Root hub port plus one for EP0 (4).
config IMXRT_EHCI_NQTDS
config IMXRT_EHCI_USB1_NQTDS
int "Number of Queue Element Transfer Descriptor (qTDs)"
default 6
---help---
Configurable number of Queue Element Transfer Descriptor (qTDs).
The default is one per root hub plus three from EP0 (6).
config IMXRT_EHCI_BUFSIZE
config IMXRT_EHCI_USB1_BUFSIZE
int "Size of one request/descriptor buffer"
default 128
---help---
@ -3114,7 +3150,7 @@ config IMXRT_EHCI_BUFSIZE
size must be an even number of 32-bit words and must be large enough
to hangle the largest transfer via a SETUP request.
config IMXRT_EHCI_PREALLOCATE
config IMXRT_EHCI_USB1_PREALLOCATE
bool "Preallocate descriptor pool"
default y
---help---
@ -3123,7 +3159,44 @@ config IMXRT_EHCI_PREALLOCATE
dynamically allocated using kmm_memalign().
endmenu # USB host controller driver (HCD) options
endif # IMXRT_USBOTG && USBHOST
endif # IMXRT_USBOTG1 && USBHOST
if IMXRT_USBOTG2 && USBHOST
menu "USB OTG2 Host Controller Driver (HCD) options: NOT SUPPORTED YET"
config IMXRT_EHCI_USB2_NQHS
int "Number of Queue Head (QH) structures"
default 4
---help---
Configurable number of Queue Head (QH) structures. The default is
one per Root hub port plus one for EP0 (4).
config IMXRT_EHCI_USB2_NQTDS
int "Number of Queue Element Transfer Descriptor (qTDs)"
default 6
---help---
Configurable number of Queue Element Transfer Descriptor (qTDs).
The default is one per root hub plus three from EP0 (6).
config IMXRT_EHCI_USB2_BUFSIZE
int "Size of one request/descriptor buffer"
default 128
---help---
The size of one request/descriptor buffer in bytes. The TD buffe
size must be an even number of 32-bit words and must be large enough
to hangle the largest transfer via a SETUP request.
config IMXRT_EHCI_USB2_PREALLOCATE
bool "Preallocate descriptor pool"
default y
---help---
Select this option to pre-allocate EHCI queue and descriptor
structure pools in .bss. Otherwise, these pools will be
dynamically allocated using kmm_memalign().
endmenu # USB host controller driver (HCD) options
endif # IMXRT_USBOTG2
if IMXRT_USBDEV

View file

@ -242,7 +242,7 @@ static void imxrt_pllsetup(void)
{
}
/* Init USB PLL3 */
/* Init USB1 PLL3 */
/* capture it's original value */
@ -267,6 +267,31 @@ static void imxrt_pllsetup(void)
putreg32(pll3reg, IMXRT_CCM_ANALOG_PFD_480);
#ifdef CONFIG_IMXRT_USBOTG2
/* Init USB2 PLL */
/* Enable the USB2 PLL */
reg = getreg32(IMXRT_CCM_ANALOG_PLL_USB2);
reg |= IMXRT_USB2_PLL_DIV_SELECT |
CCM_ANALOG_PLL_USB2_ENABLE |
CCM_ANALOG_PLL_USB2_EN_USB_CLKS |
CCM_ANALOG_PLL_USB2_POWER |
CCM_ANALOG_PLL_USB2_DIV_SELECT_20;
putreg32(reg, IMXRT_CCM_ANALOG_PLL_USB2);
while ((getreg32(IMXRT_CCM_ANALOG_PLL_USB2) &
CCM_ANALOG_PLL_USB2_LOCK) == 0)
{
}
/* Disable bypass */
reg = getreg32(IMXRT_CCM_ANALOG_PLL_USB2);
reg &= ~CCM_ANALOG_PLL_USB2_BYPASS;
putreg32(reg, IMXRT_CCM_ANALOG_PLL_USB2);
#endif
#ifdef CONFIG_IMXRT_LCD
/* Init Video PLL5 */

View file

@ -71,16 +71,16 @@
* Root hub port plus one for EP0.
*/
#ifndef CONFIG_IMXRT_EHCI_NQHS
# define CONFIG_IMXRT_EHCI_NQHS (IMXRT_EHCI_NRHPORT + 1)
#ifndef CONFIG_IMXRT_EHCI_USB1_NQHS
# define CONFIG_IMXRT_EHCI_USB1_NQHS (IMXRT_EHCI_NRHPORT + 1)
#endif
/* Configurable number of Queue Element Transfer Descriptor (qTDs). The
* default is one per root hub plus three from EP0.
*/
#ifndef CONFIG_IMXRT_EHCI_NQTDS
# define CONFIG_IMXRT_EHCI_NQTDS (IMXRT_EHCI_NRHPORT + 3)
#ifndef CONFIG_IMXRT_EHCI_USB1_NQTDS
# define CONFIG_IMXRT_EHCI_USB1_NQTDS (IMXRT_EHCI_NRHPORT + 3)
#endif
/* Buffers must be aligned to the cache line size */
@ -89,17 +89,17 @@
/* Configurable size of a request/descriptor buffers */
#ifndef CONFIG_IMXRT_EHCI_BUFSIZE
# define CONFIG_IMXRT_EHCI_BUFSIZE 128
#ifndef CONFIG_IMXRT_EHCI_USB1_BUFSIZE
# define CONFIG_IMXRT_EHCI_USB1_BUFSIZE 128
#endif
#define IMXRT_EHCI_BUFSIZE \
((CONFIG_IMXRT_EHCI_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK)
((CONFIG_IMXRT_EHCI_USB1_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK)
/* Debug options */
#ifndef CONFIG_DEBUG_USB_INFO
# undef CONFIG_IMXRT_EHCI_REGDEBUG
# undef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
#endif
/* Isochronous transfers are not currently supported */
@ -407,7 +407,7 @@ static uint32_t imxrt_swap32(uint32_t value);
# define imxrt_swap32(value) (value)
#endif
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_printreg(volatile uint32_t *regaddr, uint32_t regval,
bool iswrite);
static void imxrt_checkreg(volatile uint32_t *regaddr, uint32_t regval,
@ -451,7 +451,7 @@ static int imxrt_qh_flush(struct imxrt_qh_s *qh);
/* Endpoint Transfer Handling ***********************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_qtd_print(struct imxrt_qtd_s *qtd);
static void imxrt_qh_print(struct imxrt_qh_s *qh);
static int imxrt_qtd_dump(struct imxrt_qtd_s *qtd, uint32_t **bp, void *arg);
@ -604,26 +604,26 @@ static struct imxrt_qh_s g_intrhead aligned_data(32);
/* The frame list */
#ifdef CONFIG_IMXRT_EHCI_PREALLOCATE
#ifdef CONFIG_IMXRT_EHCI_USB1_PREALLOCATE
static uint32_t g_framelist[FRAME_LIST_SIZE] aligned_data(4096);
#else
static uint32_t *g_framelist;
#endif
#endif /* CONFIG_USBHOST_INT_DISABLE */
#ifdef CONFIG_IMXRT_EHCI_PREALLOCATE
#ifdef CONFIG_IMXRT_EHCI_USB1_PREALLOCATE
/* Pools of pre-allocated data structures. These will all be linked into the
* free lists within g_ehci. These must all be aligned to 32-byte boundaries
*/
/* Queue Head (QH) pool */
static struct imxrt_qh_s g_qhpool[CONFIG_IMXRT_EHCI_NQHS]
static struct imxrt_qh_s g_qhpool[CONFIG_IMXRT_EHCI_USB1_NQHS]
aligned_data(32);
/* Queue Element Transfer Descriptor (qTD) pool */
static struct imxrt_qtd_s g_qtdpool[CONFIG_IMXRT_EHCI_NQTDS]
static struct imxrt_qtd_s g_qtdpool[CONFIG_IMXRT_EHCI_USB1_NQTDS]
aligned_data(32);
#else
@ -884,7 +884,7 @@ static uint32_t imxrt_swap32(uint32_t value)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_printreg(volatile uint32_t *regaddr, uint32_t regval,
bool iswrite)
{
@ -901,7 +901,7 @@ static void imxrt_printreg(volatile uint32_t *regaddr, uint32_t regval,
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_checkreg(volatile uint32_t *regaddr, uint32_t regval,
bool iswrite)
{
@ -966,7 +966,7 @@ static void imxrt_checkreg(volatile uint32_t *regaddr, uint32_t regval,
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static uint32_t imxrt_getreg(volatile uint32_t *regaddr)
{
/* Read the value from the register */
@ -993,7 +993,7 @@ static inline uint32_t imxrt_getreg(volatile uint32_t *regaddr)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_putreg(uint32_t regval, volatile uint32_t *regaddr)
{
/* Check if we need to print this value */
@ -1477,7 +1477,7 @@ static int imxrt_qh_flush(struct imxrt_qh_s *qh)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_qtd_print(struct imxrt_qtd_s *qtd)
{
uinfo(" QTD[%p]:\n", qtd);
@ -1498,7 +1498,7 @@ static void imxrt_qtd_print(struct imxrt_qtd_s *qtd)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static void imxrt_qh_print(struct imxrt_qh_s *qh)
{
struct imxrt_epinfo_s *epinfo;
@ -1541,7 +1541,7 @@ static void imxrt_qh_print(struct imxrt_qh_s *qh)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static int imxrt_qtd_dump(struct imxrt_qtd_s *qtd, uint32_t **bp, void *arg)
{
imxrt_qtd_print(qtd);
@ -1558,7 +1558,7 @@ static int imxrt_qtd_dump(struct imxrt_qtd_s *qtd, uint32_t **bp, void *arg)
*
****************************************************************************/
#ifdef CONFIG_IMXRT_EHCI_REGDEBUG
#ifdef CONFIG_IMXRT_EHCI_USB1_REGDEBUG
static int imxrt_qh_dump(struct imxrt_qh_s *qh, uint32_t **bp, void *arg)
{
imxrt_qh_print(qh);
@ -4988,7 +4988,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
DEBUGASSERT((sizeof(struct imxrt_qh_s) & 0x1f) == 0);
DEBUGASSERT((sizeof(struct imxrt_qtd_s) & 0x1f) == 0);
# ifdef CONFIG_IMXRT_EHCI_PREALLOCATE
# ifdef CONFIG_IMXRT_EHCI_USB1_PREALLOCATE
DEBUGASSERT(((uintptr_t)&g_qhpool & 0x1f) == 0);
DEBUGASSERT(((uintptr_t)&g_qtdpool & 0x1f) == 0);
# endif
@ -5058,7 +5058,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
# ifndef CONFIG_IMXRT_EHCI_PREALLOCATE
/* Allocate a pool of free Queue Head (QH) structures */
g_qhpool = kmm_memalign(32, CONFIG_IMXRT_EHCI_NQHS *
g_qhpool = kmm_memalign(32, CONFIG_IMXRT_EHCI_USB1_NQHS *
sizeof(struct imxrt_qh_s));
if (!g_qhpool)
{
@ -5069,17 +5069,17 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
/* Initialize the list of free Queue Head (QH) structures */
for (i = 0; i < CONFIG_IMXRT_EHCI_NQHS; i++)
for (i = 0; i < CONFIG_IMXRT_EHCI_USB1_NQHS; i++)
{
/* Put the QH structure in a free list */
imxrt_qh_free(&g_qhpool[i]);
}
# ifndef CONFIG_IMXRT_EHCI_PREALLOCATE
# ifndef CONFIG_IMXRT_EHCI_USB1_PREALLOCATE
/* Allocate a pool of free Transfer Descriptor (qTD) structures */
g_qtdpool = kmm_memalign(32, CONFIG_IMXRT_EHCI_NQTDS *
g_qtdpool = kmm_memalign(32, CONFIG_IMXRT_EHCI_USB1_NQTDS *
sizeof(struct imxrt_qtd_s));
if (!g_qtdpool)
{
@ -5089,7 +5089,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
}
# endif
# if !defined(CONFIG_IMXRT_EHCI_PREALLOCATE) && !defined(CONFIG_USBHOST_INT_DISABLE)
# if !defined(CONFIG_IMXRT_EHCI_USB1_PREALLOCATE) && !defined(CONFIG_USBHOST_INT_DISABLE)
/* Allocate the periodic framelist */
g_framelist = kmm_memalign(4096, FRAME_LIST_SIZE * sizeof(uint32_t));
@ -5104,7 +5104,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
/* Initialize the list of free Transfer Descriptor (qTD) structures */
for (i = 0; i < CONFIG_IMXRT_EHCI_NQTDS; i++)
for (i = 0; i < CONFIG_IMXRT_EHCI_USB1_NQTDS; i++)
{
/* Put the TD in a free list */
@ -5127,7 +5127,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
* some performance.
*/
# ifdef CONFIG_IMXRT_EHCI_SDIS
# ifdef CONFIG_IMXRT_EHCI_USB1_SDIS
putreg32(USBHOST_USBMODE_CM_HOST | USBHOST_USBMODE_SDIS |
USBHOST_USBMODE_VBPS, IMXRT_USBDEV_USBMODE);
# else
@ -5149,7 +5149,7 @@ struct usbhost_connection_s *imxrt_ehci_initialize(int controller)
* host configuration in the reset.
*/
# ifdef CONFIG_IMXRT_EHCI_SDIS
# ifdef CONFIG_IMXRT_EHCI_USB1_SDIS
putreg32(USBHOST_USBMODE_CM_HOST | USBHOST_USBMODE_SDIS |
USBHOST_USBMODE_VBPS, IMXRT_USBDEV_USBMODE);
# else