mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 01:53:51 +01:00
Merge pull request #18776 from gschorcht/pkg/tinyusb_otg_hs_ulpi
pkg/tinyusb: add ULPI and UTMI+ HS PHY support for STM32 USB OTG HS ports
This commit is contained in:
commit
21956db2fd
@ -24,6 +24,7 @@ config BOARD_STM32F746G_DISCO
|
||||
select HAS_PERIPH_UART
|
||||
select HAS_PERIPH_USBDEV
|
||||
select HAS_PERIPH_USBDEV_HS_ULPI
|
||||
select HAS_TINYUSB_DEVICE
|
||||
|
||||
# Clock configuration
|
||||
select BOARD_HAS_HSE
|
||||
|
||||
@ -10,6 +10,7 @@ FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_usbdev
|
||||
FEATURES_PROVIDED += periph_usbdev_hs_ulpi
|
||||
FEATURES_PROVIDED += tinyusb_device
|
||||
|
||||
# stm32f746g-disco provides a custom default Kconfig clock configuration
|
||||
KCONFIG_BOARD_CONFIG += $(RIOTBOARD)/stm32f746g-disco/clock.config
|
||||
|
||||
@ -24,6 +24,7 @@ config BOARD_STM32F7508_DK
|
||||
select HAS_PERIPH_UART
|
||||
select HAS_PERIPH_USBDEV
|
||||
select HAS_PERIPH_USBDEV_HS_ULPI
|
||||
select HAS_TINYUSB_DEVICE
|
||||
|
||||
# Clock configuration
|
||||
select BOARD_HAS_HSE
|
||||
|
||||
@ -55,6 +55,9 @@ extern "C" {
|
||||
* - In all other cases, both the device and the host stack use port 0.
|
||||
* This also applies if only the USB FS controller is used.
|
||||
*
|
||||
* @warning
|
||||
* - tinyUSB does not support host mode for STM32 MCUs yet.
|
||||
* - tinyUSB does not support to use multiple ports with device stack
|
||||
* @{
|
||||
*/
|
||||
#if defined(DWC2_USB_OTG_HS_ENABLED) && defined(DWC2_USB_OTG_FS_ENABLED)
|
||||
@ -67,6 +70,9 @@ extern "C" {
|
||||
#define TINYUSB_TUH_RHPORT 1
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED)
|
||||
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED)
|
||||
|
||||
#elif defined(DWC2_USB_OTG_HS_ENABLED)
|
||||
|
||||
#ifndef TINYUSB_TUD_RHPORT
|
||||
@ -77,6 +83,13 @@ extern "C" {
|
||||
#define TINYUSB_TUH_RHPORT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since tinyUSB does not support host mode for STM32 MCUs yet, only
|
||||
* OPT_MODE_DEVICE is enabled for the port. Once tinyUSB supports the host mode,
|
||||
* OPT_MODE_HOST could be added to CFG_TUSB_RHPORT1_MODE
|
||||
*/
|
||||
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef TINYUSB_TUD_RHPORT
|
||||
@ -87,6 +100,13 @@ extern "C" {
|
||||
#define TINYUSB_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since tinyUSB does not support host mode for STM32 MCUs yet, only
|
||||
* OPT_MODE_DEVICE is enabled for the port. Once tinyUSB supports the host mode,
|
||||
* OPT_MODE_HOST could be added to CFG_TUSB_RHPORT0_MODE.
|
||||
*/
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED)
|
||||
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
|
||||
@ -80,10 +80,6 @@
|
||||
*/
|
||||
#define CFG_TUD_ENABLED MODULE_TINYUSB_DEVICE
|
||||
|
||||
#ifndef CFG_TUD_MAX_SPEED
|
||||
#define CFG_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
@ -32,50 +32,175 @@ static int tinyusb_hw_init_dev(const dwc2_usb_otg_fshs_config_t *conf)
|
||||
pm_block(STM32_PM_STOP);
|
||||
pm_block(STM32_PM_STANDBY);
|
||||
|
||||
#if defined(PWR_CR2_USV) /* on L4 */
|
||||
/* Validate USB Supply */
|
||||
PWR->CR2 |= PWR_CR2_USV;
|
||||
#endif /* PWR_CR2_USV */
|
||||
|
||||
/* Enable the clock to the peripheral */
|
||||
periph_clk_en(conf->ahb, conf->rcc_mask);
|
||||
|
||||
#ifndef MODULE_PERIPH_USBDEV_HS_ULPI
|
||||
/* Enables clock on the GPIO bus */
|
||||
gpio_init(conf->dp, GPIO_IN);
|
||||
gpio_init(conf->dm, GPIO_IN);
|
||||
/* Configure AF for the pins */
|
||||
gpio_init_af(conf->dp, conf->af);
|
||||
gpio_init_af(conf->dm, conf->af);
|
||||
#endif /* MODULE_PERIPH_USBDEV_HS_ULPI */
|
||||
|
||||
#if 0 /* TODO we don't use USB ID pin for now */
|
||||
gpio_init(conf->id, GPIO_IN);
|
||||
#endif
|
||||
|
||||
#ifdef USB_OTG_GCCFG_NOVBUSSENS
|
||||
#if 0 /* TODO V_USB sensing pin */
|
||||
gpio_init(conf->vbus, GPIO_OD_PU);
|
||||
gpio_init_af(conf->vbus, conf->af);
|
||||
|
||||
USB_OTG_GlobalTypeDef *global_regs =
|
||||
(USB_OTG_GlobalTypeDef *)(conf->periph + USB_OTG_GLOBAL_BASE);
|
||||
|
||||
global_regs->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS;
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
|
||||
#else
|
||||
/* Enable no Vbus sensing and enable `Power Down Disable` */
|
||||
USB_OTG_GlobalTypeDef *global_regs =
|
||||
(USB_OTG_GlobalTypeDef *)(conf->periph + USB_OTG_GLOBAL_BASE);
|
||||
|
||||
#ifdef USB_OTG_GCCFG_NOVBUSSENS
|
||||
/* Enable no Vbus Detect enable and enable `Power Down Disable` */
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS | USB_OTG_GCCFG_PWRDWN;
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
|
||||
#endif
|
||||
#endif /* USB_OTG_GCCFG_NOVBUSSENS */
|
||||
|
||||
#ifdef DWC2_USB_OTG_HS_ENABLED
|
||||
if (conf->type == DWC2_USB_OTG_HS) {
|
||||
/* Disable the ULPI clock in low power mode, this is essential for the
|
||||
* peripheral when using the built-in phy */
|
||||
periph_lpclk_dis(conf->ahb, RCC_AHB1LPENR_OTGHSULPILPEN);
|
||||
/* Only the built-in phy supported for now */
|
||||
assert(conf->phy == DWC2_USB_OTG_PHY_BUILTIN);
|
||||
global_regs->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
|
||||
}
|
||||
if (conf->phy == DWC2_USB_OTG_PHY_BUILTIN) {
|
||||
/* set `Power Down Disable` to activate the on-chip FS transceiver */
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
/* Disable the ULPI clock in low power mode, this is essential for the
|
||||
* peripheral when using the built-in PHY */
|
||||
periph_lpclk_dis(conf->ahb, RCC_AHB1LPENR_OTGHSULPILPEN);
|
||||
/* select on-chip builtin PHY */
|
||||
global_regs->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
|
||||
}
|
||||
#ifdef MODULE_PERIPH_USBDEV_HS_ULPI
|
||||
else if (conf->phy == DWC2_USB_OTG_PHY_ULPI) {
|
||||
/* initialize ULPI interface */
|
||||
gpio_init(conf->ulpi_clk, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d0, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d1, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d2, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d3, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d4, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d5, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d6, GPIO_IN);
|
||||
gpio_init(conf->ulpi_d7, GPIO_IN);
|
||||
gpio_init(conf->ulpi_stp, GPIO_IN);
|
||||
gpio_init(conf->ulpi_dir, GPIO_IN);
|
||||
gpio_init(conf->ulpi_nxt, GPIO_IN);
|
||||
gpio_init_af(conf->ulpi_clk, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d0, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d1, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d2, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d3, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d4, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d5, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d6, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_d7, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_stp, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_dir, conf->ulpi_af);
|
||||
gpio_init_af(conf->ulpi_nxt, conf->ulpi_af);
|
||||
|
||||
/* enable ULPI clock */
|
||||
periph_clk_en(conf->ahb, RCC_AHB1ENR_OTGHSULPIEN);
|
||||
|
||||
#ifdef USB_OTG_GUSBCFG_ULPI_UTMI_SEL
|
||||
/* select ULPI PHY */
|
||||
global_regs->GUSBCFG |= USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
|
||||
#endif
|
||||
#ifdef USB_OTG_GUSBCFG_PHYIF
|
||||
/* use the 8-bit interface */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_PHYIF;
|
||||
#endif /* USB_OTG_GUSBCFG_PHYIF */
|
||||
#ifdef USB_OTG_GUSBCFG_DDRSEL
|
||||
/* use single data rate */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_DDRSEL;
|
||||
#endif /* USB_OTG_GUSBCFG_DDRSEL */
|
||||
|
||||
/* disable the on-chip FS transceiver */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_PHYSEL;
|
||||
|
||||
/* use internal V_BUS valid indicator and internal charge pump */
|
||||
global_regs->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD |
|
||||
USB_OTG_GUSBCFG_ULPIEVBUSI);
|
||||
/* disable ULPI FS/LS serial interface */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPIFSLS;
|
||||
}
|
||||
|
||||
#elif defined(MODULE_PERIPH_USBDEV_HS_UTMI)
|
||||
else if (conf->phy == DWC2_USB_OTG_PHY_UTMI) {
|
||||
/* enable ULPI clock */
|
||||
periph_clk_en(conf->ahb, RCC_AHB1ENR_OTGHSULPIEN);
|
||||
/* enable UTMI HS PHY Controller clock */
|
||||
periph_clk_en(APB2, RCC_APB2ENR_OTGPHYCEN);
|
||||
|
||||
#ifdef USB_OTG_GUSBCFG_ULPI_UTMI_SEL
|
||||
/* select UTMI+ PHY */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
|
||||
#endif /* USB_OTG_GUSBCFG_ULPI_UTMI_SEL */
|
||||
#ifdef USB_OTG_GUSBCFG_PHYIF
|
||||
/* use the 8-bit interface and single data rate */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_PHYIF;
|
||||
#endif /* USB_OTG_GUSBCFG_PHYIF */
|
||||
|
||||
/* disable the on-chip FS transceiver */
|
||||
global_regs->GUSBCFG &= ~USB_OTG_GUSBCFG_PHYSEL;
|
||||
|
||||
/* configure the USB HS PHY Controller (USB_HS_PHYC),
|
||||
* USB_HS_PHYC and GCCFG are STM32 specific */
|
||||
#ifdef USB_HS_PHYC
|
||||
/* enable USB HS PHY Controller */
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_PHYHSEN;
|
||||
|
||||
/* determine the PLL input clock of the USB HS PHY from HSE clock */
|
||||
switch (CLOCK_HSE) {
|
||||
case 12000000:
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL1_PLLSEL_12MHZ;
|
||||
break;
|
||||
case 12500000:
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ;
|
||||
break;
|
||||
case 16000000:
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL1_PLLSEL_16MHZ;
|
||||
break;
|
||||
case 24000000:
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL1_PLLSEL_24MHZ;
|
||||
break;
|
||||
case 25000000:
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL1_PLLSEL_25MHZ;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* configure the tuning interface of the USB HS PHY */
|
||||
USB_HS_PHYC->USB_HS_PHYC_TUNE |= conf->phy_tune;
|
||||
|
||||
/* check whether the LDO regulator is used by on the chip */
|
||||
if (USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_USED) {
|
||||
/* enable the LDO */
|
||||
USB_HS_PHYC->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE;
|
||||
/* wait until the LDO is ready */
|
||||
while (!(USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS)) {}
|
||||
}
|
||||
|
||||
/* enable the PLL of the USB HS PHY */
|
||||
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN;
|
||||
#endif /* USB_HS_PHYC */
|
||||
}
|
||||
|
||||
#else /* MODULE_PERIPH_USBDEV_HS_ULPI */
|
||||
else {
|
||||
/* only on-chip PHY support enabled */
|
||||
assert(conf->phy == DWC2_USB_OTG_PHY_BUILTIN);
|
||||
}
|
||||
#endif /* MODULE_PERIPH_USBDEV_HS_ULPI */
|
||||
}
|
||||
#endif /* DWC2_USB_OTG_HS_ENABLED */
|
||||
|
||||
if (conf->phy == DWC2_USB_OTG_PHY_BUILTIN) {
|
||||
/* set `Power Down Disable` to activate the on-chip FS transceiver */
|
||||
global_regs->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
}
|
||||
else {
|
||||
/* clear `Power Down Disable` to deactivate the on-chip FS transceiver */
|
||||
global_regs->GCCFG &= ~USB_OTG_GCCFG_PWRDWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user