Difference between revisions of "Unit DWCOTG"

From Ultibo.org
Jump to: navigation, search
 
(22 intermediate revisions by the same user not shown)
Line 5: Line 5:
 
----
 
----
  
This is a USB Host Controller Driver (HCD) that interfaces with the Synopsys DesignWare Hi-Speed USB 2.0 On-The-Go Controller, henceforth abbreviated as "DWC". This is the USB Host Controller used on the BCM2835 SoC used on the Raspberry Pi.
+
'''USB Host Controller Driver for the Synopsys DesignWare Hi-Speed USB 2.0 On-The-Go Controller unit'''
 +
 
 +
This is a USB Host Controller Driver (HCD) that interfaces with the Synopsys DesignWare Hi-Speed USB 2.0 On-The-Go Controller, henceforth abbreviated as "DWC". This is the USB Host Controller used on the BCM2835 SoC used on the Raspberry Pi.
 
   
 
   
 
Please note that there is no publicly available official documentation for this particular piece of hardware, and it uses its own custom host controller interface rather than a standard one such as EHCI. Therefore, this driver was written on a best-effort basis using several sources to glean the necessary hardware details, including the extremely complicated and difficult to understand vendor provided Linux driver.
 
Please note that there is no publicly available official documentation for this particular piece of hardware, and it uses its own custom host controller interface rather than a standard one such as EHCI. Therefore, this driver was written on a best-effort basis using several sources to glean the necessary hardware details, including the extremely complicated and difficult to understand vendor provided Linux driver.
Line 28: Line 30:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
| <code>DWC_NUM_CHANNELS = 8;</code>
+
| <code>DWCOTG_USBHOST_DESCRIPTION = 'DWCOTG USB Host';</code>
| Number of DWC host channels
+
| Description of DWCOTG host
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_MAX_CHANNELS = 16;</code>
 +
| Maximum number of DWC host channels
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_SCHEDULER_MAILSLOT_SIZE = SIZE_1K;</code>
 +
| Mailslot size for USB request scheduler
 
|-
 
|-
 
|colspan="2"|&nbsp;  
 
|colspan="2"|&nbsp;  
Line 69: Line 81:
 
| <code>DWC_RESUBMIT_THREAD_NAME = 'DWC Transfer Resubmit';</code>
 
| <code>DWC_RESUBMIT_THREAD_NAME = 'DWC Transfer Resubmit';</code>
 
| Name of USB request resubmit threads
 
| Name of USB request resubmit threads
|-
 
|colspan="2"|&nbsp;
 
|-
 
| <code>DWC_START_SPLIT_INTR_TRANSFERS_ON_SOF = True;</code>
 
| Start Split Interrupt Transfers on Start of Frame (SOF)
 
 
|-
 
|-
 
|}
 
|}
Line 79: Line 86:
 
<br />  
 
<br />  
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC USB packet ID constants''' <code> DWC_USB_PID_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC USB packet ID''' <code> DWC_USB_PID_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 95: Line 102:
 
|-
 
|-
 
| <code>DWC_USB_PID_SETUP = 3;</code>
 
| <code>DWC_USB_PID_SETUP = 3;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_USB_PID_MDATA = 3;</code>
 
| &nbsp;
 
| &nbsp;
 
|-
 
|-
Line 101: Line 111:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC FIFO value constants''' <code> DWC_RECEIVE_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC FIFO value''' <code> DWC_RECEIVE_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 118: Line 128:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC status code constants''' <code> DWC_STATUS_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC status code''' <code> DWC_STATUS_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 156: Line 166:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC complete split constants''' <code> DWC_COMPLETE_SPLIT_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC complete split''' <code> DWC_COMPLETE_SPLIT_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
| <code>DWC_SPLIT_ERROR_RETRIES = 3;</code>
 +
| style="width: 50%;"|&nbsp;
 
|-
 
|-
 
| <code>DWC_COMPLETE_SPLIT_RETRIES = 10;</code>
 
| <code>DWC_COMPLETE_SPLIT_RETRIES = 10;</code>
Line 167: Line 180:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC register value constants''' <code> DWC_OTG_CTRL_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC register value''' <code> DWC_OTG_CTRL_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 180: Line 193:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC AHB configuration constants''' <code> DWC_AHB_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC AHB configuration''' <code> DWC_AHB_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 207: Line 220:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC core USB configuration constants''' <code> DWC_USB_CFG_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC core USB configuration''' <code> DWC_USB_CFG_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 213: Line 226:
 
|colspan="2"|TDWCRegisters: 0x000c : Core USB Configuration Register
 
|colspan="2"|TDWCRegisters: 0x000c : Core USB Configuration Register
 
|-
 
|-
| <code>DWC_USB_CFG_TOUTCAL_NASK = (7 shl 0);</code>
+
| <code>DWC_USB_CFG_TOUTCAL_MASK = (7 shl 0);</code>
 
| style="width: 50%;"|&nbsp;
 
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>DWC_USB_CFG_TOUTCAL_LIMIT = (7 shl 0);</code>
 +
| &nbsp;
 
|-
 
|-
 
| <code>DWC_USB_CFG_PHYIF16 = (1 shl 3);</code>
 
| <code>DWC_USB_CFG_PHYIF16 = (1 shl 3);</code>
Line 298: Line 314:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC core reset constants''' <code> DWC_SOFT_RESET* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC core reset''' <code> DWC_SOFT_RESET* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 311: Line 327:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC core interrupt constants''' <code> DWC_CORE_INTERRUPTS_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC core interrupt''' <code> DWC_CORE_INTERRUPTS_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 325: Line 341:
 
| <code>DWC_CORE_INTERRUPTS_HOST_CHANNEL_INTR = (1 shl 25);</code>
 
| <code>DWC_CORE_INTERRUPTS_HOST_CHANNEL_INTR = (1 shl 25);</code>
 
| Bit 25 Channel interrupt occurred. Software must examine the Host All Channels Interrupt Register to determine which channel(s) have pending interrupts, then handle and clear the interrupts for these channels.
 
| Bit 25 Channel interrupt occurred. Software must examine the Host All Channels Interrupt Register to determine which channel(s) have pending interrupts, then handle and clear the interrupts for these channels.
 +
|-
 +
| <code>DWC_CORE_INTERRUPTS_DISCONNECT = (1 shl 29);</code>
 +
| Bit 29 Disconnect interrupt indicated that a device has been disconnected from the root port.
 
|-
 
|-
 
|}
 
|}
Line 330: Line 349:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC vendor Id constants''' <code> DWC_VENDOR_ID_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC vendor Id''' <code> DWC_VENDOR_ID_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 351: Line 370:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC hardware configuration 2 constants''' <code> DWC_HWCFG2_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC hardware configuration 2''' <code> DWC_HWCFG2_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 472: Line 491:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC host frame interval constants''' <code> DWC_HFIR_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC host configuration''' <code> DWC_HCFG_* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|TDWCRegisters: 0x0400 : Host Configuration Register
 +
|-
 +
| <code>DWC_HCFG_FS_LS_PHY_CLK_SEL_MASK = (3 shl 0);</code>
 +
| FS/LS Phy Clock Select
 +
|-
 +
| <code>DWC_HCFG_FS_LS_PHY_CLK_SEL_SHIFT = 0;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_FS_LS_PHY_CLK_SEL_30_60_MHZ = 0;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FS_LS_PHY_CLK_SEL_48_MHZ = 1;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FS_LS_PHY_CLK_SEL_6_MHZ = 2;</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_FS_LS_SUPPORT_ONLY = (1 shl 2);</code>
 +
| FS/LS Only Support
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_ENABLE_32KHZ = (1 shl 7);</code>
 +
| Enable 32-KHz Suspend Mode
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_RESUME_VALID_MASK = ($FF shl 8);</code>
 +
| Resume Validation Period
 +
|-
 +
| <code>DWC_HCFG_RESUME_VALID_SHIFT = 8;</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_DESC_DMA = (1 shl 23);</code>
 +
| Enable Scatter/gather DMA in Host mode
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_MASK = (3 shl 24);</code>
 +
