summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-08-11 20:06:57 +0700
committerhathach <[email protected]>2021-08-11 20:06:57 +0700
commitf3a6e564ee9dfe3587d8d9dce051eae76bdb9d0c (patch)
treea979584c0947dcae11bf4f25e6790ab1f3069e11 /src
parenta5b464c5cad840c8dcdb87c96a20e52991b828f5 (diff)
rp2040 enable suspend and resume interrupt
Diffstat (limited to 'src')
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c74
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c7
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.c6
3 files changed, 52 insertions, 35 deletions
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index f78a932f1..f39cfab3e 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -37,6 +37,14 @@
#include "device/dcd.h"
+// Current implementation force vbus detection as always present, causing device think it is always plugged into host.
+// Therefore it cannot detect disconnect event, mistaken it as suspend.
+// Note: won't work if change to 0 (for now)
+//
+// Note: Line state when disconnected is very sensitive, in actual testing,
+// it can toggles between J-state (idle) and SE1 if cable still connected to rp2040 (not connected to host)
+#define FORCE_VBUS_DETECT 1
+
/*------------------------------------------------------------------*/
/* Low level controller
*------------------------------------------------------------------*/
@@ -52,14 +60,14 @@ static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0};
static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir)
{
- return &hw_endpoints[num][dir];
+ return &hw_endpoints[num][dir];
}
static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr)
{
- uint8_t num = tu_edpt_number(ep_addr);
- tusb_dir_t dir = tu_edpt_dir(ep_addr);
- return hw_endpoint_get_by_num(num, dir);
+ uint8_t num = tu_edpt_number(ep_addr);
+ tusb_dir_t dir = tu_edpt_dir(ep_addr);
+ return hw_endpoint_get_by_num(num, dir);
}
static void _hw_endpoint_alloc(struct hw_endpoint *ep)
@@ -290,7 +298,9 @@ static void dcd_rp2040_irq(void)
hw_handle_buff_status();
}
- // SE0 for 2 us or more, usually together with Bus Reset
+#if FORCE_VBUS_DETECT == 0
+ // Since we force VBUS detect On, device will always think it is connected and
+ // couldn't distinguish between disconnect and suspend
if (status & USB_INTS_DEV_CONN_DIS_BITS)
{
handled |= USB_INTS_DEV_CONN_DIS_BITS;
@@ -306,6 +316,7 @@ static void dcd_rp2040_irq(void)
usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
}
+#endif
// SE0 for 2.5 us or more
if (status & USB_INTS_BUS_RESET_BITS)
@@ -322,7 +333,7 @@ static void dcd_rp2040_irq(void)
#endif
}
-#if 0
+#if 1
// TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection
/* Note from pico datasheet 4.1.2.6.4 (v1.2)
@@ -364,36 +375,43 @@ static void dcd_rp2040_irq(void)
/*------------------------------------------------------------------*/
/* Controller API
*------------------------------------------------------------------*/
+
void dcd_init (uint8_t rhport)
{
- pico_trace("dcd_init %d\n", rhport);
- assert(rhport == 0);
+ pico_trace("dcd_init %d\n", rhport);
+ assert(rhport == 0);
+
+ // Reset hardware to default state
+ rp2040_usb_init();
- // Reset hardware to default state
- rp2040_usb_init();
+#if FORCE_VBUS_DETECT
+ // 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;
+#endif
- irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq);
- memset(hw_endpoints, 0, sizeof(hw_endpoints));
- next_buffer_ptr = &usb_dpram->epx_data[0];
+ irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq);
+ memset(hw_endpoints, 0, sizeof(hw_endpoints));
+ next_buffer_ptr = &usb_dpram->epx_data[0];
- // EP0 always exists so init it now
- // EP0 OUT
- hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL);
- // EP0 IN
- hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL);
+ // EP0 always exists so init it now
+ // EP0 OUT
+ hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL);
+ // EP0 IN
+ hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL);
- // Initializes the USB peripheral for device mode and enables it.
- // Don't need to enable the pull up here. Force VBUS
- usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
+ // Initializes the USB peripheral for device mode and enables it.
+ // Don't need to enable the pull up here. Force VBUS
+ usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
- // Enable individual controller IRQS here. Processor interrupt enable will be used
- // for the global interrupt enable...
- // TODO Enable SUSPEND & RESUME interrupt
- usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
- usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
- USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ;
+ // Enable individual controller IRQS here. Processor interrupt enable will be used
+ // for the global interrupt enable...
+ // Note: Force VBUS detect cause disconnection not detectable
+ usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
+ usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
+ USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
+ (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
- dcd_connect(rhport);
+ dcd_connect(rhport);
}
void dcd_int_enable(uint8_t rhport)
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index 40a0805c6..2c007ddd3 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -61,8 +61,8 @@ static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS];
// Flags we set by default in sie_ctrl (we add other bits on top)
enum {
- SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
- USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS
+ SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
+ USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS
};
static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr)
@@ -360,6 +360,9 @@ bool hcd_init(uint8_t rhport)
// Reset any previous state
rp2040_usb_init();
+ // Force VBUS detect to always present, for now we assume vbus is always provided (without using VBUS En)
+ usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+
irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq);
// clear epx and interrupt eps
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index dc12e6d82..43554d28b 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -62,11 +62,7 @@ void rp2040_usb_init(void)
memset(usb_dpram, 0, sizeof(*usb_dpram));
// 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
- // TODO support VBUs detect
- usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+ usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
}
void hw_endpoint_reset_transfer(struct hw_endpoint *ep)