From f10cefb49150688010329ee43f1ea89c7b19d350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Thu, 24 Oct 2024 17:36:22 +0200 Subject: [PATCH 1/2] dts: common: nordic: nrf54l20: add USBHS node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added USBHS device tree node for nRF54L20. Signed-off-by: Rafał Kuźnia --- .../nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp.dts | 4 ++++ dts/common/nordic/nrf54l20.dtsi | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp.dts b/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp.dts index af32bc27eb78a..45153e5578f80 100644 --- a/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp.dts +++ b/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp.dts @@ -17,3 +17,7 @@ zephyr,sram = &cpuapp_sram; }; }; + +zephyr_udc0: &usbhs { + status = "okay"; +}; diff --git a/dts/common/nordic/nrf54l20.dtsi b/dts/common/nordic/nrf54l20.dtsi index 6ad88352e07c3..c8c5ab7aa6d77 100644 --- a/dts/common/nordic/nrf54l20.dtsi +++ b/dts/common/nordic/nrf54l20.dtsi @@ -195,6 +195,19 @@ prescaler = <0>; }; + usbhs: usbhs@5a000 { + compatible = "nordic,nrf-usbhs-nrf54l", "snps,dwc2"; + reg = <0x5a000 0x1000>, <0x50020000 0x1a000>; + reg-names = "wrapper", "core"; + interrupts = <90 NRF_DEFAULT_IRQ_PRIORITY>; + num-in-eps = <16>; + num-out-eps = <16>; + ghwcfg1 = <0x0>; + ghwcfg2 = <0x22affc52>; + ghwcfg4 = <0x3e10aa60>; + status = "disabled"; + }; + dppic10: dppic@82000 { compatible = "nordic,nrf-dppic"; reg = <0x82000 0x808>; From b056f38834af13c370f1dcdc6b56a6134256b2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Fri, 25 Oct 2024 11:49:49 +0200 Subject: [PATCH 2/2] drivers: udc_dwc2: Add nRF54L20 UDC DWC2 quirks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nRF54L20 does not have the NRFS layer and the set of quirks will be different than in nRF54H20. Added new set of quirks for the nRF54L20 SoC. Signed-off-by: Rafał Kuźnia --- drivers/usb/udc/udc_dwc2_vendor_quirks.h | 159 ++++++++++++++--------- 1 file changed, 96 insertions(+), 63 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index f45404c2b8477..93ddfe3625819 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -108,13 +108,11 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) #endif /*DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) */ -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) || \ + DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs_nrf54l) #define DT_DRV_COMPAT snps_dwc2 -#include -#include - #define USBHS_DT_WRAPPER_REG_ADDR(n) UINT_TO_POINTER(DT_INST_REG_ADDR_BY_NAME(n, wrapper)) /* @@ -125,7 +123,72 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) * CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT timeout expires. */ static K_EVENT_DEFINE(usbhs_events); -#define USBHS_VBUS_READY BIT(0) +#define USBHS_VBUS_READY BIT(0) + +static inline int usbhs_enable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + k_timeout_t timeout = K_FOREVER; + +#if CONFIG_NRFS_HAS_VBUS_DETECTOR_SERVICE + if (CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT) { + timeout = K_MSEC(CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT); + } +#endif + + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { + LOG_WRN("VBUS is not ready, block udc_enable()"); + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, timeout)) { + return -ETIMEDOUT; + } + } + + wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + wrapper->TASKS_START = 1UL; + + /* Wait for clock to start to avoid hang on too early register read */ + k_busy_wait(1); + + /* Enable interrupts */ + wrapper->INTENSET = 1UL; + + return 0; +} + +static inline int usbhs_disable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + /* Disable interrupts */ + wrapper->INTENCLR = 1UL; + + wrapper->ENABLE = 0UL; + wrapper->TASKS_START = 1UL; + + return 0; +} + +static inline int usbhs_init_caps(const struct device *dev) +{ + struct udc_data *data = dev->data; + + data->caps.can_detect_vbus = true; + data->caps.hs = true; + + return 0; +} + +static inline int usbhs_is_phy_clk_off(const struct device *dev) +{ + return !k_event_test(&usbhs_events, USBHS_VBUS_READY); +} + +#endif /* nordic_nrf_usbhs || nordic_nrf_usbhs_nrf54l */ + +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) + +#include +#include static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) { @@ -180,49 +243,6 @@ static inline int usbhs_enable_nrfs_service(const struct device *dev) return 0; } -static inline int usbhs_enable_core(const struct device *dev) -{ - NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); - k_timeout_t timeout = K_FOREVER; - - #if CONFIG_NRFS_HAS_VBUS_DETECTOR_SERVICE - if (CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT) { - timeout = K_MSEC(CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT); - } - #endif - - if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { - LOG_WRN("VBUS is not ready, block udc_enable()"); - if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, timeout)) { - return -ETIMEDOUT; - } - } - - wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; - wrapper->TASKS_START = 1UL; - - /* Wait for clock to start to avoid hang on too early register read */ - k_busy_wait(1); - - /* Enable interrupts */ - wrapper->INTENSET = 1UL; - - return 0; -} - -static inline int usbhs_disable_core(const struct device *dev) -{ - NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); - - /* Disable interrupts */ - wrapper->INTENCLR = 1UL; - - wrapper->ENABLE = 0UL; - wrapper->TASKS_START = 1UL; - - return 0; -} - static inline int usbhs_disable_nrfs_service(const struct device *dev) { nrfs_err_t nrfs_err; @@ -247,21 +267,6 @@ static inline int usbhs_irq_clear(const struct device *dev) return 0; } -static inline int usbhs_init_caps(const struct device *dev) -{ - struct udc_data *data = dev->data; - - data->caps.can_detect_vbus = true; - data->caps.hs = true; - - return 0; -} - -static inline int usbhs_is_phy_clk_off(const struct device *dev) -{ - return !k_event_test(&usbhs_events, USBHS_VBUS_READY); -} - static inline int usbhs_post_hibernation_entry(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; @@ -311,6 +316,34 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) #endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs_nrf54l) + +static inline int usbhs_enable_usbreg(const struct device *dev) +{ + LOG_WRN("VBUS detection not implemented."); + k_event_post(&usbhs_events, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + + return 0; +} + +#define QUIRK_NRF_USBHS_DEFINE(n) \ + struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + .init = usbhs_enable_usbreg, \ + .pre_enable = usbhs_enable_core, \ + .disable = usbhs_disable_core, \ + .shutdown = NULL, \ + .irq_clear = NULL, \ + .caps = usbhs_init_caps, \ + .is_phy_clk_off = usbhs_is_phy_clk_off, \ + .post_hibernation_entry = NULL, \ + .pre_hibernation_exit = NULL, \ + }; + +DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) + +#endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs_nrf54l) */ + /* Add next vendor quirks definition above this line */ #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_VENDOR_QUIRKS_H */