| Frame List Entries
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_SHIFT = 24;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_8 = (0 shl 24);</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_8_SIZE = 8;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_16 = (1 shl 24);</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_16_SIZE = 16;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_32 = (3 shl 24);</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_32_SIZE = 32;</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_64 = (3 shl 24);</code>
 +
| &nbsp;
 +
|-
 +
| <code>DWC_HCFG_FRAME_LIST_ENTRIES_64_SIZE = 64;</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>DWC_HCFG_PERSCHED_ENA = (1 shl 26);</code>
 +
| Enable Periodic Scheduling
 +
|-
 +
| <code>DWC_HCFG_MODE_CH_TIM_EN = (1 shl 31);</code>
 +
| &nbsp;
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''DWC host frame interval''' <code> DWC_HFIR_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 491: Line 598:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC host port control and status constants''' <code> DWC_HOST_PORT_CTRLSTATUS_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC host frame register''' <code> DWC_HFNUM_* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|TDWCRegisters: 0x0408 : Host Frame Register
 +
|-
 +
| <code>DWC_HFNUM_FRAME_NUMBER_MASK = $FFFF;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''DWC host port control and status''' <code> DWC_HOST_PORT_CTRLSTATUS_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 550: Line 670:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel characteristics constants''' <code> DWC_HOST_CHANNEL_CHARACTERISTICS_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel characteristics''' <code> DWC_HOST_CHANNEL_CHARACTERISTICS_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 597: Line 717:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel split control constants''' <code> DWC_HOST_CHANNEL_SPLIT_CONTROL_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel split control''' <code> DWC_HOST_CHANNEL_SPLIT_CONTROL_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 629: Line 749:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel interrupt constants''' <code> DWC_HOST_CHANNEL_INTERRUPTS_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel interrupt''' <code> DWC_HOST_CHANNEL_INTERRUPTS_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 644: Line 764:
 
<br />- When doing split transactions, this bit will be set after a Complete Split transaction has finished, even though the overall transfer may not actually be complete.
 
<br />- When doing split transactions, this bit will be set after a Complete Split transaction has finished, even though the overall transfer may not actually be complete.
 
<br />- The transfer will only be complete up to the extent that data was programmed into the channel. For example, control transfers have 3 phases, each of which must be programmed into the channel separately. This flag will be set after each of these phases has successfully completed.
 
<br />- The transfer will only be complete up to the extent that data was programmed into the channel. For example, control transfers have 3 phases, each of which must be programmed into the channel separately. This flag will be set after each of these phases has successfully completed.
<br />- An OUT transfer is otherwise considered complete when exactly the requested number of bytes of data have been successfully transferred, while an IN transfer is otherwise considered complete when exactly the requested number of bytes of data have been successfully transferred or a shorter-than-expected packet was received}
+
<br />- An OUT transfer is otherwise considered complete when exactly the requested number of bytes of data have been successfully transferred, while an IN transfer is otherwise considered complete when exactly the requested number of bytes of data have been successfully transferred or a shorter-than-expected packet was received.
 
|-
 
|-
 
| <code>DWC_HOST_CHANNEL_INTERRUPTS_CHANNEL_HALTED = (1 shl 1);</code>
 
| <code>DWC_HOST_CHANNEL_INTERRUPTS_CHANNEL_HALTED = (1 shl 1);</code>
Line 698: Line 818:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel interrupt mask constants''' <code> DWC_HOST_CHANNEL_INTERRUPT_MASK_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel interrupt mask''' <code> DWC_HOST_CHANNEL_INTERRUPT_MASK_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 755: Line 875:
 
