diff --git a/drivers/usb/device/usb_dc_rpi_pico.c b/drivers/usb/device/usb_dc_rpi_pico.c index ff8f520a28c..c0b55a7de5f 100644 --- a/drivers/usb/device/usb_dc_rpi_pico.c +++ b/drivers/usb/device/usb_dc_rpi_pico.c @@ -18,6 +18,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(udc_rpi, CONFIG_USB_DRIVER_LOG_LEVEL); @@ -50,6 +51,16 @@ struct udc_rpi_ep_state { uint8_t next_pid; }; +#define USB_RPI_PICO_PINCTRL_DT_INST_DEFINE(n) \ + COND_CODE_1(DT_INST_PINCTRL_HAS_NAME(n, default), (PINCTRL_DT_INST_DEFINE(n)), ()) + +#define USB_RPI_PICO_PINCTRL_DT_INST_DEV_CONFIG_GET(n) \ + COND_CODE_1(DT_INST_PINCTRL_HAS_NAME(n, default), \ + ((void *)PINCTRL_DT_INST_DEV_CONFIG_GET(n)), (NULL)) + +USB_RPI_PICO_PINCTRL_DT_INST_DEFINE(0); +const struct pinctrl_dev_config *pcfg = USB_RPI_PICO_PINCTRL_DT_INST_DEV_CONFIG_GET(0); + #define USBD_THREAD_STACK_SIZE 1024 K_THREAD_STACK_DEFINE(thread_stack, USBD_THREAD_STACK_SIZE); @@ -333,9 +344,33 @@ static void udc_rpi_isr(const void *arg) USB_DC_CONNECTED : USB_DC_DISCONNECTED; + /* VBUS detection does not always detect the detach. + * Check on disconnect if VBUS is still attached + */ + if (pcfg != NULL && msg.type == USB_DC_DISCONNECTED && + (usb_hw->sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS) == 0) { + LOG_DBG("Disconnected. Disabling pull-up"); + hw_clear_alias(usb_hw)->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + } + k_msgq_put(&usb_dc_msgq, &msg, K_NO_WAIT); } + if (status & USB_INTS_VBUS_DETECT_BITS) { + handled |= USB_INTS_VBUS_DETECT_BITS; + hw_clear_alias(usb_hw)->sie_status = USB_SIE_STATUS_VBUS_DETECTED_BITS; + + if (pcfg != NULL) { + if (usb_hw->sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS) { + LOG_DBG("VBUS attached. Enabling pull-up"); + hw_set_alias(usb_hw)->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + } else { + LOG_DBG("VBUS detached. Disabling pull-up"); + hw_clear_alias(usb_hw)->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + } + } + } + if (status & USB_INTS_BUS_RESET_BITS) { LOG_WRN("BUS RESET"); handled |= USB_INTS_BUS_RESET_BITS; @@ -426,6 +461,17 @@ static void udc_rpi_init_endpoint(const uint8_t i) static int udc_rpi_init(void) { + int ret; + + /* Apply the pinctrl */ + if (pcfg != NULL) { + ret = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + LOG_ERR("Failed to apply pincfg: %d", ret); + return ret; + } + } + /* Reset usb controller */ reset_block(RESETS_RESET_USBCTRL_BITS); unreset_block_wait(RESETS_RESET_USBCTRL_BITS); @@ -437,8 +483,11 @@ static int udc_rpi_init(void) /* Mux the controller to the onboard usb phy */ usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; - /* Force VBUS detect so the device thinks it is plugged into a host */ - usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + if (pcfg == NULL) { + /* Force VBUS detect so the device thinks it is plugged into a host */ + usb_hw->pwr = + USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + } /* Enable the USB controller in device mode. */ usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; @@ -455,7 +504,7 @@ static int udc_rpi_init(void) USB_INTS_ERROR_BIT_STUFF_BITS | USB_INTS_ERROR_CRC_BITS | USB_INTS_ERROR_DATA_SEQ_BITS | USB_INTS_ERROR_RX_OVERFLOW_BITS | USB_INTS_ERROR_RX_TIMEOUT_BITS | USB_INTS_DEV_SUSPEND_BITS | - USB_INTR_DEV_RESUME_FROM_HOST_BITS; + USB_INTR_DEV_RESUME_FROM_HOST_BITS | USB_INTE_VBUS_DETECT_BITS; /* Set up endpoints (endpoint control registers) * described by device configuration @@ -465,8 +514,15 @@ static int udc_rpi_init(void) udc_rpi_init_endpoint(i); } - /* Present full speed device by enabling pull up on DP */ - hw_set_alias(usb_hw)->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + /* Self powered devices must enable the pull up only if vbus is detected. + * If the pull-up is not enabled here, this will be handled by the USB_INTS_VBUS_DETECT + * interrupt. + */ + if (usb_hw->sie_status & USB_SIE_STATUS_VBUS_DETECTED_BITS) { + LOG_DBG("Enabling pull-up"); + /* Present full speed device by enabling pull up on DP */ + hw_set_alias(usb_hw)->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; + } return 0; } diff --git a/dts/bindings/usb/raspberrypi,pico-usbd.yaml b/dts/bindings/usb/raspberrypi,pico-usbd.yaml index 6d307bdf0e5..26b763e9a7a 100644 --- a/dts/bindings/usb/raspberrypi,pico-usbd.yaml +++ b/dts/bindings/usb/raspberrypi,pico-usbd.yaml @@ -1,11 +1,29 @@ # Copyright (c) 2021, Pete Johanson # SPDX-License-Identifier: Apache-2.0 -description: RaspberryPi Pico USB Device Controller +description: | + RaspberryPi Pico USB Device Controller. + + Example of enabling the controller with vbus detection: + + &pinctrl { + usb_default: usb_default { + group1 { + pinmux = ; + input-enable; + }; + }; + }; + + zephyr_udc0: &usbd { + status = "okay"; + pinctrl-0 = <&usb_default>; + pinctrl-names = "default"; + }; compatible: "raspberrypi,pico-usbd" -include: [usb-ep.yaml, reset-device.yaml] +include: [usb-ep.yaml, reset-device.yaml, pinctrl-device.yaml] properties: reg: diff --git a/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h index afe7577d991..64c3832d60e 100644 --- a/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h @@ -231,4 +231,15 @@ #define GPOUT2_P24 RP2040_PINMUX(24, RP2_PINCTRL_GPIO_FUNC_GPCK) #define GPOUT3_P25 RP2040_PINMUX(25, RP2_PINCTRL_GPIO_FUNC_GPCK) +#define USB_VBUS_DET_P1 RP2040_PINMUX(1, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P4 RP2040_PINMUX(4, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P7 RP2040_PINMUX(7, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P10 RP2040_PINMUX(10, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P13 RP2040_PINMUX(13, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P16 RP2040_PINMUX(16, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P19 RP2040_PINMUX(19, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P22 RP2040_PINMUX(22, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P25 RP2040_PINMUX(25, RP2_PINCTRL_GPIO_FUNC_USB) +#define USB_VBUS_DET_P28 RP2040_PINMUX(28, RP2_PINCTRL_GPIO_FUNC_USB) + #endif /* __RP2040_PINCTRL_H__ */