drivers: usb: nordic: implement remote wakeup

Adds remote wakeup support for nRF chips.

Signed-off-by: Paweł Zadrożniak <pawel.zadrozniak@nordicsemi.no>
This commit is contained in:
Paweł Zadrożniak 2019-02-11 12:25:00 +01:00 committed by Anas Nashif
commit 804b9e1ada
2 changed files with 62 additions and 25 deletions

View file

@ -63,6 +63,7 @@ menuconfig USB_NRF52840
select USB_DEVICE_DRIVER
select HAS_DTS_USB
select NRFX_USBD
select USB_DEVICE_REMOTE_WAKEUP
help
nRF52840 USB Device Controller Driver

View file

@ -57,6 +57,7 @@ enum usbd_periph_state {
USBD_ATTACHED,
USBD_POWERED,
USBD_SUSPENDED,
USBD_RESUMED,
USBD_DEFAULT,
USBD_ADDRESS_SET,
USBD_CONFIGURED,
@ -749,6 +750,9 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt)
nrfx_usbd_enable();
(void) hf_clock_enable(true, false);
if (ctx->status_cb) {
ctx->status_cb(USB_DC_CONNECTED, NULL);
}
break;
case USBD_POWERED:
@ -773,6 +777,22 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt)
}
break;
case USBD_SUSPENDED:
LOG_DBG("USB Suspend state");
nrfx_usbd_suspend();
if (ctx->status_cb) {
ctx->status_cb(USB_DC_SUSPEND, NULL);
}
break;
case USBD_RESUMED:
LOG_DBG("USB resume");
if (ctx->status_cb) {
ctx->status_cb(USB_DC_RESUME, NULL);
}
break;
default:
break;
}
@ -1094,37 +1114,34 @@ static void usbd_event_transfer_data(nrfx_usbd_evt_t const *const p_event)
static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event)
{
struct nrf_usbd_ep_ctx *ep_ctx;
struct usbd_event *ev;
struct usbd_event evt;
bool put_evt = false;
switch (p_event->type) {
case NRFX_USBD_EVT_SUSPEND:
LOG_DBG("SUSPEND state detected.");
evt.evt_type = USBD_EVT_POWER;
evt.evt.pwr_evt.state = USBD_SUSPENDED;
put_evt = true;
break;
case NRFX_USBD_EVT_RESUME:
LOG_DBG("RESUMING from suspend.");
evt.evt_type = USBD_EVT_POWER;
evt.evt.pwr_evt.state = USBD_RESUMED;
put_evt = true;
break;
case NRFX_USBD_EVT_WUREQ:
LOG_DBG("RemoteWU initiated.");
break;
case NRFX_USBD_EVT_RESET:
ev = usbd_evt_alloc();
if (!ev) {
return;
}
ev->evt_type = USBD_EVT_RESET;
usbd_evt_put(ev);
usbd_work_schedule();
evt.evt_type = USBD_EVT_RESET;
put_evt = true;
break;
case NRFX_USBD_EVT_SOF:
#ifdef CONFIG_USB_DEVICE_SOF
ev = usbd_evt_alloc();
if (!ev) {
return;
if (IS_ENABLED(CONFIG_USB_DEVICE_SOF)) {
evt.evt_type = USBD_EVT_SOF;
put_evt = true;
}
ev->evt_type = USBD_EVT_SOF;
usbd_evt_put(ev);
usbd_work_schedule();
#endif
break;
case NRFX_USBD_EVT_EPTRANSFER:
@ -1158,15 +1175,11 @@ static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event)
struct nrf_usbd_ep_ctx *ep_ctx =
endpoint_ctx(NRF_USBD_EPOUT(0));
ev = usbd_evt_alloc();
if (!ev) {
return;
}
ev->evt_type = USBD_EVT_EP;
ev->evt.ep_evt.ep = ep_ctx;
ev->evt.ep_evt.evt_type = EP_EVT_SETUP_RECV;
usbd_evt_put(ev);
usbd_work_schedule();
evt.evt_type = USBD_EVT_EP;
evt.evt.ep_evt.ep = ep_ctx;
evt.evt.ep_evt.evt_type = EP_EVT_SETUP_RECV;
put_evt = true;
}
break;
}
@ -1174,6 +1187,19 @@ static void usbd_event_handler(nrfx_usbd_evt_t const *const p_event)
default:
break;
}
if (put_evt) {
struct usbd_event *ev;
ev = usbd_evt_alloc();
if (!ev) {
return;
}
ev->evt_type = evt.evt_type;
ev->evt = evt.evt;
usbd_evt_put(ev);
usbd_work_schedule();
}
}
static inline void usbd_reinit(void)
@ -1796,3 +1822,13 @@ int usb_dc_ep_mps(const u8_t ep)
return ep_ctx->cfg.max_sz;
}
int usb_dc_wakeup_request(void)
{
bool res = nrfx_usbd_wakeup_req();
if (!res) {
return -EAGAIN;
}
return 0;
}