<br />
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel transfer constants''' <code> DWC_HOST_CHANNEL_TRANSFER_* </code></div>
+
<div style="font-size: 14px; padding-left: 12px;">'''DWC channel transfer''' <code> DWC_HOST_CHANNEL_TRANSFER_* </code></div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
Line 770: Line 890:
 
|-
 
|-
 
| <code>DWC_HOST_CHANNEL_TRANSFER_PACKET_ID = ($03 shl 29);</code>
 
| <code>DWC_HOST_CHANNEL_TRANSFER_PACKET_ID = ($03 shl 29);</code>
| Bits 29-30 High 2 bits of the Packet ID used in the USB protocol. When performing the SETUP phase of a control transfer, specify 0x3 here to generate the needed SETUP token. When performing the DATA phase of a control transfer, initially specify 0x2 here to begin the DATA packets with the needed DATA1 Packet ID. When performing the STATUS phase of a control transfer, specify 0x2 here to generate the neeed DATA1 Packet ID. When starting a bulk, isochronous, or interrupt transfer, specify 0x0 here to generate the needed DATA0 Packet ID. In the case of a transfer consisting of multiple DATA packets, the hardware will update this field with the Packet ID to use for the next packet. This field therefore only needs to be re-programmed if the transfer is moved to a different channel or the channel is re-used before the transfer is complete. When doing so, software must save this field so that it can be re-programmed correctly.
+
| Bits 29-30 High 2 bits of the Packet ID used in the USB protocol. When performing the SETUP phase of a control transfer, specify 0x3 here to generate the needed SETUP token. When performing the DATA phase of a control transfer, initially specify 0x2 here to begin the DATA packets with the needed DATA1 Packet ID. When performing the STATUS phase of a control transfer, specify 0x2 here to generate the need DATA1 Packet ID. When starting a bulk, isochronous, or interrupt transfer, specify 0x0 here to generate the needed DATA0 Packet ID. In the case of a transfer consisting of multiple DATA packets, the hardware will update this field with the Packet ID to use for the next packet. This field therefore only needs to be re-programmed if the transfer is moved to a different channel or the channel is re-used before the transfer is complete. When doing so, software must save this field so that it can be re-programmed correctly.
 
|-
 
|-
 
| <code>DWC_HOST_CHANNEL_TRANSFER_DO_PING = (1 shl 31);</code>
 
| <code>DWC_HOST_CHANNEL_TRANSFER_DO_PING = (1 shl 31);</code>
| Bit 31
+
| Bit 31 Do PING protocol when 1 (See Section 8.5.1 of Universal Serial Bus Specification 2.0)
 
|-
 
|-
 
|}
 
|}
Line 782: Line 902:
 
----
 
----
  
''To be documented''
+
 
 +
'''DWC host channel'''
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial;">
 +
<code>PDWCHostChannel = ^TDWCHostChannel;</code>
 +
 
 +
<code>TDWCHostChannel = record</code>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|Note: TDWCRegisters: 0x0500 : Array of host channels. Each host channel can be used to execute an independent USB transfer or transaction simultaneously. A USB transfer may consist of multiple transactions, or packets. To avoid having to re-program the channel, it may be useful to use one channel for all transactions of a transfer before allowing other transfers to be scheduled on it.
 +
|-
 +
| <code>Characteristics:LongWord;</code>
 +
| (0x0000 : Channel Characteristics) Contains various fields that must be set to prepare this channel for a transfer to or from a particular endpoint on a particular USB device. This register only needs to be programmed one time when doing a transfer, regardless of how many packets it consists of, unless the channel is re-programmed for a different transfer or the transfer is moved to a different channel.
 +
|-
 +
| <code>SplitControl:LongWord;</code>
 +
| (0x0004 : Channel Split Control) This register is used to set up Split Transactions for communicating with low or full-speed devices attached to a high-speed hub. When doing so, set split_enable to 1 and the other fields as documented. Otherwise, software must clear this register before starting the transfer. Like the Channel Characteristics register, this register only needs to be programmed one time if the channel is enabled multiple times to send all the packets of a single transfer.
 +
|-
 +
| <code>Interrupts:LongWord;</code>
 +
| (0x0008 : Channel Interrupts) Bitmask of status conditions that have occurred on this channel. These bits can be used with or without "real" interrupts. To have the CPU get a real interrupt when one of these bits gets set, set the appropriate bit in the interrupt_mask, and also ensure that interrupts from the channel are enabled in the host_channels_interrupt_mask register, channel interrupts overall are enabled in the core_interrupt_mask register, and interrupts from the DWC hardware overall are enabled in the ahb_configuration register and by any system-specific interrupt controller.
 +
|-
 +
| <code>InterruptMask:LongWord;</code>
 +
| (0x000c : Channel Interrupts Mask) This has the same format as the Channel Interrupts Register, but software uses this to enable (1) or disable (0) the corresponding interrupt. Defaults to all 0's after a reset.
 +
|-
 +
| <code>Transfer:LongWord;</code>
 +
| (0x0010 : Channel Transfer) Used to store additional information about the transfer. This must be programmed before beginning the transfer.
 +
|-
 +
| <code>DMAAddress:LongWord;</code>
 +
| (0x0014 : Channel DMA Address) Word-aligned address at which the hardware will read or write data using Direct Memory Access. This must be programmed before beginning the transfer, unless the size of the data to send or receive is 0. The hardware will increment this address by the number of bytes successfully received or sent, which will correspond to the size decrease in transfer.size. Note: DMA must be enabled in the AHB Configuration Register before this register can be used. Otherwise, the hardware is considered to be in Slave mode and must be controlled a different way, which we do not use in our driver and do not attempt to document. BCM2835-specific note: Addresses written to this register must be bus addresses, not ARM physical addresses.
 +
|-
 +
| <code>Reserved0x0018:LongWord;</code>
 +
| (0x0018 : Reserved)
 +
|-
 +
| <code>Reserved0x001C:LongWord;</code>
 +
| (0x001C : Reserved)
 +
|-
 +
|}
 +
</div></div> 
 +
 +
'''DWC registers'''
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial;">
 +
<code>PDWCRegisters = ^TDWCRegisters;</code>
 +
 
 +
<code>TDWCRegisters = record</code>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|Note: Layout of the registers of the DesignWare Hi-Speed USB 2.0 On-The-Go Controller. There is no official documentation for these, however, the register locations (and to some extent the meanings) can be found in other code, such as the Linux driver for this hardware that Synopsys contributed.
 +
 +
We do not explicitly define every bit in the registers because the majority are not used by our driver and would complicate this file. For example, we do not attempt to document any features that are specific to suspend, hibernation, the OTG protocol, or to the core acting in device mode rather than host mode.
 +
 +
The bits and fields we do use in our driver we have tried to completely document based on our understanding of what they do. We cannot guarantee that all the information is correct, as we do not have access to any official documentation.
 +
|-
 +
|colspan="2"|''Core registers''
 +
|-
 +
| <code>OTGControl:LongWord;</code>
 +
| (0x0000 : OTG Control and Status)
 +
|-
 +
| <code>OTGInterrupt:LongWord;</code>
 +
| (0x0004 : OTG Interrupt)
 +
|-
 +
| <code>AHBConfiguration:LongWord;</code>
 +
| (0x0008 : Core AHB Configuration) This register configures some of the interactions the DWC has with the rest of the system.
 +
|-
 +
| <code>CoreUSBConfiguration:LongWord;</code>
 +
| (0x000c : Core USB Configuration)
 +
|-
 +
| <code>CoreReset:LongWord;</code>
 +
| (0x0010 : Core Reset) Software can use this register to cause the DWC to reset itself.
 +
|-
 +
| <code>CoreInterrupts:LongWord;</code>
 +
| (0x0014 : Core Interrupt) This register contains the state of pending top-level DWC interrupts. 1 means interrupt pending while 0 means no interrupt pending. Note that at least for port_intr and host_channel_intr, software must clear the interrupt somewhere else rather than by writing to this register.
 +
|-
 +
| <code>CoreInterruptMask:LongWord;</code>
 +
| (0x0018 : Core Interrupt Mask) This register has the same format as the Core Interrupt Register and configures whether the corresponding interrupt is enabled (1) or disabled (0). Initial state after reset is all 0's.
 +
|-
 +
| <code>ReceiveStatus:LongWord;</code>
 +
| (0x001c : Receive Status Queue Read (Read Only))
 +
|-
 +
| <code>ReceiveStatusPop:LongWord;</code>
 +
| (0x0020 : Receive Status Queue Read & POP (Read Only))
 +
|-
 +
| <code>ReceiveFIFOSize:LongWord;</code>
 +
| (0x0024 : Receive FIFO Size) This register contains the size of the Receive FIFO, in 4-byte words. This register must be set by software before using the controller (see the note in the documentation for the hwcfg3 register about configuring the dynamic FIFOs).
 +
|-
 +
| <code>NonPeriodicTransmitFIFOSize:LongWord;</code>
 +
| (0x0028 : Non Periodic Transmit FIFO Size) The low 16 bits of this register contain the offset of the Nonperiodic Transmit FIFO, in 4-byte words, from the start of the memory reserved by the controller for dynamic FIFOs. The high 16 bits of this register contain its size, in 4-byte words. This register must be set by software before using the controller (see the note in the documentation for the hwcfg3 register about configuring the dynamic FIFOs).
 +
|-
 +
| <code>NonPeriodicTransmitFIFOStatus:LongWord;</code>
 +
| (0x002c : Non Periodic Transmit FIFO/Queue Status (Read Only))
 +
|-
 +
| <code>I2CControl:LongWord;</code>
 +
| (0x0030 : I2C Access)
 +
|-
 +
| <code>PHYVendorControl:LongWord;</code>
 +
| (0x0034 : PHY Vendor Control)
 +
|-
 +
| <code>GPIO:LongWord;</code>
 +
| (0x0038 : General Purpose Input/Output)
 +
|-
 +
| <code>UserId:LongWord;</code>
 +
| (0x003c : User ID)
 +
|-
 +
| <code>VendorId:LongWord;</code>
 +
| (0x0040 : Vendor ID (Read Only))
 +
|-
 +
| <code>HWCfg1:LongWord;</code>
 +
| (0x0044 : User HW Config1 (Read Only))
 +
|-
 +
| <code>HWCfg2:LongWord;</code>
 +
| (0x0048 : User HW Config2 (Read Only))
 +
|-
 +
| <code>HWCfg3:LongWord;</code>
 +
| (0x004c : User HW Config3 (Read Only)) The high 16 bits of this read-only register contain the maximum total size, in words, of the dynamic FIFOs (Rx, Nonperiodic Tx, and Periodic Tx). Software must set up these three dynamic FIFOs in the rx_fifo_size, nonperiodic_tx_fifo_size, and host_periodic_tx_fifo_size registers such that their total size does not exceed this maximum total size and no FIFOs overlap. Note: Software must explicitly configure the dynamic FIFOs even if the controller is operating in DMA mode, since the default values for the FIFO sizes and offsets may be invalid. For example, in Broadcom's instantiation of this controller for the BCM2835, only 4080 words are available for dynamic FIFOs, but the dynamic FIFO sizes are set to 4096, 32, and 0, which are invalid as they add up to more than 4080. IF YOU DO NOT DO THIS YOU WILL GET SILENT MEMORY CORRUPTION. The low 16 bits of this register contain various flags that are not documented here as we don't use any in our driver.
 +
|-
 +
| <code>HWCfg4:LongWord;</code>
 +
| (0x0050 : User HW Config4 (Read Only))
 +
|-
 +
| <code>CoreLPMConfiguration:LongWord;</code>
 +
| (0x0054 :  Core LPM Configuration)
 +
|-
 +
| <code>GlobalPowerDown:LongWord;</code>
 +
| (0x0058 : Global PowerDown)
 +
|-
 +
| <code>GlobalFIFOConfig:LongWord;</code>
 +
| (0x005c : Global DFIFO SW Config)
 +
|-
 +
| <code>ADPControl:LongWord;</code>
 +
| (0x0060 : ADP Control (Attach Detection Protocol))
 +
|-
 +
| <code>Reserved0x0064:array[1..39] of LongWord;</code>
 +
| (0x0064 : Reserved)
 +
|-
 +
| <code>HostPeriodicTransmitFIFOSize:LongWord;</code>
 +
| (0x0100 : Host Periodic Transmit FIFO Size) The low 16 bits of this register configure the offset of the Periodic Transmit FIFO, in 4-byte words, from the start of the memory reserved by the controller for dynamic FIFOs. The high 16 bits of this register configure its size, in 4-byte words. This register should be set by software before using the controller (see the note in the documentation for the hwcfg3 register about configuring the dynamic FIFOs).
 +
|-
 +
| <code>Reserved0x0104:array[1..191] of LongWord;</code>
 +
| (0x0104 : Device Periodic Transmit FIFO#n) If dedicated fifos are disabled, otherwise Device Transmit FIFO#n.
 +
|-
 +
|colspan="2"|''Host registers''
 +
|-
 +
|colspan="2"|Note: The registers beginning at this point are considered to be the "Host" registers. These are used for the "Host" half of the OTG (On-The-Go) protocol, which allows this hardware to act as either a USB host or a USB device. This is the only half we are concerned with in this driver and we do not declare the corresponding Device registers.
 +
|-
 +
| <code>HostConfiguration:LongWord;</code>
 +
| (0x0400 : Host Configuration)
 +
|-
 +
| <code>HostFrameInterval:LongWord;</code>
 +
| (0x0404 : Host Frame Interval)
 +
|-
 +
| <code>HostFrameNumber:LongWord;</code>
 +
| (0x0408 : Host Frame Number/Frame Remaining)
 +
|-
 +
| <code>Reserved0x040c:LongWord;</code>
 +
| (0x040c : Reserved)
 +
|-
 +
| <code>HostFIFOStatus:LongWord;</code>
 +
| (0x0410 : Host Periodic Transmit FIFO/Queue Status)
 +
|-
 +
| <code>HostChannelsInterrupt:LongWord;</code>
 +
| (0x0414 : Host All Channels Interrupt) This register contains a bit for each host channel that indicates whether an interrupt has occurred on that host channel. You cannot clear the interrupts by writing to this register, use the channel-specific interrupt registers instead.
 +
|-
 +
| <code>HostChannelsInterruptMask:LongWord;</code>
 +
| (0x0418 : Host All Channels Interrupt Mask) Same format as the Host All Channels Interrupt Register, but a 1 in this register indicates that the corresponding host channel interrupt is enabled. Software can change this register. Defaults to all 0's after a reset.
 +
|-
 +
| <code>HostFrameList:LongWord;</code>
 +
| (0x041c : Host Frame List Base Address Register)
 +
|-
 +
| <code>Reserved0x0420:array[1..8] of LongWord;</code>
 +
| (0x0420)
 +
|-
 +
| <code>HostPortControlStatus:LongWord;</code>
 +
| (0x0440 : Host Port Control and Status) This register provides the information needed to respond to status queries about the "host port", which is the port that is logically attached to the root hub. When changing this register, software must read its value, then clear the enabled, connected_changed, enabled_changed, and overcurrent_changed members to avoid changing them, as those particular bits are cleared by writing 1.
 +
|-
 +
| <code>Reserved0x0444:array[1..47] of LongWord;</code>
 +
| (0x0444)
 +
|-
 +
|colspan="2"|''Host channel registers''
 +
|-
 +
| <code>HostChannels:array[0..DWC_MAX_CHANNELS - 1] of TDWCHostChannel;</code>
 +
| (0x0500 : Array of Host Channels) Each host channel can be used to execute an independent USB transfer or transaction simultaneously. A USB transfer may consist of multiple transactions, or packets. To avoid having to re-program the channel, it may be useful to use one channel for all transactions of a transfer before allowing other transfers to be scheduled on it.
 +
|-
 +
| <code>Reserved0x0700:array[1..((($800 - $500) - (DWC_MAX_CHANNELS * SizeOf(TDWCHostChannel))) div SizeOf(LongWord))] of LongWord;</code>
 +
| (0x0700)
 +
|-
 +
|colspan="2"|''Device registers''
 +
|-
 +
| <code>Reserved0x0800:array[1..(($E00 - $800) div SizeOf(LongWord))] of LongWord;</code>
 +
| (0x0800)
 +
|-
 +
| <code>PowerClockControl:LongWord;</code>
 +
| (0x0e00 : Power and Clock Gating Control)
 +
|-
 +
|}
 +
</div></div>
 +
 
 +
'''DWC root hub configuration'''
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial;">
 +
<code>PDWCRootHubConfiguration = ^TDWCRootHubConfiguration;</code>
 +
 
 +
<code>TDWCRootHubConfiguration = packed record</code>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
| <code>ConfigurationDescriptor:TUSBConfigurationDescriptor;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>InterfaceDescriptor:TUSBInterfaceDescriptor;</code>
 +
| &nbsp;
 +
|-
 +
| <code>EndpointDescriptor:TUSBEndpointDescriptor;</code>
 +
| &nbsp;
 +
|-
 +
|}
 +
</div></div>
 +
 
 +
'''DWC USB transfer'''
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial;">
 +
<code>PDWCUSBTransfer = ^TDWCUSBTransfer;</code>
 +
 
 +
<code>TDWCUSBTransfer = record</code>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
| style="width: 50%;"|&nbsp;
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
|}
 +
</div></div> 
 +
 
 +
'''DWC USB host'''
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial;">
 +
<code>PDWCUSBHost = ^TDWCUSBHost;</code>
 +
 
 +
<code>TDWCUSBHost = record</code>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|''USB Properties''
 +
|-
 +
| <code>Host:TUSBHost;</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''DWCOTG Properties''
 +
|-
 +
| <code>Lock:TSpinHandle;</code>
 +
| Host lock (Differs from lock in Host portion) (Spin lock due to use by interrupt handler)
 +
|-
 +
| <code>IRQ:LongWord;</code>
 +
| The IRQ assigned to this host
 +
|-
 +
| <code>PowerID:LongWord;</code>
 +
| The Power ID required to power on this host
 +
|-
 +
| <code>Registers:PDWCRegisters;</code>
 +
| Memory mapped registers of the Synopsys DesignWare Hi-Speed USB 2.0 OTG Controller
 +
|-
 +
| <code>ChannelCount:LongWord;</code>
 +
| The number of channels available on this host
 +
|-
 +
| <code>SchedulerThread:TThreadHandle;</code>
 +
| Thread ID of USB request scheduler thread
 +
|-
 +
| <code>CompletionThread:TThreadHandle;</code>
 +
| Thread ID of USB request completion thread
 +
|-
 +
| <code>SchedulerMailslot:TMailslotHandle;</code>
 +
| USB requests that have been submitted to the Host but not yet started on a channel
 +
|-
 +
|colspan="2"|''Channel Properties''
 +
|-
 +
| <code>DMABuffers:array[0..DWC_MAX_CHANNELS - 1] of Pointer;</code>
 +
| DMA buffers allocated for each hardware channel (4 byte aligned / 1 per channel)
 +
|-
 +
| <code>ChannelRequests:array[0..DWC_MAX_CHANNELS - 1] of PUSBRequest;</code>
 +
| Current USB request pending on each hardware channel (or nil of no request is pending)
 +
|-
 +
| <code>ChannelFreeMask:LongWord;</code>
 +
| Bitmap of channel free (1) or used (0) status
 +
|-
 +
| <code>ChannelFreeLock:TMutexHandle;</code>
 +
| Lock for access to ChannelFreeMask
 +
|-
 +
| <code>ChannelFreeWait:TSemaphoreHandle;</code>
 +
| Number of free channels in ChannelFreeMask
 +
|-
 +
| <code>StartOfFrameMask:LongWord;</code>
 +
| Bitmap of channels waiting for Start of Frame
 +
|-
 +
| <code>StartOfFrameLock:TSpinHandle;</code>
 +
| Lock for access to StartOfFrameMask (Spin lock due to use by interrupt handler)
 +
|-
 +
| <code>LastFrameNumber:LongWord;</code>
 +
| Frame Number at the last Start Of Frame interrupt
 +
|-
 +
|colspan="2"|''Root Hub Properties''
 +
|-
 +
| <code>HubStatus:PUSBHubStatus;</code>
 +
| Hub status for the root hub
 +
|-
 +
| <code>PortStatus:PUSBPortStatus;</code>
 +
| Host port status for the root hub (Obtained from port interrupt due to status change)
 +
|-
 +
| <code>DeviceStatus:PUSBDeviceStatus;</code>
 +
| Device status for the root hub
 +
|-
 +
| <code>HubDescriptor:PUSBHubDescriptor;</code>
 +
| Hub descriptor for the root hub
 +
|-
 +
| <code>DeviceDescriptor:PUSBDeviceDescriptor;</code>
 +
| Device descriptor for the root hub
 +
|-
 +
| <code>HubConfiguration:PDWCRootHubConfiguration;</code>
 +
| Configuration, Interface and Endpoint descriptors for the root hub
 +
|-
 +
| <code>HubStringTable:array[0..2] of PUSBStringDescriptor;</code>
 +
| String table for Language, Product and Manufacturer strings for the root hub
 +
|-
 +
| <code>HubProductString:PUSBStringDescriptor;</code>
 +
| Product identifier string for the root hub
 +
|-
 +
| <code>HubLanguageString:PUSBStringDescriptor;</code>
 +
| Language identifier string for the root hub
 +
|-
 +
| <code>HubManufacturerString:PUSBStringDescriptor;</code>
 +
| Manufacturer identifier string for the root hub
 +
|-
 +
| <code>HubStatusChange:PUSBRequest;</code>
 +
| Status change request to the root hub interrupt endpoint (nil if no request is pending)
 +
|-
 +
|colspan="2"|''Statistics Properties''
 +
|-
 +
| <code>InterruptCount:LongWord;</code>
 +
| Number of interrupt requests received by the host controller
 +
|-
 +
| <code>PortInterruptCount:LongWord;</code>
 +
| Number of port interrupts received by the host controller
 +
|-
 +
| <code>ChannelInterruptCount:LongWord;</code>
 +
| Number of channel interrupts received by the host controller
 +
|-
 +
| <code>StartOfFrameInterruptCount:LongWord;</code>
 +
| Number of start of frame interrupts received by the host controller
 +
|-
 +
| <code>DisconnectInterruptCount:LongWord;</code>
 +
| Number of disconnect interrupts received by the host controller
 +
|-
 +
| <code>ResubmitCount:LongWord;</code>
 +
| Number of requests resubmitted for later retry
 +
|-
 +
| <code>StartOfFrameCount:LongWord;</code>
 +
| Number of requests queued to wait for start of frame
 +
|-
 +
| <code>DMABufferReadCount:LongWord;</code>
 +
| Number of IN requests that required a DMA buffer copy
 +
|-
 +
| <code>DMABufferWriteCount:LongWord;</code>
 +
| Number of OUT requests that required a DMA buffer copy
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>NAKResponseCount:LongWord;</code>
 +
| Number of NAK responses received by the host controller
 +
|-
 +
| <code>NYETResponseCount:LongWord;</code>
 +
| Number of NYET responses received by the host controller
 +
|-
 +
| <code>StallResponseCount:LongWord;</code>
 +
| Number of Stall responses received by the host controller
 +
|-
 +
| <code>RequestCancelCount:LongWord;</code>
 +
| Number of requests Cancelled by the host controller
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>AHBErrorCount:LongWord;</code>
 +
| Number of AHB errors received by the host controller
 +
|-
 +
| <code>TransactionErrorCount:LongWord;</code>
 +
| Number of transaction errors received by the host controller
 +
|-
 +
| <code>BabbleErrorCount:LongWord;</code>
 +
| Number of babble errors received by the host controller
 +
|-
 +
| <code>ExcessTransactionCount:LongWord;</code>
 +
| Number of excess transaction errors received by the host controller
 +
|-
 +
| <code>FrameListRolloverCount:LongWord;</code>
 +
| Number of frame list rollover errors received by the host controller
 +
|-
 +
| <code>DataToggleErrorCount:LongWord;</code>
 +
| Number of data toggle errors received by the host controller
 +
|-
 +
| <code>FrameOverrunCount:LongWord;</code>
 +
| Number of frame overrun errors received by the host controller
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>ShortAttemptCount:LongWord;</code>
 +
| Number of short attempts where transfer size was less than the request size
 +
|-
 +
| <code>StartSplitCount:LongWord;</code>
 +
| Number of start split transactions
 +
|-
 +
| <code>CompleteSplitCount:LongWord;</code>
 +
| Number of complete split transactions
 +
|-
 +
| <code>CompleteSplitRestartCount:LongWord;</code>
 +
| Number of times a complete split transaction has been restarted at start split due to errors
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>TransferRestartCount:LongWord;</code>
 +
| Number of times a transfer is restarted to continue or retry the transfer
 +
|-
 +
| <code>TransactionRestartCount:LongWord;</code>
 +
| Number of times a transaction is restarted to continue or complete the transfer
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>NoChannelCompletedCount:LongWord;</code>
 +
| Number of times the channel completed interrupt bit was not set when a request completed
 +
|-
 +
| <code>NoPacketsTransferredCount:LongWord;</code>
 +
| Number of times no packets were transferred but no error occured when a channel halted
 +
|-
 +
|}
 +
</div></div>
 +
<br />
  
 
=== Public variables ===
 
=== Public variables ===
 
----
 
----
  
''To be documented''
+
''None defined''
  
 
=== Function declarations ===
 
=== Function declarations ===
Line 801: Line 1,352:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
 
|-
 
|-
Line 809: Line 1,360:
  
 
'''DWCOTG functions'''
 
'''DWCOTG functions'''
 +
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
 +
<pre style="border: 0; padding-bottom:0px;">function DWCHostCreate(Address:PtrUInt; IRQ,PowerID:LongWord):PUSBHost;</pre>
 +
<div style="font-size: 14px; padding-left: 12px;">'''Description:''' Create and register a new DWCOTG host which can be accessed using the USB API</div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
! Address
 +
| The address of the DWCOTG registers
 +
|-
 +
! IRQ
 +
| The interrupt number for the DWCOTG host
 +
|-
 +
! PowerID
 +
| The power ID value to power on the host using PowerOn (or POWER_ID_UNKNOWN if not applicable)
 +
|-
 +
! Return
 +
| Pointer to the new USB host or nil if the USB host could not be created
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
 +
<pre style="border: 0; padding-bottom:0px;">function DWCHostDestroy(Host:PUSBHost):LongWord;</pre>
 +
<div style="font-size: 14px; padding-left: 12px;">'''Description:''' Stop, deregister and destroy a DWCOTG USB host created by this driver</div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
! Host
 +
| The USB host to destroy
 +
|-
 +
! Return
 +
| ERROR_SUCCESS if completed or another error code on failure
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
 +
'''DWCOTG USB functions'''
  
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
Line 816: Line 1,406:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
|-
 
|-
Line 828: Line 1,418:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
|-
 
|-
Line 840: Line 1,430:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
 
|-
 
|-
Line 852: Line 1,442:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 864: Line 1,454:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
| See usb.pas for the documentation of this interface of the Host Controller Driver
This Host Controller Driver implements this interface asynchronously, as intended. Furthermore, it uses a simplistic scheduling algorithm where it places requests into a single queue and executes them in the order they were submitted. Transfers that need to be retried, including periodic transfers that receive a NAK reply and split transactions that receive a NYET reply when doing the Complete Split transaction, are scheduled to be retried at an appropriate time by separate code that shortcuts the main queue when the timer expires.
+
This Host Controller Driver implements this interface asynchronously, as intended. Furthermore, it uses a simplistic scheduling algorithm where it places requests into a single queue and executes them in the order they were submitted. Transfers that need to be retried, including periodic transfers that receive a NAK reply and split transactions that receive a NYET reply when doing the Complete Split transaction, are scheduled to be retried at an appropriate time by separate code that shortcuts the main queue when the timer expires.
 
<br />Caller must hold the device lock.
 
<br />Caller must hold the device lock.
 
|-
 
|-
Line 881: Line 1,471:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
| See usb.pas for the documentation of thisinterface of the Host Controller Driver
+
| See usb.pas for the documentation of this interface of the Host Controller Driver
 
Caller must hold the device lock
 
Caller must hold the device lock
 
|-
 
|-
Line 897: Line 1,487:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Request'''
+
! Request
 
