drivers: usb_dc_rpi_pico: Implemented vbus detection handling
As per USB 2.0 specification 7.1.5.1: The voltage source on the pull-up resistor must be derived from or controlled by the power supplied on the USB cable such that when VBUS is removed, the pull-up resistor does not supply current on the data line to which it is attached. Signed-off-by: Lukas Gehreke <lk.gehreke@gmail.com>
This commit is contained in:
parent
e528d53a7a
commit
4c0317fa47
3 changed files with 92 additions and 7 deletions
|
@ -18,6 +18,7 @@
|
|||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 = <USB_VBUS_DET_P1>;
|
||||
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:
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue