1 | /*
|
---|
2 | * Copyright (c) 2018 Ondrej Hlavaty
|
---|
3 | * All rights reserved.
|
---|
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 | *
|
---|
9 | * - Redistributions of source code must retain the above copyright
|
---|
10 | * notice, this list of conditions and the following disclaimer.
|
---|
11 | * - 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 | * - 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 ``AS IS'' AND ANY EXPRESS OR
|
---|
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
---|
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
---|
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
---|
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
---|
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
27 | */
|
---|
28 |
|
---|
29 | /** @addtogroup drvusbxhci
|
---|
30 | * @{
|
---|
31 | */
|
---|
32 | /** @file
|
---|
33 | * Memory-mapped register structures of the xHC.
|
---|
34 | *
|
---|
35 | * The main pr
|
---|
36 | */
|
---|
37 |
|
---|
38 | #ifndef XHCI_REGS_H
|
---|
39 | #define XHCI_REGS_H
|
---|
40 |
|
---|
41 | #include <macros.h>
|
---|
42 | #include <ddi.h>
|
---|
43 | #include "common.h"
|
---|
44 |
|
---|
45 | #define XHCI_PIO_CHANGE_UDELAY 5
|
---|
46 |
|
---|
47 | /*
|
---|
48 | * These four are the main macros to be used.
|
---|
49 | * Semantics is usual - READ reads value, WRITE changes value, SET sets
|
---|
50 | * selected bits, CLEAR clears selected bits to 0.
|
---|
51 | *
|
---|
52 | * The key thing here is the order of macro expansion, expanding the reg_spec
|
---|
53 | * argument as more arguments (comma delimited) for the inner macro.
|
---|
54 | */
|
---|
55 | #define XHCI_REG_RD(reg_set, reg_spec) XHCI_REG_RD_INNER(reg_set, reg_spec)
|
---|
56 | #define XHCI_REG_WR(reg_set, reg_spec, value) XHCI_REG_WR_INNER(reg_set, value, reg_spec)
|
---|
57 | #define XHCI_REG_SET(reg_set, reg_spec, value) XHCI_REG_SET_INNER(reg_set, value, reg_spec)
|
---|
58 | #define XHCI_REG_CLR(reg_set, reg_spec, value) XHCI_REG_CLR_INNER(reg_set, value, reg_spec)
|
---|
59 | #define XHCI_REG_MASK(reg_spec) XHCI_REG_MASK_INNER(reg_spec)
|
---|
60 | #define XHCI_REG_SHIFT(reg_spec) XHCI_REG_SHIFT_INNER(reg_spec)
|
---|
61 |
|
---|
62 | /*
|
---|
63 | * These take a pointer to the field, and selects the type-specific macro.
|
---|
64 | */
|
---|
65 | #define XHCI_REG_RD_INNER(reg_set, field, size, type, ...) \
|
---|
66 | XHCI_REG_RD_##type(&((reg_set)->field), size, ##__VA_ARGS__)
|
---|
67 |
|
---|
68 | #define XHCI_REG_WR_INNER(reg_set, value, field, size, type, ...) \
|
---|
69 | XHCI_REG_WR_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
|
---|
70 |
|
---|
71 | #define XHCI_REG_SET_INNER(reg_set, value, field, size, type, ...) \
|
---|
72 | XHCI_REG_SET_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
|
---|
73 |
|
---|
74 | #define XHCI_REG_CLR_INNER(reg_set, value, field, size, type, ...) \
|
---|
75 | XHCI_REG_CLR_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
|
---|
76 |
|
---|
77 | #define XHCI_REG_MASK_INNER(field, size, type, ...) \
|
---|
78 | XHCI_REG_MASK_##type(size, ##__VA_ARGS__)
|
---|
79 |
|
---|
80 | #define XHCI_REG_SHIFT_INNER(field, size, type, ...) \
|
---|
81 | XHCI_REG_SHIFT_##type(size, ##__VA_ARGS__)
|
---|
82 |
|
---|
83 | /*
|
---|
84 | * Field handling is the easiest. Just do it with whole field.
|
---|
85 | */
|
---|
86 | #define XHCI_REG_RD_FIELD(ptr, size) \
|
---|
87 | xhci2host(size, pio_read_##size((ptr)))
|
---|
88 | #define XHCI_REG_WR_FIELD(ptr, value, size) \
|
---|
89 | pio_write_##size((ptr), host2xhci(size, value))
|
---|
90 | #define XHCI_REG_SET_FIELD(ptr, value, size) \
|
---|
91 | pio_set_##size((ptr), host2xhci(size, value), XHCI_PIO_CHANGE_UDELAY);
|
---|
92 | #define XHCI_REG_CLR_FIELD(ptr, value, size) \
|
---|
93 | pio_clear_##size((ptr), host2xhci(size, value), XHCI_PIO_CHANGE_UDELAY);
|
---|
94 | #define XHCI_REG_MASK_FIELD(size) (~((uint##size##_t) 0))
|
---|
95 | #define XHCI_REG_SHIFT_FIELD(size) (0)
|
---|
96 |
|
---|
97 | /*
|
---|
98 | * Flags are just trivial case of ranges.
|
---|
99 | */
|
---|
100 | #define XHCI_REG_RD_FLAG(ptr, size, offset) \
|
---|
101 | XHCI_REG_RD_RANGE((ptr), size, (offset), (offset))
|
---|
102 | #define XHCI_REG_WR_FLAG(ptr, value, size, offset) \
|
---|
103 | XHCI_REG_WR_RANGE((ptr), (value), size, (offset), (offset))
|
---|
104 | #define XHCI_REG_SET_FLAG(ptr, value, size, offset) \
|
---|
105 | XHCI_REG_SET_RANGE((ptr), (value), size, (offset), (offset))
|
---|
106 | #define XHCI_REG_CLR_FLAG(ptr, value, size, offset) \
|
---|
107 | XHCI_REG_CLR_RANGE((ptr), (value), size, (offset), (offset))
|
---|
108 | #define XHCI_REG_MASK_FLAG(size, offset) BIT_V(uint##size##_t, offset)
|
---|
109 | #define XHCI_REG_SHIFT_FLAG(size, offset) (offset)
|
---|
110 |
|
---|
111 | /*
|
---|
112 | * Ranges are the most difficult. We need to play around with bitmasks.
|
---|
113 | */
|
---|
114 | #define XHCI_REG_RD_RANGE(ptr, size, hi, lo) \
|
---|
115 | BIT_RANGE_EXTRACT(uint##size##_t, (hi), (lo), XHCI_REG_RD_FIELD((ptr), size))
|
---|
116 |
|
---|
117 | #define XHCI_REG_WR_RANGE(ptr, value, size, hi, lo) \
|
---|
118 | pio_change_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, \
|
---|
119 | (hi), (lo), (value))), \
|
---|
120 | host2xhci(size, BIT_RANGE(uint##size##_t, (hi), (lo))), \
|
---|
121 | XHCI_PIO_CHANGE_UDELAY);
|
---|
122 |
|
---|
123 | #define XHCI_REG_SET_RANGE(ptr, value, size, hi, lo) \
|
---|
124 | pio_set_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, \
|
---|
125 | (hi), (lo), (value))), \
|
---|
126 | XHCI_PIO_CHANGE_UDELAY);
|
---|
127 |
|
---|
128 | #define XHCI_REG_CLR_RANGE(ptr, value, size, hi, lo) \
|
---|
129 | pio_clear_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, \
|
---|
130 | (hi), (lo), (value))), \
|
---|
131 | XHCI_PIO_CHANGE_UDELAY);
|
---|
132 |
|
---|
133 | #define XHCI_REG_MASK_RANGE(size, hi, lo) BIT_RANGE(uint##size##_t, hi, lo)
|
---|
134 | #define XHCI_REG_SHIFT_RANGE(size, hi, lo) (lo)
|
---|
135 |
|
---|
136 | /** HC capability registers: section 5.3 */
|
---|
137 | typedef const struct xhci_cap_regs {
|
---|
138 |
|
---|
139 | /* Size of this structure, offset for the operation registers */
|
---|
140 | const ioport8_t caplength;
|
---|
141 |
|
---|
142 | const PADD8;
|
---|
143 |
|
---|
144 | /* BCD of specification version */
|
---|
145 | const ioport16_t hciversion;
|
---|
146 |
|
---|
147 | /*
|
---|
148 | * 7:0 - MaxSlots
|
---|
149 | * 18:8 - MaxIntrs
|
---|
150 | * 31:24 - MaxPorts
|
---|
151 | */
|
---|
152 | const ioport32_t hcsparams1;
|
---|
153 |
|
---|
154 | /*
|
---|
155 | * 3:0 - IST
|
---|
156 | * 7:4 - ERST Max
|
---|
157 | * 25:21 - Max Scratchpad Bufs Hi
|
---|
158 | * 26 - SPR
|
---|
159 | * 31:27 - Max Scratchpad Bufs Lo
|
---|
160 | */
|
---|
161 | const ioport32_t hcsparams2;
|
---|
162 |
|
---|
163 | /*
|
---|
164 | * 7:0 - U1 Device Exit Latency
|
---|
165 | * 31:16 - U2 Device Exit Latency
|
---|
166 | */
|
---|
167 | const ioport32_t hcsparams3;
|
---|
168 |
|
---|
169 | /*
|
---|
170 | * 11 10 9 8 7 6 5 4 3 2 1 0
|
---|
171 | * 11:0 - CFC SEC SPC PAE NSS LTC C PIND PPC CSZ BNC AC64
|
---|
172 | * 15:12 - MaxPSASize
|
---|
173 | * 31:16 - xECP
|
---|
174 | */
|
---|
175 | const ioport32_t hccparams1;
|
---|
176 |
|
---|
177 | /*
|
---|
178 | * 31:2 - Doorbell Array Offset
|
---|
179 | */
|
---|
180 | const ioport32_t dboff;
|
---|
181 |
|
---|
182 | /*
|
---|
183 | * 31:5 - Runtime Register Space Offset
|
---|
184 | */
|
---|
185 | const ioport32_t rtsoff;
|
---|
186 |
|
---|
187 | /*
|
---|
188 | * 5 4 3 2 1 0
|
---|
189 | * 5:0 - Flags: CIC LEC CTC FSC CMC U3C
|
---|
190 | */
|
---|
191 | const ioport32_t hccparams2;
|
---|
192 |
|
---|
193 | // the rest to operational registers is reserved
|
---|
194 | } xhci_cap_regs_t;
|
---|
195 |
|
---|
196 | /*
|
---|
197 | * The register specifiers are to be used as the reg_spec argument.
|
---|
198 | *
|
---|
199 | * The values are field, bitsize, type, (type specific args)
|
---|
200 | * When the type is RANGE: hi, lo
|
---|
201 | */
|
---|
202 | #define XHCI_CAP_LENGTH caplength, 8, FIELD
|
---|
203 | #define XHCI_CAP_VERSION hciversion, 16, FIELD
|
---|
204 | #define XHCI_CAP_MAX_SLOTS hcsparams1, 32, RANGE, 7, 0
|
---|
205 | #define XHCI_CAP_MAX_INTRS hcsparams1, 32, RANGE, 18, 8
|
---|
206 | #define XHCI_CAP_MAX_PORTS hcsparams1, 32, RANGE, 31, 24
|
---|
207 | #define XHCI_CAP_IST hcsparams2, 32, RANGE, 3, 0
|
---|
208 | #define XHCI_CAP_ERST_MAX hcsparams2, 32, RANGE, 7, 4
|
---|
209 | #define XHCI_CAP_MAX_SPBUF_HI hcsparams2, 32, RANGE, 25, 21
|
---|
210 | #define XHCI_CAP_SPR hcsparams2, 32, FLAG, 26
|
---|
211 | #define XHCI_CAP_MAX_SPBUF_LO hcsparams2, 32, RANGE, 31, 27
|
---|
212 | #define XHCI_CAP_U1EL hcsparams3, 32, RANGE, 7, 0
|
---|
213 | #define XHCI_CAP_U2EL hcsparams3, 32, RANGE, 31, 16
|
---|
214 | #define XHCI_CAP_AC64 hccparams1, 32, FLAG, 0
|
---|
215 | #define XHCI_CAP_BNC hccparams1, 32, FLAG, 1
|
---|
216 | #define XHCI_CAP_CSZ hccparams1, 32, FLAG, 2
|
---|
217 | #define XHCI_CAP_PPC hccparams1, 32, FLAG, 3
|
---|
218 | #define XHCI_CAP_PIND hccparams1, 32, FLAG, 4
|
---|
219 | #define XHCI_CAP_C hccparams1, 32, FLAG, 5
|
---|
220 | #define XHCI_CAP_LTC hccparams1, 32, FLAG, 6
|
---|
221 | #define XHCI_CAP_NSS hccparams1, 32, FLAG, 7
|
---|
222 | #define XHCI_CAP_PAE hccparams1, 32, FLAG, 8
|
---|
223 | #define XHCI_CAP_SPC hccparams1, 32, FLAG, 9
|
---|
224 | #define XHCI_CAP_SEC hccparams1, 32, FLAG, 10
|
---|
225 | #define XHCI_CAP_CFC hccparams1, 32, FLAG, 11
|
---|
226 | #define XHCI_CAP_MAX_PSA_SIZE hccparams1, 32, RANGE, 15, 12
|
---|
227 | #define XHCI_CAP_XECP hccparams1, 32, RANGE, 31, 16
|
---|
228 | #define XHCI_CAP_DBOFF dboff, 32, FIELD
|
---|
229 | #define XHCI_CAP_RTSOFF rtsoff, 32, FIELD
|
---|
230 | #define XHCI_CAP_U3C hccparams2, 32, FLAG, 0
|
---|
231 | #define XHCI_CAP_CMC hccparams2, 32, FLAG, 1
|
---|
232 | #define XHCI_CAP_FSC hccparams2, 32, FLAG, 2
|
---|
233 | #define XHCI_CAP_CTC hccparams2, 32, FLAG, 3
|
---|
234 | #define XHCI_CAP_LEC hccparams2, 32, FLAG, 4
|
---|
235 | #define XHCI_CAP_CIC hccparams2, 32, FLAG, 5
|
---|
236 |
|
---|
237 | static inline unsigned xhci_get_max_spbuf(xhci_cap_regs_t *cap_regs) {
|
---|
238 | return XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_HI) << 5
|
---|
239 | | XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_LO);
|
---|
240 | }
|
---|
241 |
|
---|
242 | /**
|
---|
243 | * XHCI Port Register Set: section 5.4, table 32
|
---|
244 | */
|
---|
245 | typedef struct xhci_port_regs {
|
---|
246 | /*
|
---|
247 | * 4 3 2 1 0
|
---|
248 | * 4:0 - PR OCA Z PED CCS
|
---|
249 | * 8:5 - PLS
|
---|
250 | * 9 - PP
|
---|
251 | * 13:10 - Port Speed
|
---|
252 | * 15:14 - PIC
|
---|
253 | * 27 26 25 24 23 22 21 20 19 18 17 16
|
---|
254 | * 27:16 - WOE WDE WCE CAS CEC PLC PRC OCC WRC PEC CSC LWS
|
---|
255 | * 30 - DR
|
---|
256 | * 31 - WPR
|
---|
257 | */
|
---|
258 | ioport32_t portsc;
|
---|
259 |
|
---|
260 | /*
|
---|
261 | * Contents of this fields depends on the protocol supported by the port.
|
---|
262 | * USB3:
|
---|
263 | * 7:0 - U1 Timeout
|
---|
264 | * 15:8 - U2 Timeout
|
---|
265 | * 16 - Force Link PM Accept
|
---|
266 | * USB2:
|
---|
267 | * 2:0 - L1S
|
---|
268 | * 3 - RWE
|
---|
269 | * 7:4 - BESL
|
---|
270 | * 15:8 - L1 Device Slot
|
---|
271 | * 16 - HLE
|
---|
272 | * 31:28 - Test Mode
|
---|
273 | */
|
---|
274 | ioport32_t portpmsc;
|
---|
275 |
|
---|
276 | /*
|
---|
277 | * This field is valid only for USB3 ports.
|
---|
278 | * 15:0 - Link Error Count
|
---|
279 | * 19:16 - RLC
|
---|
280 | * 23:20 - TLC
|
---|
281 | */
|
---|
282 | ioport32_t portli;
|
---|
283 |
|
---|
284 | /*
|
---|
285 | * This field is valid only for USB2 ports.
|
---|
286 | * 1:0 - HIRDM
|
---|
287 | * 9:2 - L1 Timeout
|
---|
288 | * 13:10 - BESLD
|
---|
289 | */
|
---|
290 | ioport32_t porthlpmc;
|
---|
291 | } xhci_port_regs_t;
|
---|
292 |
|
---|
293 | #define XHCI_PORT_CCS portsc, 32, FLAG, 0
|
---|
294 | #define XHCI_PORT_PED portsc, 32, FLAG, 1
|
---|
295 | #define XHCI_PORT_OCA portsc, 32, FLAG, 3
|
---|
296 | #define XHCI_PORT_PR portsc, 32, FLAG, 4
|
---|
297 | #define XHCI_PORT_PLS portsc, 32, RANGE, 8, 5
|
---|
298 | #define XHCI_PORT_PP portsc, 32, FLAG, 9
|
---|
299 | #define XHCI_PORT_PS portsc, 32, RANGE, 13, 10
|
---|
300 | #define XHCI_PORT_PIC portsc, 32, RANGE, 15, 14
|
---|
301 | #define XHCI_PORT_LWS portsc, 32, FLAG, 16
|
---|
302 | #define XHCI_PORT_CSC portsc, 32, FLAG, 17
|
---|
303 | #define XHCI_PORT_PEC portsc, 32, FLAG, 18
|
---|
304 | #define XHCI_PORT_WRC portsc, 32, FLAG, 19
|
---|
305 | #define XHCI_PORT_OCC portsc, 32, FLAG, 20
|
---|
306 | #define XHCI_PORT_PRC portsc, 32, FLAG, 21
|
---|
307 | #define XHCI_PORT_PLC portsc, 32, FLAG, 22
|
---|
308 | #define XHCI_PORT_CEC portsc, 32, FLAG, 23
|
---|
309 | #define XHCI_PORT_CAS portsc, 32, FLAG, 24
|
---|
310 | #define XHCI_PORT_WCE portsc, 32, FLAG, 25
|
---|
311 | #define XHCI_PORT_WDE portsc, 32, FLAG, 26
|
---|
312 | #define XHCI_PORT_WOE portsc, 32, FLAG, 27
|
---|
313 | #define XHCI_PORT_DR portsc, 32, FLAG, 30
|
---|
314 | #define XHCI_PORT_WPR portsc, 32, FLAG, 31
|
---|
315 |
|
---|
316 | #define XHCI_PORT_USB3_U1TO portpmsc, 32, RANGE, 7, 0
|
---|
317 | #define XHCI_PORT_USB3_U2TO portpmsc, 32, RANGE, 15, 8
|
---|
318 | #define XHCI_PORT_USB3_FLPMA portpmsc, 32, FLAG, 16
|
---|
319 | #define XHCI_PORT_USB3_LEC portli, 32, RANGE, 15, 0
|
---|
320 | #define XHCI_PORT_USB3_RLC portli, 32, RANGE, 19, 16
|
---|
321 | #define XHCI_PORT_USB3_TLC portli, 32, RANGE, 23, 20
|
---|
322 |
|
---|
323 | #define XHCI_PORT_USB2_L1S portpmsc, 32, RANGE, 2, 0
|
---|
324 | #define XHCI_PORT_USB2_RWE portpmsc, 32, FLAG, 3
|
---|
325 | #define XHCI_PORT_USB2_BESL portpmsc, 32, RANGE, 7, 4
|
---|
326 | #define XHCI_PORT_USB2_L1DS portpmsc, 32, RANGE, 15, 8
|
---|
327 | #define XHCI_PORT_USB2_HLE portpmsc, 32, FLAG, 16
|
---|
328 | #define XHCI_PORT_USB2_TM portpmsc, 32, RANGE, 31, 28
|
---|
329 | #define XHCI_PORT_USB2_HIRDM porthlpmc, 32, RANGE, 1, 0
|
---|
330 | #define XHCI_PORT_USB2_L1TO porthlpmc, 32, RANGE, 9, 2
|
---|
331 | #define XHCI_PORT_USB2_BESLD porthlpmc, 32, RANGE, 13, 10
|
---|
332 |
|
---|
333 | /**
|
---|
334 | * XHCI Operational Registers: section 5.4
|
---|
335 | */
|
---|
336 | typedef struct xhci_op_regs {
|
---|
337 |
|
---|
338 | /*
|
---|
339 | * 3 2 1 0
|
---|
340 | * 3:0 - HSEE INTE HCRST R/S
|
---|
341 | *
|
---|
342 | * 11 10 9 8 7
|
---|
343 | * 11:7 - EU3S EWE CRS CSS LHCRST
|
---|
344 | * 13 - CME
|
---|
345 | */
|
---|
346 | ioport32_t usbcmd;
|
---|
347 |
|
---|
348 | /*
|
---|
349 | * 4 3 2 1 0
|
---|
350 | * 4:0 - PCD EINT HSE _ HCH
|
---|
351 | *
|
---|
352 | * 12 11 10 9 8
|
---|
353 | * 12:8 - HCE CNR SRE RSS SSS
|
---|
354 | */
|
---|
355 | ioport32_t usbsts;
|
---|
356 |
|
---|
357 | /*
|
---|
358 | * Bitmask of page sizes supported: 128M .. 4K
|
---|
359 | */
|
---|
360 | ioport32_t pagesize;
|
---|
361 |
|
---|
362 | PADD32[2];
|
---|
363 |
|
---|
364 | /*
|
---|
365 | * 15:0 - Notification enable
|
---|
366 | */
|
---|
367 | ioport32_t dnctrl;
|
---|
368 |
|
---|
369 | /* 3 2 1 0
|
---|
370 | * 3:0 - CRR CA CS RCS
|
---|
371 | * 64:6 - Command Ring Pointer
|
---|
372 | */
|
---|
373 | ioport64_t crcr;
|
---|
374 |
|
---|
375 | PADD32[4];
|
---|
376 |
|
---|
377 | ioport64_t dcbaap;
|
---|
378 |
|
---|
379 | /*
|
---|
380 | * 7:0 - MaxSlotsEn
|
---|
381 | * 8 - U3E
|
---|
382 | * 9 - CIE
|
---|
383 | */
|
---|
384 | ioport32_t config;
|
---|
385 |
|
---|
386 | /* Offset of portrs from op_regs addr is 0x400. */
|
---|
387 | PADD32[241];
|
---|
388 |
|
---|
389 | /*
|
---|
390 | * Individual ports register sets
|
---|
391 | */
|
---|
392 | xhci_port_regs_t portrs[256];
|
---|
393 | } xhci_op_regs_t;
|
---|
394 |
|
---|
395 | #define XHCI_OP_RS usbcmd, 32, FLAG, 0
|
---|
396 | #define XHCI_OP_HCRST usbcmd, 32, FLAG, 1
|
---|
397 | #define XHCI_OP_INTE usbcmd, 32, FLAG, 2
|
---|
398 | #define XHCI_OP_HSEE usbcmd, 32, FLAG, 3
|
---|
399 | #define XHCI_OP_LHCRST usbcmd, 32, FLAG, 7
|
---|
400 | #define XHCI_OP_CSS usbcmd, 32, FLAG, 8
|
---|
401 | #define XHCI_OP_CRS usbcmd, 32, FLAG, 9
|
---|
402 | #define XHCI_OP_EWE usbcmd, 32, FLAG, 10
|
---|
403 | #define XHCI_OP_EU3S usbcmd, 32, FLAG, 11
|
---|
404 | #define XHCI_OP_CME usbcmd, 32, FLAG, 13
|
---|
405 | #define XHCI_OP_HCH usbsts, 32, FLAG, 0
|
---|
406 | #define XHCI_OP_HSE usbsts, 32, FLAG, 2
|
---|
407 | #define XHCI_OP_EINT usbsts, 32, FLAG, 3
|
---|
408 | #define XHCI_OP_PCD usbsts, 32, FLAG, 4
|
---|
409 | #define XHCI_OP_SSS usbsts, 32, FLAG, 8
|
---|
410 | #define XHCI_OP_RSS usbsts, 32, FLAG, 9
|
---|
411 | #define XHCI_OP_SRE usbsts, 32, FLAG, 10
|
---|
412 | #define XHCI_OP_CNR usbsts, 32, FLAG, 11
|
---|
413 | #define XHCI_OP_HCE usbsts, 32, FLAG, 12
|
---|
414 | #define XHCI_OP_PAGESIZE pagesize, 32, FIELD
|
---|
415 | #define XHCI_OP_NOTIFICATION dnctrl, 32, RANGE, 15, 0
|
---|
416 | #define XHCI_OP_RCS crcr, 64, FLAG, 0
|
---|
417 | #define XHCI_OP_CS crcr, 64, FLAG, 1
|
---|
418 | #define XHCI_OP_CA crcr, 64, FLAG, 2
|
---|
419 | #define XHCI_OP_CRR crcr, 64, FLAG, 3
|
---|
420 | /*
|
---|
421 | * This shall be RANGE, 6, 0, but the value containing CR pointer and RCS flag
|
---|
422 | * must be written at once.
|
---|
423 | */
|
---|
424 | #define XHCI_OP_CRCR crcr, 64, FIELD
|
---|
425 | #define XHCI_OP_DCBAAP dcbaap, 64, FIELD
|
---|
426 | #define XHCI_OP_MAX_SLOTS_EN config, 32, RANGE, 7, 0
|
---|
427 | #define XHCI_OP_U3E config, 32, FLAG, 8
|
---|
428 | #define XHCI_OP_CIE config, 32, FLAG, 9
|
---|
429 |
|
---|
430 | /* Aggregating field to read & write whole status at once */
|
---|
431 | #define XHCI_OP_STATUS usbsts, 32, RANGE, 12, 0
|
---|
432 |
|
---|
433 | /* RW1C fields in usbsts */
|
---|
434 | #define XHCI_STATUS_ACK_MASK 0x41C
|
---|
435 |
|
---|
436 | /**
|
---|
437 | * Interrupter Register Set: section 5.5.2
|
---|
438 | */
|
---|
439 | typedef struct xhci_interrupter_regs {
|
---|
440 | /*
|
---|
441 | * 0 - Interrupt Pending
|
---|
442 | * 1 - Interrupt Enable
|
---|
443 | */
|
---|
444 | ioport32_t iman;
|
---|
445 |
|
---|
446 | /*
|
---|
447 | * 15:0 - Interrupt Moderation Interval
|
---|
448 | * 31:16 - Interrupt Moderation Counter
|
---|
449 | */
|
---|
450 | ioport32_t imod;
|
---|
451 |
|
---|
452 | ioport32_t erstsz;
|
---|
453 |
|
---|
454 | PADD32;
|
---|
455 |
|
---|
456 | ioport64_t erstba;
|
---|
457 |
|
---|
458 | /*
|
---|
459 | * 2:0 - Dequeue ERST Segment Index
|
---|
460 | * 3 - Event Handler Busy
|
---|
461 | * 63:4 - Event Ring Dequeue Pointer
|
---|
462 | */
|
---|
463 | ioport64_t erdp;
|
---|
464 | } xhci_interrupter_regs_t;
|
---|
465 |
|
---|
466 | #define XHCI_INTR_IP iman, 32, FLAG, 0
|
---|
467 | #define XHCI_INTR_IE iman, 32, FLAG, 1
|
---|
468 | #define XHCI_INTR_IMI imod, 32, RANGE, 15, 0
|
---|
469 | #define XHCI_INTR_IMC imod, 32, RANGE, 31, 16
|
---|
470 | #define XHCI_INTR_ERSTSZ erstsz, 32, FIELD
|
---|
471 | #define XHCI_INTR_ERSTBA erstba, 64, FIELD
|
---|
472 | #define XHCI_INTR_ERDP_ESI erdp, 64, RANGE, 2, 0
|
---|
473 | #define XHCI_INTR_ERDP_EHB erdp, 64, FLAG, 3
|
---|
474 | #define XHCI_INTR_ERDP erdp, 64, FIELD
|
---|
475 |
|
---|
476 | /**
|
---|
477 | * XHCI Runtime registers: section 5.5
|
---|
478 | */
|
---|
479 | typedef struct xhci_rt_regs {
|
---|
480 | ioport32_t mfindex;
|
---|
481 |
|
---|
482 | PADD32 [7];
|
---|
483 |
|
---|
484 | xhci_interrupter_regs_t ir [];
|
---|
485 | } xhci_rt_regs_t;
|
---|
486 |
|
---|
487 | #define XHCI_RT_MFINDEX mfindex, 32, RANGE, 13, 0
|
---|
488 | #define XHCI_MFINDEX_MAX (1 << 14)
|
---|
489 |
|
---|
490 | /**
|
---|
491 | * XHCI Doorbell Registers: section 5.6
|
---|
492 | *
|
---|
493 | * These registers are to be written as a whole field.
|
---|
494 | */
|
---|
495 | typedef ioport32_t xhci_doorbell_t;
|
---|
496 |
|
---|
497 | enum xhci_plt {
|
---|
498 | XHCI_PSI_PLT_SYMM,
|
---|
499 | XHCI_PSI_PLT_RSVD,
|
---|
500 | XHCI_PSI_PLT_RX,
|
---|
501 | XHCI_PSI_PLT_TX
|
---|
502 | };
|
---|
503 |
|
---|
504 | /**
|
---|
505 | * Protocol speed ID: section 7.2.1
|
---|
506 | */
|
---|
507 | typedef struct xhci_psi {
|
---|
508 | xhci_dword_t psi;
|
---|
509 | } xhci_psi_t;
|
---|
510 |
|
---|
511 | #define XHCI_PSI_PSIV psi, 32, RANGE, 3, 0
|
---|
512 | #define XHCI_PSI_PSIE psi, 32, RANGE, 5, 4
|
---|
513 | #define XHCI_PSI_PLT psi, 32, RANGE, 7, 6
|
---|
514 | #define XHCI_PSI_PFD psi, 32, FLAG, 8
|
---|
515 | #define XHCI_PSI_PSIM psi, 32, RANGE, 31, 16
|
---|
516 |
|
---|
517 | enum xhci_extcap_type {
|
---|
518 | XHCI_EC_RESERVED = 0,
|
---|
519 | XHCI_EC_USB_LEGACY,
|
---|
520 | XHCI_EC_SUPPORTED_PROTOCOL,
|
---|
521 | XHCI_EC_EXTENDED_POWER_MANAGEMENT,
|
---|
522 | XHCI_EC_IOV,
|
---|
523 | XHCI_EC_MSI,
|
---|
524 | XHCI_EC_LOCALMEM,
|
---|
525 | XHCI_EC_DEBUG = 10,
|
---|
526 | XHCI_EC_MSIX = 17,
|
---|
527 | XHCI_EC_MAX = 255
|
---|
528 | };
|
---|
529 |
|
---|
530 | /**
|
---|
531 | * xHCI Extended Capability: section 7
|
---|
532 | */
|
---|
533 | typedef struct xhci_extcap {
|
---|
534 | xhci_dword_t header;
|
---|
535 | xhci_dword_t cap_specific[];
|
---|
536 | } xhci_extcap_t;
|
---|
537 |
|
---|
538 | #define XHCI_EC_CAP_ID header, 32, RANGE, 7, 0
|
---|
539 | #define XHCI_EC_SIZE header, 32, RANGE, 15, 8
|
---|
540 |
|
---|
541 | /* Supported protocol */
|
---|
542 | #define XHCI_EC_SP_MINOR header, 32, RANGE, 23, 16
|
---|
543 | #define XHCI_EC_SP_MAJOR header, 32, RANGE, 31, 24
|
---|
544 | #define XHCI_EC_SP_NAME cap_specific[0], 32, FIELD
|
---|
545 | #define XHCI_EC_SP_CP_OFF cap_specific[1], 32, RANGE, 7, 0
|
---|
546 | #define XHCI_EC_SP_CP_COUNT cap_specific[1], 32, RANGE, 15, 8
|
---|
547 | #define XHCI_EC_SP_PSIC cap_specific[1], 32, RANGE, 31, 28
|
---|
548 | #define XHCI_EC_SP_SLOT_TYPE cap_specific[2], 32, RANGE, 4, 0
|
---|
549 |
|
---|
550 | typedef union {
|
---|
551 | char str [4];
|
---|
552 | uint32_t packed;
|
---|
553 | } xhci_sp_name_t;
|
---|
554 |
|
---|
555 | static const xhci_sp_name_t xhci_name_usb = {
|
---|
556 | .str = "USB "
|
---|
557 | };
|
---|
558 |
|
---|
559 | static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
|
---|
560 | {
|
---|
561 | unsigned dword_offset = XHCI_REG_RD(cur, XHCI_EC_SIZE);
|
---|
562 | if (!dword_offset)
|
---|
563 | return NULL;
|
---|
564 | return (xhci_extcap_t *) (((xhci_dword_t *) cur) + dword_offset);
|
---|
565 | }
|
---|
566 |
|
---|
567 | static inline xhci_psi_t *xhci_extcap_psi(const xhci_extcap_t *ec, unsigned psid)
|
---|
568 | {
|
---|
569 | assert(XHCI_REG_RD(ec, XHCI_EC_CAP_ID) == XHCI_EC_SUPPORTED_PROTOCOL);
|
---|
570 | assert(XHCI_REG_RD(ec, XHCI_EC_SP_PSIC) > psid);
|
---|
571 |
|
---|
572 | unsigned dword_offset = 4 + psid;
|
---|
573 | return (xhci_psi_t *) (((xhci_dword_t *) ec) + dword_offset);
|
---|
574 | }
|
---|
575 |
|
---|
576 | /**
|
---|
577 | * USB Legacy Support: section 7.1
|
---|
578 | *
|
---|
579 | * Legacy support have an exception from dword-access, because it needs to be
|
---|
580 | * byte-accessed.
|
---|
581 | */
|
---|
582 | typedef struct xhci_extcap_legsup {
|
---|
583 | ioport8_t cap_id;
|
---|
584 | ioport8_t size; /**< Next Capability Pointer */
|
---|
585 | ioport8_t sem_bios;
|
---|
586 | ioport8_t sem_os;
|
---|
587 |
|
---|
588 | /** USB Legacy Support Control/Status - RW for BIOS, RO for OS */
|
---|
589 | xhci_dword_t usblegctlsts;
|
---|
590 | } xhci_legsup_t;
|
---|
591 |
|
---|
592 | #define XHCI_LEGSUP_SEM_BIOS sem_bios, 8, FLAG, 0
|
---|
593 | #define XHCI_LEGSUP_SEM_OS sem_os, 8, FLAG, 0
|
---|
594 |
|
---|
595 | /* 4.22.1 BIOS may take up to 1 second to release the device */
|
---|
596 | #define XHCI_LEGSUP_BIOS_TIMEOUT_US 1000000
|
---|
597 | #define XHCI_LEGSUP_POLLING_DELAY_1MS 1000
|
---|
598 |
|
---|
599 | #endif
|
---|
600 | /**
|
---|
601 | * @}
|
---|
602 | */
|
---|