| USB transfer to resubmit
 
| USB transfer to resubmit
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| For periodic transfers (e.g. polling an interrupt endpoint), the exact time at which the transfer must be retried is specified by the bInterval member of the endpoint descriptor. For low and full-speed devices, bInterval specifies the number of millisconds to wait before the next poll, while for high-speed devices it specifies the exponent (plus one) of a power-of-two number of milliseconds to wait before the next poll.
 
| For periodic transfers (e.g. polling an interrupt endpoint), the exact time at which the transfer must be retried is specified by the bInterval member of the endpoint descriptor. For low and full-speed devices, bInterval specifies the number of millisconds to wait before the next poll, while for high-speed devices it specifies the exponent (plus one) of a power-of-two number of milliseconds to wait before the next poll.
To actually implement delaying a transfer, we associate each transfer with a thread created on-demand. Each such thread simply enters a loop where it calls sleep() for the appropriate number of milliseconds, then retries the transfer. A semaphore is needed to make the thread do nothing until the request has actually been resubmitted.
+
To actually implement delaying a transfer, we associate each transfer with a thread created on-demand. Each such thread simply enters a loop where it calls sleep() for the appropriate number of milliseconds, then retries the transfer. A semaphore is needed to make the thread do nothing until the request has actually been resubmitted.
<br />This code gets used to scheduling polling of IN interrupt endpoints, including those on hubs and HID devices. Thus, polling of these devices for status changes (in the case of hubs) or new input (in the case of HID devices) is done in software. This wakes up the CPU a lot and wastes time and energy. But with USB 2.0, there is no way around this, other than by suspending the USB device which we don't support.
+
<br />This code gets used to schedule polling of IN interrupt endpoints, including those on hubs and HID devices. Thus, polling of these devices for status changes (in the case of hubs) or new input (in the case of HID devices) is done in software. This wakes up the CPU a lot and wastes time and energy. But with USB 2.0, there is no way around this, other than by suspending the USB device which we don't support.
 
