summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerzy Kasenberg <[email protected]>2021-09-17 11:41:58 +0200
committerJerzy Kasenberg <[email protected]>2021-09-17 12:10:17 +0200
commit6d8677a78ab4973ff498ec2fe8ea40a1cde230a1 (patch)
treea5bef85ec3b889eb91dea82020c036aa785e03c6
parent03866ddf9be007e8c26dc290e28093a9e59b1e17 (diff)
dcd_da146xx: Add VBUS handling
DA146xx are Bluetooth devices that may be battery powered and when not connected to USB host there is no need for USB peripheral to be running. This change allows to enable USB peripheral when VBUS is present otherwise USB is down reducing power consumption. tud_vsub_changed() function must be called whenever VBUS change was detected. For bus-powered devices this function should be called at startup since VBUS must be present while device is working.
-rw-r--r--src/portable/dialog/da146xx/dcd_da146xx.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c
index 7b0d8f86c..112cdb502 100644
--- a/src/portable/dialog/da146xx/dcd_da146xx.c
+++ b/src/portable/dialog/da146xx/dcd_da146xx.c
@@ -217,6 +217,7 @@ typedef struct {
static struct
{
bool vbus_present;
+ bool init_called;
bool in_reset;
xfer_ctl_t xfer_status[EP_MAX][2];
// Endpoints that use DMA, one for each direction
@@ -224,6 +225,7 @@ static struct
} _dcd =
{
.vbus_present = false,
+ .init_called = false,
.xfer_status =
{
{ { .regs = EP_REGS(USB_EPC0_REG) }, { .regs = EP_REGS(USB_EPC0_REG) } },
@@ -735,19 +737,13 @@ static void handle_ep0_nak(void)
*------------------------------------------------------------------*/
void dcd_init(uint8_t rhport)
{
- USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
- USB->USB_NFSR_REG = 0;
- USB->USB_FAR_REG = 0x80;
- USB->USB_NFSR_REG = NFSR_NODE_RESET;
- USB->USB_TXMSK_REG = 0;
- USB->USB_RXMSK_REG = 0;
-
- USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
- USB_USB_MAMSK_REG_USB_M_ALT_Msk |
- USB_USB_MAMSK_REG_USB_M_WARN_Msk;
- USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
+ (void) rhport;
- dcd_connect(rhport);
+ _dcd.init_called = true;
+ if (_dcd.vbus_present)
+ {
+ dcd_connect(rhport);
+ }
}
void dcd_int_enable(uint8_t rhport)
@@ -783,10 +779,25 @@ void dcd_connect(uint8_t rhport)
{
(void)rhport;
- REG_SET_BIT(USB_MCTRL_REG, USB_NAT);
+ if (GET_BIT(USB->USB_MCTRL_REG, USB_USB_MCTRL_REG_USB_NAT) == 0)
+ {
+ USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
+ USB->USB_NFSR_REG = 0;
+ USB->USB_FAR_REG = 0x80;
+ USB->USB_NFSR_REG = NFSR_NODE_RESET;
+ USB->USB_TXMSK_REG = 0;
+ USB->USB_RXMSK_REG = 0;
+
+ USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
+ USB_USB_MAMSK_REG_USB_M_ALT_Msk |
+ USB_USB_MAMSK_REG_USB_M_WARN_Msk;
+ USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
+
+ REG_SET_BIT(USB_MCTRL_REG, USB_NAT);
- // Select chosen DMA to be triggered by USB.
- DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX;
+ // Select chosen DMA to be triggered by USB.
+ DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX;
+ }
}
void dcd_disconnect(uint8_t rhport)
@@ -796,6 +807,30 @@ void dcd_disconnect(uint8_t rhport)
REG_CLR_BIT(USB_MCTRL_REG, USB_NAT);
}
+TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
+{
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
+}
+
+void tusb_vbus_changed(bool present)
+{
+ if (present && !_dcd.vbus_present)
+ {
+ _dcd.vbus_present = true;
+ // If power event happened before USB started, delay dcd_connect
+ // until dcd_init is called.
+ if (_dcd.init_called)
+ {
+ dcd_connect(0);
+ }
+ }
+ else if (!present && _dcd.vbus_present)
+ {
+ _dcd.vbus_present = false;
+ USB->USB_MCTRL_REG = 0;
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr());
+ }
+}
/*------------------------------------------------------------------*/
/* DCD Endpoint port