3 * Copyright (C) 2010 Patrick Georgi
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #ifndef __OHCI_PRIVATE_H
30 #define __OHCI_PRIVATE_H
34 #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit))
37 typedef enum { CMD
} reg
;
39 enum HcRhDescriptorAReg
{
40 NumberDownstreamPorts
= 1 << 0,
41 PowerSwitchingMode
= 1 << 8,
42 NoPowerSwitching
= 1 << 9,
44 OverCurrentProtectionMode
= 1 << 11,
45 NoOverCurrentProtection
= 1 << 12,
46 PowerOnToPowerGoodTime
= 1 << 24
49 enum HcRhDescriptorAMask
{
50 NumberDownstreamPortsMask
= MASK(0, 8),
51 PowerOnToPowerGoodTimeMask
= MASK(24, 8)
54 enum HcRhDescriptorBReg
{
55 DeviceRemovable
= 1 << 0,
56 PortPowerControlMask
= 1 << 16
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
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,
85 LocalPowerStatus
= 1 << 0,
86 OverCurrentIndicator
= 1 << 1,
87 DeviceRemoteWakeupEnable
= 1 << 15,
88 LocalPowerStatusChange
= 1 << 16,
89 OverCurrentIndicatorChange
= 1 << 17,
90 ClearRemoteWakeupEnable
= 1 << 31
93 enum HcFmIntervalOffset
{
94 FrameInterval
= 1 << 0,
95 FSLargestDataPacket
= 1 << 16,
96 FrameIntervalToggle
= 1 << 31
99 enum HcFmIntervalMask
{
100 FrameIntervalMask
= MASK(0, 14),
101 FSLargestDataPacketMask
= MASK(16, 15),
102 FrameIntervalToggleMask
= MASK(31, 1)
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
118 ControlBulkServiceRatioMask
= MASK(0, 2),
119 HostControllerFunctionalStateMask
= MASK(6, 2)
123 USBReset
= 0*HostControllerFunctionalState
,
124 USBResume
= 1*HostControllerFunctionalState
,
125 USBOperational
= 2*HostControllerFunctionalState
,
126 USBSuspend
= 3*HostControllerFunctionalState
129 enum HcCommandStatusReg
{
130 HostControllerReset
= 1 << 0,
131 ControlListFilled
= 1 << 1,
132 BulkListFilled
= 1 << 2,
133 OwnershipChangeRequest
= 1 << 3,
134 SchedulingOverrunCount
= 1 << 16
137 enum HcCommandStatusMask
{
138 SchedulingOverrunCountMask
= MASK(16, 2)
141 enum HcFmRemainingReg
{
142 FrameRemaining
= 1 << 0,
143 FrameRemainingToggle
= 1 << 31
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
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
;
166 // Memory Pointer Partition
168 volatile u32 HcPeriodCurrentED
;
169 volatile u32 HcControlHeadED
;
170 volatile u32 HcControlCurrentED
;
171 volatile u32 HcBulkHeadED
;
172 volatile u32 HcBulkCurrentED
;
173 volatile u32 HcDoneHead
;
175 // Frame Counter Partition
176 volatile u32 HcFmInterval
;
177 volatile u32 HcFmRemaining
;
178 volatile u32 HcFmNumber
;
179 volatile u32 HcPeriodicStart
;
180 volatile u32 HcLSThreshold
;
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
[];
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 */
201 typedef volatile struct {
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
219 typedef volatile struct {
221 u32 current_buffer_pointer
;
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
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)
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 >= */
254 #define OHCI_INST(controller) ((ohci_t*)((controller)->instance))
256 typedef struct ohci
{
261 #define DMA_SIZE (64 * 1024)
265 typedef enum { OHCI_SETUP
= 0, OHCI_OUT
= 1, OHCI_IN
= 2, OHCI_FROM_TD
= 3 } ohci_pid_t
;