|-
 
|-
 
|}
 
|}
Line 917: Line 1,507:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host to power on
 
| The DWCOTG host to power on
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
Line 932: Line 1,522:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host to power off
 
| The DWCOTG host to power off
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
Line 947: Line 1,537:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
Line 959: Line 1,549:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
Line 971: Line 1,561:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
|-
 
|}
 
</div></div>
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
 
<pre style="border: 0; padding-bottom:0px;">function DWCHostSetupDMA(Host:PDWCUSBHost):LongWord;</pre>
 
<div style="font-size: 14px; padding-left: 12px;">'''Description:''' Set up the DWC OTG USB Host Controller for DMA (direct memory access). This makes it possible for the Host Controller to directly access in-memory buffers when performing USB transfers.</div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
! '''Note'''
 
| None documented
 
|-
 
|}
 
</div></div>
 
<br />
 
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 0px; padding-bottom: 15px;">
 
<pre style="border: 0; padding-bottom:0px;">function DWCHostSetupInterrupts(Host:PDWCUSBHost):LongWord;</pre>
 
<div style="font-size: 14px; padding-left: 12px;">'''Description:''' Performs initial setup of the Synopsys Designware USB 2.0 On-The-Go Controller (DWC) interrupts</div>
 
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
! '''Note'''
 
