1 /* 2 * 3 * Copyright (C) 2010 Patrick Georgi 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifndef __OHCI_PRIVATE_H 30 #define __OHCI_PRIVATE_H 31 32 #include <usb/usb.h> 33 34 #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) 35 36 // FIXME: fake 37 typedef enum { CMD} reg; 38 39 enum HcRhDescriptorAReg { 40 NumberDownstreamPorts = 1 << 0, 41 PowerSwitchingMode = 1 << 8, 42 NoPowerSwitching = 1 << 9, 43 DeviceType = 1 << 10, 44 OverCurrentProtectionMode = 1 << 11, 45 NoOverCurrentProtection = 1 << 12, 46 PowerOnToPowerGoodTime = 1 << 24 47 }; 48 49 enum HcRhDescriptorAMask { 50 NumberDownstreamPortsMask = MASK(0, 8), 51 PowerOnToPowerGoodTimeMask = MASK(24, 8) 52 }; 53 54 enum HcRhDescriptorBReg { 55 DeviceRemovable = 1 << 0, 56 PortPowerControlMask = 1 << 16 57 }; 58 59 enum HcRhPortStatusRead { 60 CurrentConnectStatus = 1 << 0, 61 PortEnableStatus = 1 << 1, 62 PortSuspendStatus = 1 << 2, 63 PortOverCurrentIndicator = 1 << 3, 64 PortResetStatus = 1 << 4, 65 PortPowerStatus = 1 << 8, 66 LowSpeedDeviceAttached = 1 << 9, 67 ConnectStatusChange = 1 << 16, 68 PortEnableStatusChange = 1 << 17, 69 PortSuspendStatusChange = 1 << 18, 70 PortOverCurrentIndicatorChange = 1 << 19, 71 PortResetStatusChange = 1 << 20 72 }; 73 74 enum HcRhPortStatusSet { 75 ClearPortEnable = 1 << 0, 76 SetPortEnable = 1 << 1, 77 SetPortSuspend = 1 << 2, 78 ClearSuspendStatus = 1 << 3, 79 SetPortReset = 1 << 4, 80 SetPortPower = 1 << 8, 81 ClearPortPower = 1 << 9, 82 }; 83 84 enum HcRhStatusReg { 85 LocalPowerStatus = 1 << 0, 86 OverCurrentIndicator = 1 << 1, 87 DeviceRemoteWakeupEnable = 1 << 15, 88 LocalPowerStatusChange = 1 << 16, 89 OverCurrentIndicatorChange = 1 << 17, 90 ClearRemoteWakeupEnable = 1 << 31 91 }; 92 93 enum HcFmIntervalOffset { 94 FrameInterval = 1 << 0, 95 FSLargestDataPacket = 1 << 16, 96 FrameIntervalToggle = 1 << 31 97 }; 98 99 enum HcFmIntervalMask { 100 FrameIntervalMask = MASK(0, 14), 101 FSLargestDataPacketMask = MASK(16, 15), 102 FrameIntervalToggleMask = MASK(31, 1) 103 }; 104 105 enum HcControlReg { 106 ControlBulkServiceRatio = 1 << 0, 107 PeriodicListEnable = 1 << 2, 108 IsochronousEnable = 1 << 3, 109 ControlListEnable = 1 << 4, 110 BulkListEnable = 1 << 5, 111 HostControllerFunctionalState = 1 << 6, 112 InterruptRouting = 1 << 8, 113 RemoteWakeupConnected = 1 << 9, 114 RemoteWakeupEnable = 1 << 10 115 }; 116 117 enum HcControlMask { 118 ControlBulkServiceRatioMask = MASK(0, 2), 119 HostControllerFunctionalStateMask = MASK(6, 2) 120 }; 121 122 enum { 123 USBReset = 0*HostControllerFunctionalState, 124 USBResume = 1*HostControllerFunctionalState, 125 USBOperational = 2*HostControllerFunctionalState, 126 USBSuspend = 3*HostControllerFunctionalState 127 }; 128 129 enum HcCommandStatusReg { 130 HostControllerReset = 1 << 0, 131 ControlListFilled = 1 << 1, 132 BulkListFilled = 1 << 2, 133 OwnershipChangeRequest = 1 << 3, 134 SchedulingOverrunCount = 1 << 16 135 }; 136 137 enum HcCommandStatusMask { 138 SchedulingOverrunCountMask = MASK(16, 2) 139 }; 140 141 enum HcFmRemainingReg { 142 FrameRemaining = 1 << 0, 143 FrameRemainingToggle = 1 << 31 144 }; 145 146 enum HcInterruptStatusReg { 147 SchedulingOverrung = 1 << 0, 148 WritebackDoneHead = 1 << 1, 149 StartofFrame = 1 << 2, 150 ResumeDetected = 1 << 3, 151 UnrecoverableError = 1 << 4, 152 FrameNumberOverflow = 1 << 5, 153 RootHubStatusChange = 1 << 6, 154 OwnershipChange = 1 << 30 155 }; 156 157 typedef struct { 158 // Control and Status Partition 159 volatile u32 HcRevision; 160 volatile u32 HcControl; 161 volatile u32 HcCommandStatus; 162 volatile u32 HcInterruptStatus; 163 volatile u32 HcInterruptEnable; 164 volatile u32 HcInterruptDisable; 165 166 // Memory Pointer Partition 167 volatile u32 HcHCCA; 168 volatile u32 HcPeriodCurrentED; 169 volatile u32 HcControlHeadED; 170 volatile u32 HcControlCurrentED; 171 volatile u32 HcBulkHeadED; 172 volatile u32 HcBulkCurrentED; 173 volatile u32 HcDoneHead; 174 175 // Frame Counter Partition 176 volatile u32 HcFmInterval; 177 volatile u32 HcFmRemaining; 178 volatile u32 HcFmNumber; 179 volatile u32 HcPeriodicStart; 180 volatile u32 HcLSThreshold; 181 182 // Root Hub Partition 183 volatile u32 HcRhDescriptorA; 184 volatile u32 HcRhDescriptorB; 185 volatile u32 HcRhStatus; 186 /* all bits in HcRhPortStatus registers are R/WC, so 187 _DO NOT_ use |= to set the bits, 188 this clears the entire state */ 189 volatile u32 HcRhPortStatus[]; 190 } __packed opreg_t; 191 192 typedef struct { /* should be 256 bytes according to spec */ 193 u32 HccaInterruptTable[32]; 194 volatile u16 HccaFrameNumber; 195 volatile u16 HccaPad1; 196 volatile u32 HccaDoneHead; 197 u8 reserved[116]; /* pad according to spec */ 198 u8 what[4]; /* really pad to 256 as spec only covers 252 */ 199 } __packed hcca_t; 200 201 typedef volatile struct { 202 u32 config; 203 u32 tail_pointer; 204 u32 head_pointer; 205 u32 next_ed; 206 } __packed ed_t; 207 #define ED_HALTED 1 208 #define ED_TOGGLE 2 209 210 #define ED_FUNC_SHIFT 0 211 #define ED_FUNC_MASK MASK(0, 7) 212 #define ED_EP_SHIFT 7 213 #define ED_EP_MASK MASK(7, 4) 214 #define ED_DIR_SHIFT 11 215 #define ED_DIR_MASK MASK(11, 2) 216 #define ED_LOWSPEED (1 << 13) 217 #define ED_MPS_SHIFT 16 218 219 typedef volatile struct { 220 u32 config; 221 u32 current_buffer_pointer; 222 u32 next_td; 223 u32 buffer_end; 224 } __packed td_t; 225 /* 226 * Bits 0 through 17 of .config won't be interpreted by the host controller 227 * (HC) and, after processing the TD, the HC has to ensure those bits have 228 * the same state as before. So we are free to use those bits for our own 229 * purpose. 230 */ 231 #define TD_QUEUETYPE_SHIFT 0 232 #define TD_QUEUETYPE_MASK MASK(TD_QUEUETYPE_SHIFT, 2) 233 #define TD_QUEUETYPE_ASYNC (0 << TD_QUEUETYPE_SHIFT) 234 #define TD_QUEUETYPE_INTR (1 << TD_QUEUETYPE_SHIFT) 235 236 #define TD_DIRECTION_SHIFT 19 237 #define TD_DIRECTION_MASK MASK(TD_DIRECTION_SHIFT, 2) 238 #define TD_DIRECTION_SETUP (OHCI_SETUP << TD_DIRECTION_SHIFT) 239 #define TD_DIRECTION_IN (OHCI_IN << TD_DIRECTION_SHIFT) 240 #define TD_DIRECTION_OUT (OHCI_OUT << TD_DIRECTION_SHIFT) 241 #define TD_DELAY_INTERRUPT_SHIFT 21 242 #define TD_DELAY_INTERRUPT_MASK MASK(TD_DELAY_INTERRUPT_SHIFT, 3) 243 #define TD_DELAY_INTERRUPT_ZERO 0 244 #define TD_DELAY_INTERRUPT_NOINTR (7 << TD_DELAY_INTERRUPT_SHIFT) 245 #define TD_TOGGLE_DATA0 0 246 #define TD_TOGGLE_DATA1 (1 << 24) 247 #define TD_TOGGLE_FROM_ED 0 248 #define TD_TOGGLE_FROM_TD (1 << 25) 249 #define TD_CC_SHIFT 28 250 #define TD_CC_MASK MASK(TD_CC_SHIFT, 4) 251 #define TD_CC_NOERR 0 252 #define TD_CC_NOACCESS (14 << TD_CC_SHIFT) /* the lower of the two values, so "no access" can be tested with >= */ 253 254 #define OHCI_INST(controller) ((ohci_t*)((controller)->instance)) 255 256 typedef struct ohci { 257 opreg_t *opreg; 258 hcca_t *hcca; 259 usbdev_t *roothub; 260 ed_t *periodic_ed; 261 #define DMA_SIZE (64 * 1024) 262 void *dma_buffer; 263 } ohci_t; 264 265 typedef enum { OHCI_SETUP = 0, OHCI_OUT = 1, OHCI_IN = 2, OHCI_FROM_TD = 3 } ohci_pid_t; 266 267 #endif 268