| # USBDEV Suspending and Resuming with Sleep / Low Power Modes |
| |
| # Overview |
| |
| This document outlines a recipe for going in and out of low power modes for suspending and resuming, respectively. |
| It assumes the design uses the `usbdev_aon_wake` and `pinmux` modules to handle critical signals in low-power mode like `top_earlgrey`. |
| The `pinmux` module ensures the D+ and D- pins are high-Z / input only. |
| The `usbdev_aon_wake` module maintains the pull-up state, monitors the D+ and D- pins for events to leave the suspended state, and provides the wake-up signal. |
| |
| Note that this procedure to hand control over to `usbdev_aon_wake` does not apply if there is no intention to go to a low-power mode. |
| |
| ## Suspending from Active |
| |
| ### Configuration |
| |
| 0. Software configures the sleep state for usbdev DIOs to be high-Z (input only), in the `pinmux`. |
| |
| ### Suspending |
| |
| 1. The `usbdev_linkstate` module detects the line has been at idle for at least 3 ms, issues `link_suspend_o`, and transitions to the `LinkSuspended` state. |
| - The protocol engine begins ignoring transactions. |
| Any non-idle signaling kicks off the process to resume. |
| - The USB differential receiver is turned off, if it was controlled by the `rx_enable_o` pin. |
| - Software receives the event for going into the suspended state in [`intr_state.link_suspend`](../data/usbdev.hjson#intr_state). |
| 2. Software hands control to the AON module. |
| - Software writes a `1` to [`wake_control.suspend_req`](../data/usbdev.hjson#wake_control). |
| - The AON module transitions to the active state and takes over the pullup enable. |
| It begins monitoring for events that trigger waking / resuming / resetting. |
| 3. Software prepares for deep sleep. |
| - It saves the current "device state" in the AON retention RAM, including the current configuration and device address (if any). |
| - The `usbdev_linkstate` module is still powered and monitoring events, and it can resume at any time. |
| Note that if a resume event does occur before the point of no return, software need only set [`wake_control.wake_ack`](../data/usbdev.hjson#wake_control) to restore control to `usbdev`. |
| - Software also does any other tasks for preparing for deep sleep, such as enabling USB events to wake the chip. |
| 4. Software begins deep sleep. |
| - This is the likely the point of no return. |
| - It turns off non-AON clocks and power. |
| - As it is now unpowered, the `usbdev_linkstate` module is inactive. |
| The AON module is now the only device monitoring for USB events. |
| |
| ### Resuming |
| |
| 1. Software determines whether it is waking due to USB. |
| - If the low-power state was never entered, software merely unwinds / drops the deep sleep preparation and skips to step 6. |
| 2. Software pulls configuration data from the AON retention RAM and restores information about the USB device state. |
| 3. Software sets up and connects usbdev. |
| - The `usbdev_linkstate` module should hold in the LinkPowered state, waiting for a bus reset. |
| It is now monitoring events alongside the AON module. |
| 4. Software releases the DIOs from sleep mode. |
| 5. Software checks the AON events and identifies the correct state transition. |
| 6. Software issues [`wake_control.wake_ack`](../data/usbdev.hjson#wake_control) to the AON module. |
| - The AON module stops monitoring events and controlling the pull-ups, restoring control to the full-power `usbdev` module. |
| - The AON module also clears the stored events. |
| Events that occurred between reading the stored values in the AON module and acknowledging the wake-up are captured in the `usbdev_linkstate` module. |
| 7. If software determined the state transition should be back to an active state, software issues [`usbctrl.resume_link_active`](../data/usbdev.hjson#usbctrl). |
| - After going to low-power, it's not clear to the hardware whether it needs a bus reset to transition out of the `LinkPowered` state. |
| Software's saved state in the AON retention RAM should provide this information, and the CSR write provides a bypass mechanism. |
| - The `usbdev_linkstate` module transitions from `LinkPowered` to `LinkResuming` state. |
| 8. The upstream hub stops signaling K to resume. |
| - The `usbdev_linkstate` module transitions from `LinkResuming` to `LinkActiveNoSOF` state, and USB is active once again. |