| The DWC contains several levels of interrupt registers, detailed in the following list.  Note that for each level, each bit of the "interrupt" register contains the state of a pending interrupt (1 means interrupt pending; write 1 to clear), while the "interrupt mask" register has the same format but is used to turn the corresponding interrupt on or off (1 means on; write 1 to turn on; write 0 to turn off).
 
- The AHB configuration register contains a mask bit used to enable/disable all interrupts whatsoever from the DWC hardware.
 
<br />- The "Core" interrupt and interrupt mask registers control top-level interrupts. For example, a single bit in these registers corresponds to all channel interrupts.
 
<br />- The "Host All Channels" interrupt and interrupt mask registers control all interrupts on each channel.
 
<br />- The "Channel" interrupt and interrupt mask registers, of which one copy exists for each channel, control individual interrupt types on that channel.
 
<br />We can assume that an interrupt only occurs if it is enabled in all the places listed above.  Furthermore, it only seems to work to clear interrupts at the lowest level; for example, a channel interrupt must be cleared in its individual channel interrupt register rather than in one of the higher level interrupt registers.
 
<br />The above just covers the DWC-specific interrupt registers. In addition to those, the system will have other ways to control interrupts. For example, on the BCM2835 (Raspberry Pi), the interrupt line going to the DWC is just one of many dozen and can be enabled/disabled using the interrupt controller. In the code below we enable this interrupt line and register a handler function so that we can actually get interrupts from the DWC.
 
<br />And all that's in addition to the CPSR of the ARM processor itself, or the equivalent on other CPUs. So all in all, you literally have to enable interrupts in 6 different places to get an interrupt when a USB transfer has completed
 
 
|-
 
|-
 
|}
 
|}
Line 1,014: Line 1,573:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
 
|-
 
|-
Line 1,026: Line 1,585:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host to get available channel from
 
| The DWC host to get available channel from
 
|-
 
|-
! '''Return'''
+
! Return
 
| Channel number of the next available channel
 
| Channel number of the next available channel
 
|-
 
|-
Line 1,041: Line 1,600:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host to mark available channel on
 
| The DWC host to mark available channel on
 
|-
 
|-
! '''Channel'''
+
! Channel
 
| The channel number to mark as available
 
| The channel number to mark as available
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
Line 1,059: Line 1,618:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host to start the request on
 
| The DWC host to start the request on
 
|-
 
|-
! '''Channel'''
+
! Channel
 
| The channel number to start the request on
 
| The channel number to start the request on
 
|-
 
|-
! '''Request'''
+
! Request
 
| USB request to start
 
| USB request to start
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the host lock
 
| Caller must hold the host lock
 
Can be called by the interrupt handler
 
Can be called by the interrupt handler
Line 1,081: Line 1,640:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host to start the transaction on
 
| The DWC host to start the transaction on
 
|-
 
|-
! '''Channel'''
+
! Channel
 
| The host channel number to start the transaction on
 
| The host channel number to start the transaction on
 
|-
 
|-
! '''Request'''
+
! Request
 
| USB request set up for the next transaction
 
| USB request set up for the next transaction
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the host lock
 
| Caller must hold the host lock
 
Can be called by the interrupt handler
 
Can be called by the interrupt handler
Line 1,103: Line 1,662:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,115: Line 1,674:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,127: Line 1,686:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,139: Line 1,698:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,151: Line 1,710:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,163: Line 1,722:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host for the change request
 
| The DWCOTG host for the change request
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
Can be called by the interrupt handler
 
Can be called by the interrupt handler
Line 1,179: Line 1,738:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host for the request
 
| The DWCOTG host for the request
 
|-
 
|-
! '''Request'''
+
! Request
 
| The USB request to perform
 
| The USB request to perform
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,200: Line 1,759:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host for the request
 
| The DWCOTG host for the request
 
|-
 
|-
! '''Request'''
+
! Request
 
| The USB request to perform
 
| The USB request to perform
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,221: Line 1,780:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host for the request
 
| The DWCOTG host for the request
 
|-
 
|-
! '''Request'''
+
! Request
 
| Hub specific request to the root hub
 
| Hub specific request to the root hub
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,242: Line 1,801:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host for the request
 
| The DWCOTG host for the request
 
|-
 
|-
! '''Request'''
+
! Request
 
| Standard request to the root hub
 
| Standard request to the root hub
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| Caller must hold the Host lock
 
| Caller must hold the Host lock
 
|-
 
|-
Line 1,263: Line 1,822:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
 
|-
 
|-
Line 1,275: Line 1,834:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| USB host to service submitted requests for
 
