mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
bdk: usb: improve USB2/XUSB power down
TODO: add more power downs on XUSB stack
This commit is contained in:
parent
605f270f98
commit
f6c9e636d1
2 changed files with 101 additions and 22 deletions
|
@ -443,6 +443,11 @@ static void _usb_device_power_down()
|
||||||
usb_init_done = false;
|
usb_init_done = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _usbd_disable_ep1()
|
||||||
|
{
|
||||||
|
usbd_otg->regs->endptctrl[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void _usbd_stall_reset_ep1(usb_dir_t direction, usb_ep_cfg_t stall)
|
static void _usbd_stall_reset_ep1(usb_dir_t direction, usb_ep_cfg_t stall)
|
||||||
{
|
{
|
||||||
stall &= 1;
|
stall &= 1;
|
||||||
|
@ -628,13 +633,12 @@ int usbd_flush_endpoint(u32 endpoint)
|
||||||
return USB_RES_OK;
|
return USB_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_end(bool reset_ep, bool only_controller)
|
static void _usb_reset_disable_ep1()
|
||||||
{
|
|
||||||
if (reset_ep)
|
|
||||||
{
|
{
|
||||||
usbd_flush_endpoint(USB_EP_ALL);
|
usbd_flush_endpoint(USB_EP_ALL);
|
||||||
_usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_RESET); // EP1 Bulk OUT.
|
_usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_RESET); // EP1 Bulk OUT.
|
||||||
_usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_RESET); // EP1 Bulk IN.
|
_usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_RESET); // EP1 Bulk IN.
|
||||||
|
_usbd_disable_ep1();
|
||||||
|
|
||||||
usbd_otg->config_num = 0;
|
usbd_otg->config_num = 0;
|
||||||
usbd_otg->interface_num = 0;
|
usbd_otg->interface_num = 0;
|
||||||
|
@ -642,6 +646,11 @@ void usbd_end(bool reset_ep, bool only_controller)
|
||||||
usbd_otg->max_lun_set = false;
|
usbd_otg->max_lun_set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usbd_end(bool reset_ep, bool only_controller)
|
||||||
|
{
|
||||||
|
if (reset_ep)
|
||||||
|
_usb_reset_disable_ep1();
|
||||||
|
|
||||||
// Stop device controller.
|
// Stop device controller.
|
||||||
usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN;
|
usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN;
|
||||||
|
|
||||||
|
@ -762,7 +771,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_time
|
||||||
// Set buffers addresses to all page pointers.
|
// Set buffers addresses to all page pointers.
|
||||||
u32 dt_buffer_offset = dtd_idx * USB_TD_BUFFER_MAX_SIZE;
|
u32 dt_buffer_offset = dtd_idx * USB_TD_BUFFER_MAX_SIZE;
|
||||||
for (u32 i = 0; i < 4; i++)
|
for (u32 i = 0; i < 4; i++)
|
||||||
usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[i] =
|
usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[i] = !buf ? 0 :
|
||||||
(u32)&buf[dt_buffer_offset + (USB_TD_BUFFER_PAGE_SIZE * i)];
|
(u32)&buf[dt_buffer_offset + (USB_TD_BUFFER_PAGE_SIZE * i)];
|
||||||
|
|
||||||
//usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[5] =
|
//usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[5] =
|
||||||
|
@ -825,6 +834,7 @@ out:
|
||||||
else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE)
|
else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE)
|
||||||
res = USB_ERROR_XFER_ERROR;
|
res = USB_ERROR_XFER_ERROR;
|
||||||
|
|
||||||
|
// Invalidate data after OP is done.
|
||||||
if (direction == USB_DIR_OUT)
|
if (direction == USB_DIR_OUT)
|
||||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,6 +752,51 @@ static int _xusbd_ep_initialize(u32 ep_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _xusbd_ep1_disable(u32 ep_idx)
|
||||||
|
{
|
||||||
|
volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[ep_idx];
|
||||||
|
u32 ep_mask = BIT(ep_idx);
|
||||||
|
|
||||||
|
switch (ep_idx)
|
||||||
|
{
|
||||||
|
case USB_EP_BULK_OUT:
|
||||||
|
case USB_EP_BULK_IN:
|
||||||
|
// Skip if already disabled.
|
||||||
|
if (!ep_ctxt->ep_state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_mask;
|
||||||
|
|
||||||
|
// Set EP state to disabled.
|
||||||
|
ep_ctxt->ep_state = EP_DISABLED;
|
||||||
|
|
||||||
|
// Clear EP context.
|
||||||
|
memset((void *)ep_ctxt, 0, sizeof(xusb_ep_ctx_t));
|
||||||
|
|
||||||
|
// Wait for EP status to change.
|
||||||
|
_xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_mask, ep_mask, 1000);
|
||||||
|
|
||||||
|
// Clear status change.
|
||||||
|
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_mask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _xusb_disable_ep1()
|
||||||
|
{
|
||||||
|
_xusbd_ep1_disable(USB_EP_BULK_OUT);
|
||||||
|
_xusbd_ep1_disable(USB_EP_BULK_IN);
|
||||||
|
|
||||||
|
// Device mode stop.
|
||||||
|
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) &= ~XHCI_CTRL_RUN;
|
||||||
|
XUSB_DEV_XHCI(XUSB_DEV_XHCI_ST) |= XHCI_ST_RC;
|
||||||
|
|
||||||
|
usbd_xotg->config_num = 0;
|
||||||
|
usbd_xotg->interface_num = 0;
|
||||||
|
usbd_xotg->max_lun_set = false;
|
||||||
|
usbd_xotg->device_state = XUSB_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
static void _xusb_init_phy()
|
static void _xusb_init_phy()
|
||||||
{
|
{
|
||||||
// Configure and enable PLLU.
|
// Configure and enable PLLU.
|
||||||
|
@ -841,11 +886,9 @@ static void _xusbd_init_device_clocks()
|
||||||
|
|
||||||
int xusb_device_init()
|
int xusb_device_init()
|
||||||
{
|
{
|
||||||
/////////////////////////////////////////////////
|
// Disable USB2 device controller clocks.
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD);
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD);
|
||||||
/////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// Enable XUSB clock and clear Reset to XUSB Pad Control.
|
// Enable XUSB clock and clear Reset to XUSB Pad Control.
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_XUSB);
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_XUSB);
|
||||||
|
@ -927,6 +970,32 @@ int xusb_device_init()
|
||||||
return USB_RES_OK;
|
return USB_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! TODO: Power down more stuff.
|
||||||
|
static void _xusb_device_power_down()
|
||||||
|
{
|
||||||
|
// Force UTMIP_PLL power down.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= BIT(4) | BIT(0); // UTMIP_FORCE_PD_SAMP_A/C_POWERDOWN.
|
||||||
|
|
||||||
|
// Force enable UTMIPLL IDDQ.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) |= 3;
|
||||||
|
|
||||||
|
// Disable clocks for XUSB device and Super-Speed logic.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_XUSB_DEV);
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_XUSB_DEV);
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB_SS);
|
||||||
|
|
||||||
|
// Set XUSB_PADCTL clock reset.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
||||||
|
|
||||||
|
// Disable XUSB clock.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
||||||
|
|
||||||
|
// Disable PLLU.
|
||||||
|
clock_disable_pllu();
|
||||||
|
}
|
||||||
|
|
||||||
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||||
{
|
{
|
||||||
int res = USB_RES_OK;
|
int res = USB_RES_OK;
|
||||||
|
@ -1903,16 +1972,16 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||||
return USB_RES_OK;
|
return USB_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! TODO: Do a full deinit.
|
|
||||||
void xusb_end(bool reset_ep, bool only_controller)
|
void xusb_end(bool reset_ep, bool only_controller)
|
||||||
{
|
{
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
|
// Disable endpoints and stop device mode operation.
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB_SS);
|
_xusb_disable_ep1();
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_XUSB_DEV);
|
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_XUSB_DEV);
|
// Disable device mode.
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) &= ~XHCI_CTRL_ENABLE;
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
|
||||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
//! TODO: Add only controller support?
|
||||||
|
_xusb_device_power_down();
|
||||||
}
|
}
|
||||||
|
|
||||||
int xusb_handle_ep0_ctrl_setup()
|
int xusb_handle_ep0_ctrl_setup()
|
||||||
|
|
Loading…
Reference in a new issue