drivers: usb: nordic: Power consumption fix with cable detached

This commit fixes the issue with excess current being drawn
during sleep due to active HFCLK with external crystal.
Clock-related operations were moved to cable attachmend and
detachment handlers to ensure that HFCLK is not requested
when it's not needed.

Signed-off-by: Paweł Zadrożniak <pawel.zadrozniak@nordicsemi.no>
This commit is contained in:
Paweł Zadrożniak 2019-01-31 12:05:15 +01:00 committed by Anas Nashif
commit 85d75ec853

View file

@ -525,6 +525,7 @@ static int hf_clock_enable(bool on, bool blocking)
{
int ret = -ENODEV;
struct device *clock;
static bool clock_requested;
clock = device_get_binding(CONFIG_CLOCK_CONTROL_NRF_M16SRC_DRV_NAME);
if (!clock) {
@ -533,8 +534,18 @@ static int hf_clock_enable(bool on, bool blocking)
}
if (on) {
if (clock_requested) {
/* Do not request HFCLK multiple times. */
return 0;
}
ret = clock_control_on(clock, (void *)blocking);
} else {
if (!clock_requested) {
/* Cancel the operation if clock has not
* been requested by this driver before.
*/
return 0;
}
ret = clock_control_off(clock, (void *)blocking);
}
@ -544,9 +555,14 @@ static int hf_clock_enable(bool on, bool blocking)
return ret;
}
clock_requested = on;
LOG_DBG("HF clock %s success (%d)", on ? "start" : "stop", ret);
return ret;
/* NOTE: Non-blocking HF clock enable can return -EINPROGRESS
* if HF clock start was already requested. Such error code
* does not need to be propagated, hence returned value is 0.
*/
return 0;
}
static void usbd_enable_endpoints(struct nrf_usbd_ctx *ctx)
@ -731,6 +747,8 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt)
case USBD_ATTACHED:
LOG_DBG("USB detected");
nrfx_usbd_enable();
(void) hf_clock_enable(true, false);
break;
case USBD_POWERED:
@ -748,6 +766,7 @@ static inline void usbd_work_process_pwr_events(struct usbd_pwr_event *pwr_evt)
LOG_DBG("USB Removed");
ctx->ready = false;
nrfx_usbd_disable();
(void) hf_clock_enable(false, false);
if (ctx->status_cb) {
ctx->status_cb(USB_DC_DISCONNECTED, NULL);
@ -1248,14 +1267,6 @@ int usb_dc_attach(void)
DT_NORDIC_NRF_USBD_USBD_0_IRQ_PRIORITY,
nrfx_isr, nrfx_usbd_irq_handler, 0);
/* NOTE: Non-blocking HF clock enable can return -EINPROGRESS
* if HF clock start was already requested.
*/
ret = hf_clock_enable(true, false);
if (ret && ret != -EINPROGRESS) {
return ret;
}
err = nrfx_usbd_init(usbd_event_handler);
if (err != NRFX_SUCCESS) {
@ -1280,7 +1291,6 @@ int usb_dc_attach(void)
int usb_dc_detach(void)
{
struct nrf_usbd_ctx *ctx = get_usbd_ctx();
int ret;
k_mutex_lock(&ctx->drv_lock, K_FOREVER);
@ -1289,18 +1299,13 @@ int usb_dc_detach(void)
nrfx_usbd_disable();
nrfx_usbd_uninit();
ret = hf_clock_enable(false, false);
if (ret) {
return ret;
k_mutex_unlock(&ctx->drv_lock);
}
(void) hf_clock_enable(false, false);
nrf5_power_usb_power_int_enable(false);
ctx->attached = false;
k_mutex_unlock(&ctx->drv_lock);
return ret;
return 0;
}
int usb_dc_reset(void)