| USB host to service submitted requests for
 
|-
 
|-
! '''Note'''
+
! Note
 
| This thread receives requests that have been submitted and schedules them on the next available channel.
 
| This thread receives requests that have been submitted and schedules them on the next available channel.
 
This is a very simplistic scheduler that does not take into account bandwidth requirements or which endpoint a transfer is for.
 
This is a very simplistic scheduler that does not take into account bandwidth requirements or which endpoint a transfer is for.
Line 1,291: Line 1,850:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| USB host to service completed requests for
 
| USB host to service completed requests for
 
|-
 
|-
! '''Note'''
+
! Note
 
| This thread receives completed requests which have either succeeded or failed and calls the completion handler which will call the registered callback for the request.
 
| This thread receives completed requests which have either succeeded or failed and calls the completion handler which will call the registered callback for the request.
 
This thread also receives requests that need to be resubmitted and resubmits them for later processing by another thread.
 
This thread also receives requests that need to be resubmitted and resubmits them for later processing by another thread.
Line 1,311: Line 1,870:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Request'''
+
! Request
 
| USB request to resubmit
 
| USB request to resubmit
 
|-
 
|-
! '''Note'''
+
! Note
| An instance of this thread is created for each request that needs to be resubmitted, this thread then either waits for a predetermined number of milliseconds before scheduling the request on the next available channel or waits for a signal from the interrupt handler to indicate a start of frame before scheduling the request on the allocated channel.
+
| An instance of this thread is created for each request that needs to be resubmitted, this thread then either waits for a predetermined number of milliseconds before scheduling the request on the next available channel.
 
Once the request has been resubmitted the thread waits for the semaphore to be signaled again. If the request is a periodic polling of an endpoint then it will be resubmitted continuously at the predetermined interval, otherwise the semaphore will be destroyed by the completion handler and the thread will terminate.
 
Once the request has been resubmitted the thread waits for the semaphore to be signaled again. If the request is a periodic polling of an endpoint then it will be resubmitted continuously at the predetermined interval, otherwise the semaphore will be destroyed by the completion handler and the thread will terminate.
 
|-
 
|-
Line 1,327: Line 1,886:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host where the interrupt occurred
 
| The DWC host where the interrupt occurred
 
|-
 
|-
Line 1,339: Line 1,898:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host where the interrupt occurred
 
| The DWC host where the interrupt occurred
 
|-
 
|-
! '''Channel'''
+
! Channel
 
| DWC host channel where the channel interrupt occurred
 
| DWC host channel where the channel interrupt occurred
 
|-
 
|-
! '''Return'''
+
! Return
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
| USB_STATUS_SUCCESS if completed or another error code on failure
 
|-
 
|-
! '''Note'''
+
! Note
 
| Only called by DWCInterruptHandler
 
| Only called by DWCInterruptHandler
 
Caller must hold the host lock
 
Caller must hold the host lock
Line 1,361: Line 1,920:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Request'''
+
! Request
 
| The USB request currently scheduled on this channel
 
| The USB request currently scheduled on this channel
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWC host where the interrupt occurred
 
| The DWC host where the interrupt occurred
 
|-
 
|-
! '''Channel'''
+
! Channel
 
| DWC host channel where the channel interrupt occurred
 
| DWC host channel where the channel interrupt occurred
 
|-
 
|-
! '''Interrupts'''
+
! Interrupts
 
| The currently pending interrupts on this channel
 
| The currently pending interrupts on this channel
 
|-
 
|-
! '''Note'''
+
! Note
 
| Only called by DWCChannelInterrupt
 
| Only called by DWCChannelInterrupt
 
Caller must hold the host lock
 
