blob: f8d0217f5df798ceecee7d0fe07adb46bc45daf2 [file] [log] [blame]
Patrick Georgi6615ef32010-08-13 09:18:58 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2010 Patrick Georgi
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef __OHCI_PRIVATE_H
31#define __OHCI_PRIVATE_H
32
Patrick Georgi6615ef32010-08-13 09:18:58 +000033#include <usb/usb.h>
34
35#define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit))
36
37 // FIXME: fake
38 typedef enum { CMD} reg;
39
40 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020041 NumberDownstreamPorts = 1 << 0,
42 PowerSwitchingMode = 1 << 8,
43 NoPowerSwitching = 1 << 9,
44 DeviceType = 1 << 10,
45 OverCurrentProtectionMode = 1 << 11,
46 NoOverCurrentProtection = 1 << 12,
47 PowerOnToPowerGoodTime = 1 << 24
Patrick Georgi6615ef32010-08-13 09:18:58 +000048 } HcRhDescriptorAReg;
49
50 enum {
51 NumberDownstreamPortsMask = MASK(0, 8),
52 PowerOnToPowerGoodTimeMask = MASK(24, 8)
53 } HcRhDescriptorAMask;
54
55 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020056 DeviceRemovable = 1 << 0,
57 PortPowerControlMask = 1 << 16
Patrick Georgi6615ef32010-08-13 09:18:58 +000058 } HcRhDescriptorBReg;
59
60 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020061 CurrentConnectStatus = 1 << 0,
62 PortEnableStatus = 1 << 1,
63 PortSuspendStatus = 1 << 2,
64 PortOverCurrentIndicator = 1 << 3,
65 PortResetStatus = 1 << 4,
66 PortPowerStatus = 1 << 8,
67 LowSpeedDeviceAttached = 1 << 9,
68 ConnectStatusChange = 1 << 16,
69 PortEnableStatusChange = 1 << 17,
70 PortSuspendStatusChange = 1 << 18,
71 PortOverCurrentIndicatorChange = 1 << 19,
72 PortResetStatusChange = 1 << 20
Patrick Georgi6615ef32010-08-13 09:18:58 +000073 } HcRhPortStatusRead;
74 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020075 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,
Patrick Georgi6615ef32010-08-13 09:18:58 +000082 } HcRhPortStatusSet;
83
84 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020085 LocalPowerStatus = 1 << 0,
86 OverCurrentIndicator = 1 << 1,
87 DeviceRemoteWakeupEnable = 1 << 15,
88 LocalPowerStatusChange = 1 << 16,
89 OverCurrentIndicatorChange = 1 << 17,
90 ClearRemoteWakeupEnable = 1 << 31
Patrick Georgi6615ef32010-08-13 09:18:58 +000091 } HcRhStatusReg;
92
93 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +020094 FrameInterval = 1 << 0,
95 FSLargestDataPacket = 1 << 16,
96 FrameIntervalToggle = 1 << 31
Patrick Georgi6615ef32010-08-13 09:18:58 +000097 } HcFmIntervalOffset;
98 enum {
99 FrameIntervalMask = MASK(0, 14),
100 FSLargestDataPacketMask = MASK(16, 15),
101 FrameIntervalToggleMask = MASK(31, 1)
102 } HcFmIntervalMask;
103
104 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +0200105 ControlBulkServiceRatio = 1 << 0,
106 PeriodicListEnable = 1 << 2,
107 IsochronousEnable = 1 << 3,
108 ControlListEnable = 1 << 4,
109 BulkListEnable = 1 << 5,
110 HostControllerFunctionalState = 1 << 6,
111 InterruptRouting = 1 << 8,
112 RemoteWakeupConnected = 1 << 9,
113 RemoteWakeupEnable = 1 << 10
Patrick Georgi6615ef32010-08-13 09:18:58 +0000114 } HcControlReg;
115
116 enum {
117 ControlBulkServiceRatioMask = MASK(0, 2),
118 HostControllerFunctionalStateMask = MASK(6, 2)
119 } HcControlMask;
120
121 enum {
122 USBReset = 0*HostControllerFunctionalState,
123 USBResume = 1*HostControllerFunctionalState,
124 USBOperational = 2*HostControllerFunctionalState,
125 USBSuspend = 3*HostControllerFunctionalState
126 };
127
128 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +0200129 HostControllerReset = 1 << 0,
130 ControlListFilled = 1 << 1,
131 BulkListFilled = 1 << 2,
132 OwnershipChangeRequest = 1 << 3,
133 SchedulingOverrunCount = 1 << 16
Patrick Georgi6615ef32010-08-13 09:18:58 +0000134 } HcCommandStatusReg;
135
136 enum {
137 SchedulingOverrunCountMask = MASK(16, 2)
138 } HcCommandStatusMask;
139
140 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +0200141 FrameRemaining = 1 << 0,
142 FrameRemainingToggle = 1 << 31
Patrick Georgi6615ef32010-08-13 09:18:58 +0000143 } HcFmRemainingReg;
144
145 enum {
Elyes HAOUAS70083a12017-06-27 21:51:20 +0200146 SchedulingOverrung = 1 << 0,
147 WritebackDoneHead = 1 << 1,
148 StartofFrame = 1 << 2,
149 ResumeDetected = 1 << 3,
150 UnrecoverableError = 1 << 4,
151 FrameNumberOverflow = 1 << 5,
152 RootHubStatusChange = 1 << 6,
153 OwnershipChange = 1 << 30
Patrick Georgi6615ef32010-08-13 09:18:58 +0000154 } HcInterruptStatusReg;
155
156 typedef struct {
157 // Control and Status Partition
158 volatile u32 HcRevision;
159 volatile u32 HcControl;
160 volatile u32 HcCommandStatus;
161 volatile u32 HcInterruptStatus;
162 volatile u32 HcInterruptEnable;
163 volatile u32 HcInterruptDisable;
164
165 // Memory Pointer Partition
166 volatile u32 HcHCCA;
167 volatile u32 HcPeriodCurrentED;
168 volatile u32 HcControlHeadED;
169 volatile u32 HcControlCurrentED;
170 volatile u32 HcBulkHeadED;
171 volatile u32 HcBulkCurrentED;
172 volatile u32 HcDoneHead;
173
174 // Frame Counter Partition
175 volatile u32 HcFmInterval;
176 volatile u32 HcFmRemaining;
177 volatile u32 HcFmNumber;
178 volatile u32 HcPeriodicStart;
179 volatile u32 HcLSThreshold;
180
181 // Root Hub Partition
182 volatile u32 HcRhDescriptorA;
183 volatile u32 HcRhDescriptorB;
184 volatile u32 HcRhStatus;
185 /* all bits in HcRhPortStatus registers are R/WC, so
186 _DO NOT_ use |= to set the bits,
187 this clears the entire state */
188 volatile u32 HcRhPortStatus[];
Stefan Reinauer6a001132017-07-13 02:20:27 +0200189 } __packed opreg_t;
Patrick Georgi6615ef32010-08-13 09:18:58 +0000190
Nico Huber542fe852012-06-20 11:37:17 +0200191 typedef struct { /* should be 256 bytes according to spec */
Patrick Georgi6615ef32010-08-13 09:18:58 +0000192 u32 HccaInterruptTable[32];
Nico Huber9951ade2012-06-20 10:08:06 +0200193 volatile u16 HccaFrameNumber;
194 volatile u16 HccaPad1;
195 volatile u32 HccaDoneHead;
Nico Huber542fe852012-06-20 11:37:17 +0200196 u8 reserved[116]; /* pad according to spec */
197 u8 what[4]; /* really pad to 256 as spec only covers 252 */
Stefan Reinauer6a001132017-07-13 02:20:27 +0200198 } __packed hcca_t;
Patrick Georgi6615ef32010-08-13 09:18:58 +0000199
Patrick Georgi6615ef32010-08-13 09:18:58 +0000200 typedef volatile struct {
Patrick Georgic4348d02011-11-24 09:12:11 +0100201 u32 config;
Patrick Georgi6615ef32010-08-13 09:18:58 +0000202 u32 tail_pointer;
Patrick Georgic4348d02011-11-24 09:12:11 +0100203 u32 head_pointer;
Patrick Georgi6615ef32010-08-13 09:18:58 +0000204 u32 next_ed;
Stefan Reinauer6a001132017-07-13 02:20:27 +0200205 } __packed ed_t;
Patrick Georgic4348d02011-11-24 09:12:11 +0100206#define ED_HALTED 1
207#define ED_TOGGLE 2
208
209#define ED_FUNC_SHIFT 0
Nico Huberac8d5502012-06-13 15:49:09 +0200210#define ED_FUNC_MASK MASK(0, 7)
Patrick Georgic4348d02011-11-24 09:12:11 +0100211#define ED_EP_SHIFT 7
Nico Huberac8d5502012-06-13 15:49:09 +0200212#define ED_EP_MASK MASK(7, 4)
Patrick Georgic4348d02011-11-24 09:12:11 +0100213#define ED_DIR_SHIFT 11
Nico Huberac8d5502012-06-13 15:49:09 +0200214#define ED_DIR_MASK MASK(11, 2)
Patrick Georgic4348d02011-11-24 09:12:11 +0100215#define ED_LOWSPEED (1 << 13)
216#define ED_MPS_SHIFT 16
Patrick Georgi6615ef32010-08-13 09:18:58 +0000217
218 typedef volatile struct {
Patrick Georgic4348d02011-11-24 09:12:11 +0100219 u32 config;
Patrick Georgi6615ef32010-08-13 09:18:58 +0000220 u32 current_buffer_pointer;
221 u32 next_td;
222 u32 buffer_end;
Stefan Reinauer6a001132017-07-13 02:20:27 +0200223 } __packed td_t;
Nico Huber9951ade2012-06-20 10:08:06 +0200224/*
225 * Bits 0 through 17 of .config won't be interpreted by the host controller
226 * (HC) and, after processing the TD, the HC has to ensure those bits have
227 * the same state as before. So we are free to use those bits for our own
228 * purpose.
229 */
230#define TD_QUEUETYPE_SHIFT 0
231#define TD_QUEUETYPE_MASK MASK(TD_QUEUETYPE_SHIFT, 2)
232#define TD_QUEUETYPE_ASYNC (0 << TD_QUEUETYPE_SHIFT)
Nico Huber274c63e2012-06-20 14:58:21 +0200233#define TD_QUEUETYPE_INTR (1 << TD_QUEUETYPE_SHIFT)
Nico Huber9951ade2012-06-20 10:08:06 +0200234
Patrick Georgic4348d02011-11-24 09:12:11 +0100235#define TD_DIRECTION_SHIFT 19
Nico Huberac8d5502012-06-13 15:49:09 +0200236#define TD_DIRECTION_MASK MASK(TD_DIRECTION_SHIFT, 2)
Elyes HAOUASb09822c2017-06-26 21:34:13 +0200237#define TD_DIRECTION_SETUP (OHCI_SETUP << TD_DIRECTION_SHIFT)
238#define TD_DIRECTION_IN (OHCI_IN << TD_DIRECTION_SHIFT)
Elyes HAOUAS03f25362017-07-03 21:20:27 +0200239#define TD_DIRECTION_OUT (OHCI_OUT << TD_DIRECTION_SHIFT)
Nico Huber9951ade2012-06-20 10:08:06 +0200240#define TD_DELAY_INTERRUPT_SHIFT 21
241#define TD_DELAY_INTERRUPT_MASK MASK(TD_DELAY_INTERRUPT_SHIFT, 3)
242#define TD_DELAY_INTERRUPT_ZERO 0
243#define TD_DELAY_INTERRUPT_NOINTR (7 << TD_DELAY_INTERRUPT_SHIFT)
Patrick Georgic4348d02011-11-24 09:12:11 +0100244#define TD_TOGGLE_DATA0 0
245#define TD_TOGGLE_DATA1 (1 << 24)
246#define TD_TOGGLE_FROM_ED 0
247#define TD_TOGGLE_FROM_TD (1 << 25)
248#define TD_CC_SHIFT 28
Nico Huberac8d5502012-06-13 15:49:09 +0200249#define TD_CC_MASK MASK(TD_CC_SHIFT, 4)
Patrick Georgic4348d02011-11-24 09:12:11 +0100250#define TD_CC_NOERR 0
251#define TD_CC_NOACCESS (14 << TD_CC_SHIFT) /* the lower of the two values, so "no access" can be tested with >= */
Patrick Georgi6615ef32010-08-13 09:18:58 +0000252
253#define OHCI_INST(controller) ((ohci_t*)((controller)->instance))
254
Nico Huber542fe852012-06-20 11:37:17 +0200255 typedef struct ohci {
256 opreg_t *opreg;
257 hcca_t *hcca;
258 usbdev_t *roothub;
259 ed_t *periodic_ed;
Julius Werner3b9795b2014-04-08 13:34:11 -0700260#define DMA_SIZE (64 * 1024)
261 void *dma_buffer;
Nico Huber542fe852012-06-20 11:37:17 +0200262 } ohci_t;
263
264 typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t;
265
Patrick Georgi6615ef32010-08-13 09:18:58 +0000266#endif