Caller must hold the host lock
Line 1,389: Line 1,948:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Note'''
+
! Note
 
| None documented
 
| None documented
 
|-
 
|-
Line 1,401: Line 1,960:
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
{| class="wikitable" style="font-size: 14px; background: white;"
 
|-
 
|-
! '''Host'''
+
! Host
 
| The DWCOTG host to calculate the interval for
 
| The DWCOTG host to calculate the interval for
 
|-
 
|-
! '''Note'''
+
! Note
 
| The host frame interval register can only be modified when the port enabled bit is set in the host port control and status register
 
| The host frame interval register can only be modified when the port enabled bit is set in the host port control and status register
 
Caller must hold the Host lock
 
Caller must hold the Host lock

Latest revision as of 04:10, 23 March 2023

Return to Unit Reference


Description


USB Host Controller Driver for the Synopsys DesignWare Hi-Speed USB 2.0 On-The-Go Controller unit

This is a USB Host Controller Driver (HCD) that interfaces with the Synopsys DesignWare Hi-Speed USB 2.0 On-The-Go Controller, henceforth abbreviated as "DWC". This is the USB Host Controller used on the BCM2835 SoC used on the Raspberry Pi.

Please note that there is no publicly available official documentation for this particular piece of hardware, and it uses its own custom host controller interface rather than a standard one such as EHCI. Therefore, this driver was written on a best-effort basis using several sources to glean the necessary hardware details, including the extremely complicated and difficult to understand vendor provided Linux driver.

This file implements the Host Controller Driver Interface defined in TUSBHost. Most importantly, it implements a function to power on and start the host controller (HostStart) and a function to send and receive messages over the USB (HostSubmit).

The DWC is controlled by reading and writing to/from memory-mapped registers. The most important registers are the host channel registers. On this particular hardware, a "host channel", or simply "channel", is a set of registers to which software can read and write to cause transactions to take place on the USB. A fixed number of host channels exist, on the Raspberry Pi there are 8. From the software's perspective, transactions using different host channels can be executed at the same time.

Some of the host channel registers, as well as other registers, deal with interrupts. This driver makes heavy use of these and performs all USB transfers in an interrupt-driven manner. However, due to design flaws in this hardware and in USB 2.0 itself, "interrupt" and "isochronous" transfers still need to make use of software polling when checking for new data, even though each individual transfer is itself interrupt-driven. This means that, for example, if your USB mouse specifies a polling rate of 100 times per second, then it will, unfortunately, be polled 100 times per second in software. For more detail about how interrupts can be controlled on this particular hardware, see the comment above DWCSetupInterrupts. Another important concept is the idea of "packets", "transactions", and "transfers". A USB transfer, such as a single control message or bulk request, may need to be split into multiple packets if it exceeds the endpoint's maximum packet size. Unfortunately, this has to be dealt with explicitly in this code, as this hardware doesn't do it for us. But at least, from the viewpoint of this software, a "transaction" is essentially the same as a "packet".

The "On-The-Go" in the name of this hardware means that it supports the USB On-The-Go protocol, which allows it to act either as a host or a device. However, we only are concerned with it acting as a host, which simplifies our driver.

To simplify the USB core software, a useful design technique (as recommended by the USB 2.0 standard and used in other implementations such as Linux's) is to have the HCD present the root hub as a standard USB hub, even if the root hub is integrated with the host controller and does not appear as a standard hub at the hardware level. This is the case with the DWC, and we implement this design. Therefore, some code in this file deals with faking requests sent to the root hub.

Constants



[Expand]
DWCOTG specific constants DWC_*


[Expand]
DWC USB packet ID DWC_USB_PID_*


[Expand]
DWC FIFO value DWC_RECEIVE_*


[Expand]
DWC status code DWC_STATUS_*


[Expand]
DWC complete split DWC_COMPLETE_SPLIT_*


[Expand]
DWC register value DWC_OTG_CTRL_*


[Expand]
DWC AHB configuration DWC_AHB_*


[Expand]
DWC core USB configuration DWC_USB_CFG_*


[Expand]
DWC core reset DWC_SOFT_RESET*


[Expand]
DWC core interrupt DWC_CORE_INTERRUPTS_*


[Expand]
DWC vendor Id DWC_VENDOR_ID_*


[Expand]
DWC hardware configuration 2 DWC_HWCFG2_*


[Expand]
DWC host configuration DWC_HCFG_*


[Expand]
DWC host frame interval DWC_HFIR_*


[Expand]
DWC host frame register DWC_HFNUM_*


[Expand]
DWC host port control and status DWC_HOST_PORT_CTRLSTATUS_*


[Expand]
DWC channel characteristics DWC_HOST_CHANNEL_CHARACTERISTICS_*


[Expand]
DWC channel split control DWC_HOST_CHANNEL_SPLIT_CONTROL_*


[Expand]
DWC channel interrupt DWC_HOST_CHANNEL_INTERRUPTS_*


[Expand]
DWC channel interrupt mask DWC_HOST_CHANNEL_INTERRUPT_MASK_*


[Expand]
DWC channel transfer DWC_HOST_CHANNEL_TRANSFER_*


Type definitions



DWC host channel

[Expand]

PDWCHostChannel = ^TDWCHostChannel;

TDWCHostChannel = record

DWC registers

[Expand]

PDWCRegisters = ^TDWCRegisters;

TDWCRegisters = record

DWC root hub configuration

[Expand]

PDWCRootHubConfiguration = ^TDWCRootHubConfiguration;

TDWCRootHubConfiguration = packed record

DWC USB transfer

[Expand]

PDWCUSBTransfer = ^TDWCUSBTransfer;

TDWCUSBTransfer = record

DWC USB host

[Expand]

PDWCUSBHost = ^TDWCUSBHost;

TDWCUSBHost = record


Public variables


None defined

Function declarations



Initialization functions

[Expand]
procedure DWCInit;
Description: To be documented


DWCOTG functions

[Expand]
function DWCHostCreate(Address:PtrUInt; IRQ,PowerID:LongWord):PUSBHost;
Description: Create and register a new DWCOTG host which can be accessed using the USB API


[Expand]
function DWCHostDestroy(Host:PUSBHost):LongWord;
Description: Stop, deregister and destroy a DWCOTG USB host created by this driver


DWCOTG USB functions

[Expand]
function DWCHostStart(Host:PUSBHost):LongWord;
Description: Implementation of USBHostStart for the DesignWare Hi-Speed USB 2.0 On-The-Go Controller


[Expand]
function DWCHostStop(Host:PUSBHost):LongWord;
Description: Implementation of USBHostStop for the DesignWare Hi-Speed USB 2.0 On-The-Go Controller


[Expand]
function DWCHostReset(Host:PUSBHost):LongWord;
Description: Performs a software reset of the DWC OTG Controller


[Expand]
function DWCHostResetEx(Host:PDWCUSBHost):LongWord;
Description: Performs a software reset of the DWC OTG Controller


[Expand]
function DWCHostSubmit(Host:PUSBHost; Request:PUSBRequest):LongWord;
Description: Implementation of USBHostSubmit for the DesignWare Hi-Speed USB 2.0 On-The-Go Controller


[Expand]
function DWCHostCancel(Host:PUSBHost; Request:PUSBRequest):LongWord;
Description: Implementation of USBHostCancel for the DesignWare Hi-Speed USB 2.0 On-The-Go Controller


[Expand]
function DWCHostResubmit(Host:PDWCUSBHost; Request:PUSBRequest):LongWord;
Description: Called when a USB transfer needs to be retried at a later time due to no data being available from the endpoint


[Expand]
function DWCHostPowerOn(Host:PDWCUSBHost):LongWord;
Description: Power on the DWCOTG Host controller


[Expand]
function DWCHostPowerOff(Host:PDWCUSBHost):LongWord;
Description: Powers off the DWCOTG Host controller


[Expand]
function DWCHostCheck(Host:PDWCUSBHost):LongWord;
Description: Check the DWC OTG USB Host Controller to confirm it is valid


[Expand]
function DWCHostInit(Host:PDWCUSBHost):LongWord;
Description: Initialize the DWC OTG USB Host Controller with core USB settings and perform a host reset


[Expand]
function DWCHostSetup(Host:PDWCUSBHost):LongWord;
Description: Configure the DWC OTG USB Host Controller with....


[Expand]
function DWCHostStartFrameInterrupt(Host:PDWCUSBHost; Enable:Boolean):LongWord;
Description: To be documented


[Expand]
function DWCAllocateChannel(Host:PDWCUSBHost):LongWord;
Description: Get the next available host channel on the supplied DWC host


[Expand]
function DWCReleaseChannel(Host:PDWCUSBHost; Channel:LongWord):LongWord;
Description: Mark the specified host channel on the supplied DWC host as available


[Expand]
function DWCChannelStartTransfer(Host:PDWCUSBHost; Channel:LongWord; Request:PUSBRequest):LongWord;
Description: Start or restart a USB request on a channel of the supplied DWC host


[Expand]
function DWCChannelStartTransaction(Host:PDWCUSBHost; Channel:LongWord; Request:PUSBRequest):LongWord;
Description: Start a USB transaction on a channel of the supplied DWC host


[Expand]
function DWCHostPortReset(Host:PDWCUSBHost):LongWord;
Description: Resets the DWC host port (The USB port that is attached to the root hub)


[Expand]
function DWCHostPortPowerOn(Host:PDWCUSBHost):LongWord;
Description: Powers on the DWC host port (The USB port that is attached to the root hub)


[Expand]
function DWCHostPortGetStatus(Host:PDWCUSBHost):LongWord;
Description: Read the Host Port Control and Status register with the intention of modifying it. Due to the inconsistent design of the bits in this register, this requires zeroing the write-clear bits so they aren't unintentionally cleared by writing back 1's to them.


[Expand]
function DWCHostPortSetFeature(Host:PDWCUSBHost; Feature:Word):LongWord;
Description: Handle a SetPortFeature request on the port attached to the root hub


[Expand]
function DWCHostPortClearFeature(Host:PDWCUSBHost; Feature:Word):LongWord;
Description: Handle a ClearPortFeature request on the port attached to the root hub


[Expand]
procedure DWCHostPortStatusChanged(Host:PDWCUSBHost);
Description: Complete any outstanding IN interrupt status change request


[Expand]
function DWCRootHubRequest(Host:PDWCUSBHost; Request:PUSBRequest):LongWord;
Description: Perform a request to the root hub


[Expand]
function DWCRootHubControlRequest(Host:PDWCUSBHost; Request:PUSBRequest):LongWord;
Description: Perform a control request to or from the root hub


[Expand]
function DWCRootHubClassRequest(Host:PDWCUSBHost; Request:PUSBRequest):LongWord;
Description: Perform a hub specific control request to the root hub


[Expand]
function DWCRootHubStandardRequest(Host:PDWCUSBHost; Request:PUSBRequest):LongWord;
Description: Perform a standard (non hub specific) control request to the root hub


[Expand]
function DWCSchedulerStart(Host:PDWCUSBHost):LongWord;
Description: Initialize a bitmask and semaphore that keep track of the Free/Used status of the host channels and a queue in which to place submitted USB transfer requests, then start the USB request scheduler thread


[Expand]
function DWCSchedulerExecute(Host:PDWCUSBHost):PtrInt;
Description: USB request scheduler thread


[Expand]
function DWCCompletionExecute(Host:PDWCUSBHost):PtrInt;
Description: USB request completion thread


[Expand]
function DWCResubmitExecute(Request:PUSBRequest):PtrInt;
Description: USB request resubmit thread


[Expand]
procedure DWCInterruptHandler(Host:PDWCUSBHost);
Description: Interrupt handler for the DWCOTG controller


[Expand]
function DWCChannelInterrupt(Host:PDWCUSBHost; Channel:LongWord):LongWord;
Description: Handle a channel interrupt on the specified channel


[Expand]
function DWCChannelCompleted(Host:PDWCUSBHost; Request:PUSBRequest; Channel,Interrupts:LongWord):LongWord;
Description: Handle a channel interrupt where no error occurred


DWCOTG helper functions

[Expand]
function DWCDivRoundUp(Number,Denominator:LongWord):LongWord;
Description: To be documented


[Expand]
function DWCCalculateFrameInterval(Host:PDWCUSBHost):LongWord;
Description: Calculate the frame interval register value based on USB configuration and port speed


Return to Unit Reference