1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use crate::register_space::Register;
6 use crate::register_space::RegisterSpace;
7
8 /// Max interrupter number.
9 pub const MAX_INTERRUPTER: u8 = 1;
10 /// For port configuration, see register HCSPARAMS1, spcap1.3 and spcap2.3.
11 pub const MAX_SLOTS: u8 = 16;
12
13 /// Usb 2 ports start from port number 0.
14 pub const USB2_PORTS_START: u8 = 0;
15 /// Last usb 2 ports is 7.
16 pub const USB2_PORTS_END: u8 = 8;
17 /// Usb 3 ports start from port number 8.
18 pub const USB3_PORTS_START: u8 = 8;
19 /// Last usb 3 port is 15.
20 pub const USB3_PORTS_END: u8 = 16;
21
22 /// Max port number. Review the following before changing this:
23 /// HCSPARAMS1, portsc, spcap1.3 and spcap2.3.
24 pub const MAX_PORTS: u8 = USB3_PORTS_END;
25
26 /// Cap register length.
27 pub const XHCI_CAPLENGTH: u8 = 0x20;
28 /// Offset for doorbell register.
29 pub const XHCI_DBOFF: u32 = 0x00002000;
30 /// Offset for RTs.
31 pub const XHCI_RTSOFF: u32 = 0x00003000;
32
33 /// Bitmask for the usbcmd register, see spec 5.4.1.
34 pub const USB_CMD_RUNSTOP: u32 = 1u32 << 0;
35 /// Bitmask for the usbcmd register, see spec 5.4.1.
36 pub const USB_CMD_RESET: u32 = 1u32 << 1;
37 /// Bitmask for the usbcmd register, see spec 5.4.1.
38 pub const USB_CMD_INTERRUPTER_ENABLE: u32 = 1u32 << 2;
39
40 /// Bitmask for the usbsts register, see spec 5.4.2.
41 pub const USB_STS_HALTED: u32 = 1u32 << 0;
42 /// Bitmask for the usbsts register, see spec 5.4.2.
43 pub const USB_STS_EVENT_INTERRUPT: u32 = 1u32 << 3;
44 /// Bitmask for the usbsts register, see spec 5.4.2.
45 pub const USB_STS_PORT_CHANGE_DETECT: u32 = 1u32 << 4;
46 /// Bitmask for the usbsts register, see spec 5.4.2.
47 pub const USB_STS_CONTROLLER_NOT_READY: u32 = 1u32 << 11;
48 /// Bitmask for the usbsts register, see spec 5.4.2.
49 pub const USB_STS_SET_TO_CLEAR_MASK: u32 = 0x0000041C;
50
51 /// Bitmask for the crcr register, see spec 5.4.5.
52 pub const CRCR_RING_CYCLE_STATE: u64 = 1u64 << 0;
53 /// Bitmask for the crcr register, see spec 5.4.5.
54 pub const CRCR_COMMAND_STOP: u64 = 1u64 << 1;
55 /// Bitmask for the crcr register, see spec 5.4.5.
56 pub const CRCR_COMMAND_ABORT: u64 = 1u64 << 2;
57 /// Bitmask for the crcr register, see spec 5.4.5.
58 pub const CRCR_COMMAND_RING_RUNNING: u64 = 1u64 << 3;
59 /// Bitmask for the crcr register, see spec 5.4.5.
60 pub const CRCR_COMMAND_RING_POINTER: u64 = 0xFFFFFFFFFFFFFFC0;
61
62 /// Bitmask for portsc register, see spec 5.4.8.
63 pub const PORTSC_CURRENT_CONNECT_STATUS: u32 = 1u32 << 0;
64 /// Bitmask for portsc register, see spec 5.4.8.
65 pub const PORTSC_PORT_ENABLED: u32 = 1u32 << 1;
66 /// Bitmask for portsc register, see spec 5.4.8.
67 pub const PORTSC_PORT_RESET: u32 = 1u32 << 4;
68 /// Bitmask for portsc register, see spec 5.4.8.
69 pub const PORTSC_PORT_LINK_STATE_MASK: u32 = 0x000001E0;
70 /// Bitmask for portsc register, see spec 5.4.8.
71 pub const PORTSC_PORT_POWER: u32 = 1u32 << 9;
72 /// Bitmask for portsc register, see spec 5.4.8.
73 pub const PORTSC_PORT_SPEED_MASK: u32 = 0x00003C00;
74 /// Bitmask for portsc register, see spec 5.4.8.
75 pub const PORTSC_PORT_SPEED_SHIFT: u32 = 10;
76 /// Bitmask for portsc register, see spec 5.4.8.
77 pub const PORTSC_CONNECT_STATUS_CHANGE: u32 = 1u32 << 17;
78 /// Bitmask for portsc register, see spec 5.4.8.
79 pub const PORTSC_PORT_ENABLED_DISABLED_CHANGE: u32 = 1u32 << 18;
80 /// Bitmask for portsc register, see spec 5.4.8.
81 pub const PORTSC_PORT_RESET_CHANGE: u32 = 1u32 << 21;
82 /// Bitmask for portsc register, see spec 5.4.8.
83 pub const PORTSC_WARM_PORT_RESET: u32 = 1u32 << 31;
84 /// Bitmask for portsc register, see spec 5.4.8.
85 pub const PORTSC_SET_TO_CLEAR_MASK: u32 = 0x00FE0002;
86
87 /// Bitmask for iman registers, see spec 5.5.2.1.
88 pub const IMAN_INTERRUPT_PENDING: u32 = 1u32 << 0;
89 /// Bitmask for iman registers, see spec 5.5.2.1.
90 pub const IMAN_INTERRUPT_ENABLE: u32 = 1u32 << 1;
91 /// Bitmask for iman registers, see spec 5.5.2.1.
92 pub const IMAN_SET_TO_CLEAR_MASK: u32 = 0x00000001;
93
94 /// Bitmask for imod registers, see spec 5.5.2.2.
95 pub const IMOD_INTERRUPT_MODERATION_INTERVAL: u32 = 0xFFFF;
96 /// Bitmask for imod registers, see spec 5.5.2.2.
97 pub const IMOD_INTERRUPT_MODERATION_COUNTER_OFFSET: u8 = 16;
98
99 /// Bitmask for erstsz registers, see 5.5.2.3.
100 pub const ERSTSZ_SEGMENT_TABLE_SIZE: u32 = 0xFFFF;
101
102 /// Bitmask for erstba registers, see 5.5.2.3.
103 pub const ERSTBA_SEGMENT_TABLE_BASE_ADDRESS: u64 = 0xFFFFFFFFFFFFFFC0;
104
105 /// Bitmask for erdp registers, see 5.5.2.3.
106 pub const ERDP_EVENT_HANDLER_BUSY: u64 = 1u64 << 3;
107 /// Bitmask for erdp registers, see 5.5.2.3.
108 pub const ERDP_EVENT_RING_DEQUEUE_POINTER: u64 = 0xFFFFFFFFFFFFFFF0;
109 /// Bitmask for erdp registers, see 5.5.2.3.
110 pub const ERDP_SET_TO_CLEAR_MASK: u64 = 0x0000000000000008;
111
112 /// Bitmask for doorbell registers.
113 pub const DOORBELL_TARGET: u32 = 0xFF;
114 /// Offset of stream id.
115 pub const DOORBELL_STREAM_ID_OFFSET: u32 = 16;
116
117 /// Bitmask for structural parameter registers.
118 pub const HCSPARAMS1_MAX_INTERRUPTERS_MASK: u32 = 0x7FF00;
119 /// Offset of max interrupters.
120 pub const HCSPARAMS1_MAX_INTERRUPTERS_OFFSET: u32 = 8;
121 /// Mask to get max slots.
122 pub const HCSPARAMS1_MAX_SLOTS_MASK: u32 = 0xFF;
123
124 /// Bitmask for extended capabilities registers.
125 pub const SPCAP_PORT_COUNT_MASK: u32 = 0xFF00;
126 /// Offset of port count.
127 pub const SPCAP_PORT_COUNT_OFFSET: u32 = 8;
128
129 /// Bitmask for hccparams1 register, see spec 5.3.6.
130 pub const HCCPARAMS1_MAX_PSA_SIZE_OFFSET: u32 = 12;
131 /// Maximum primary stream array size, support up to 16 (2^(MAX_PSA_SIZE+1)) streams
132 pub const MAX_PSA_SIZE: u32 = 3;
133
134 /// Helper function for validating slot_id.
valid_slot_id(slot_id: u8) -> bool135 pub fn valid_slot_id(slot_id: u8) -> bool {
136 // slot id count from 1.
137 slot_id > 0 && slot_id <= MAX_SLOTS
138 }
139
140 /// Helper function for validating max_pstreams.
valid_max_pstreams(max_pstreams: u8) -> bool141 pub fn valid_max_pstreams(max_pstreams: u8) -> bool {
142 max_pstreams <= MAX_PSA_SIZE as u8
143 }
144
145 /// Helper function for validating stream_id. (assuming Linear Stream Array)
valid_stream_id(stream_id: u16) -> bool146 pub fn valid_stream_id(stream_id: u16) -> bool {
147 // stream id 0 is reserved
148 stream_id > 0 && stream_id < (1 << (MAX_PSA_SIZE + 1))
149 }
150
151 /// XhciRegs hold all xhci registers.
152 pub struct XhciRegs {
153 pub usbcmd: Register<u32>,
154 pub usbsts: Register<u32>,
155 pub dnctrl: Register<u32>,
156 pub crcr: Register<u64>,
157 pub dcbaap: Register<u64>,
158 pub config: Register<u64>,
159 pub portsc: Vec<Register<u32>>,
160 pub doorbells: Vec<Register<u32>>,
161 pub iman: Register<u32>,
162 pub imod: Register<u32>,
163 pub erstsz: Register<u32>,
164 pub erstba: Register<u64>,
165 pub erdp: Register<u64>,
166 }
167
168 /// This function returns mmio space definition for xhci. See Xhci spec chapter 5
169 /// for details.
init_xhci_mmio_space_and_regs() -> (RegisterSpace, XhciRegs)170 pub fn init_xhci_mmio_space_and_regs() -> (RegisterSpace, XhciRegs) {
171 let mut mmio = RegisterSpace::new();
172
173 /* Host Controller Capability Registers */
174 mmio.add_register(
175 // CAPLENGTH
176 static_register!(
177 ty: u8,
178 offset: 0x00,
179 value: XHCI_CAPLENGTH, // Operation register start at offset 0x20
180 ),
181 );
182 mmio.add_register(
183 // HCIVERSION
184 static_register!(
185 ty: u16,
186 offset: 0x02,
187 value: 0x0110,// Revision 1.1
188 ),
189 );
190 mmio.add_register(
191 // HCSPARAMS1
192 static_register!(
193 ty: u32,
194 offset: 0x04,
195 value: 0x10000110, // max_slots = 16, max_interrupters = 1, max_ports = 16
196 ),
197 );
198
199 mmio.add_register(
200 // HCSPARAMS2
201 static_register!(
202 ty: u32,
203 offset: 0x08,
204 // Maximum number of event ring segment table entries = 32k
205 // No scratchpad buffers.
206 value: 0xf0,
207 ),
208 );
209
210 mmio.add_register(
211 // HCSPARAM3
212 static_register!(
213 ty: u32,
214 offset: 0x0c,
215
216 // Exit latencies for U1 (standby with fast exit) and U2 (standby with
217 // slower exit) power states. We use the max values:
218 // - U1 to U0: < 10 us
219 // - U2 to U1: < 2047 us
220 value: 0x07FF000A,
221 ),
222 );
223
224 mmio.add_register(
225 // HCCPARAMS1
226 static_register!(
227 ty: u32,
228 offset: 0x10,
229 // Supports 64 bit addressing
230 // Max primary stream array size = 3 (support up to 16 streams).
231 // Extended capabilities pointer = 0xC000 offset from base.
232 value: 0x30000501 | (MAX_PSA_SIZE << HCCPARAMS1_MAX_PSA_SIZE_OFFSET),
233 ),
234 );
235 mmio.add_register(
236 // DBOFF
237 static_register!(
238 ty: u32,
239 offset: 0x14,
240 value: XHCI_DBOFF, // Doorbell array offset 0x2000 from base.
241 ),
242 );
243
244 mmio.add_register(
245 // RTSOFF
246 static_register!(
247 ty: u32,
248 offset: 0x18,
249 value: XHCI_RTSOFF, // Runtime registers offset 0x3000 from base.
250 ),
251 );
252
253 mmio.add_register(
254 // HCCPARAMS2
255 static_register!(
256 ty: u32,
257 offset: 0x1c,
258 value: 0,
259 ),
260 );
261 /* End of Host Controller Capability Registers */
262
263 /* Host Controller Operational Registers */
264 let usbcmd = register!(
265 name: "usbcmd",
266 ty: u32,
267 offset: 0x20,
268 reset_value: 0,
269 guest_writeable_mask: 0x00002F0F,
270 guest_write_1_to_clear_mask: 0,
271 );
272 mmio.add_register(usbcmd.clone());
273
274 let usbsts = register!(
275 name: "usbsts",
276 ty: u32,
277 offset: 0x24,
278 reset_value: 0x00000001,
279 guest_writeable_mask: 0x0000041C,
280 guest_write_1_to_clear_mask: 0x0000041C,
281 );
282 mmio.add_register(usbsts.clone());
283
284 mmio.add_register(
285 // Pagesize
286 static_register!(
287 ty: u32,
288 offset: 0x28,
289 value: 0x00000001,
290 ),
291 );
292
293 let dnctrl = register!(
294 name: "dnctrl",
295 ty: u32,
296 offset: 0x34,
297 reset_value: 0,
298 guest_writeable_mask: 0x0000FFFF,
299 guest_write_1_to_clear_mask: 0,
300 );
301 mmio.add_register(dnctrl.clone());
302
303 let crcr = register!(
304 name: "crcr",
305 ty: u64,
306 offset: 0x38,
307 reset_value: 9,
308 guest_writeable_mask: 0xFFFFFFFFFFFFFFC7,
309 guest_write_1_to_clear_mask: 0,
310 );
311 mmio.add_register(crcr.clone());
312
313 let dcbaap = register!(
314 name: "dcbaap",
315 ty: u64,
316 offset: 0x50,
317 reset_value: 0x0,
318 guest_writeable_mask: 0xFFFFFFFFFFFFFFC0,
319 guest_write_1_to_clear_mask: 0,
320 );
321 mmio.add_register(dcbaap.clone());
322
323 let config = register!(
324 name: "config",
325 ty: u64,
326 offset: 0x58,
327 reset_value: 0,
328 guest_writeable_mask: 0x0000003F,
329 guest_write_1_to_clear_mask: 0,
330 );
331 mmio.add_register(config.clone());
332
333 let portsc = register_array!(
334 name: "portsc",
335 ty: u32,
336 cnt: MAX_PORTS,
337 base_offset: 0x420,
338 stride: 16,
339 reset_value: 0x000002A0,
340 guest_writeable_mask: 0x8EFFC3F2,
341 guest_write_1_to_clear_mask: 0x00FE0002,);
342 mmio.add_register_array(&portsc);
343
344 // Portpmsc.
345 mmio.add_register_array(®ister_array!(
346 name: "portpmsc",
347 ty: u32,
348 cnt: MAX_PORTS,
349 base_offset: 0x424,
350 stride: 16,
351 reset_value: 0,
352 guest_writeable_mask: 0x0001FFFF,
353 guest_write_1_to_clear_mask: 0,));
354
355 // Portli
356 mmio.add_register_array(®ister_array!(
357 name: "portli",
358 ty: u32,
359 cnt: MAX_PORTS,
360 base_offset: 0x428,
361 stride: 16,
362 reset_value: 0,
363 guest_writeable_mask: 0,
364 guest_write_1_to_clear_mask: 0,));
365
366 // Porthlpmc
367 mmio.add_register_array(®ister_array!(
368 name: "porthlpmc",
369 ty: u32,
370 cnt: MAX_PORTS,
371 base_offset: 0x42c,
372 stride: 16,
373 reset_value: 0,
374 guest_writeable_mask: 0x00003FFF,
375 guest_write_1_to_clear_mask: 0,));
376
377 let doorbells = register_array!(
378 name: "doorbell",
379 ty: u32,
380 cnt: MAX_SLOTS + 1, // Must be equal to max_slots + 1
381 base_offset: 0x2000,
382 stride: 4,
383 reset_value: 0,
384 guest_writeable_mask: 0xFFFF00FF,
385 guest_write_1_to_clear_mask: 0,);
386 mmio.add_register_array(&doorbells);
387
388 /* Runtime Registers */
389
390 mmio.add_register(
391 // mfindex
392 static_register!(
393 ty: u32,
394 offset: 0x3000,
395 value: 0, // 4 ports starting at port 5
396 ),
397 );
398
399 /* Reg Array for interrupters */
400 // Although the following should be register arrays, we only have one interrupter.
401 let iman = register!(
402 name: "iman",
403 ty: u32,
404 offset: 0x3020,
405 reset_value: 0,
406 guest_writeable_mask: 0x00000003,
407 guest_write_1_to_clear_mask: 0x00000001,);
408 mmio.add_register(iman.clone());
409
410 let imod = register!(
411 name: "imod",
412 ty: u32,
413 offset: 0x3024,
414 reset_value: 0x00000FA0,
415 guest_writeable_mask: 0xFFFFFFFF,
416 guest_write_1_to_clear_mask: 0,);
417 mmio.add_register(imod.clone());
418
419 let erstsz = register!(
420 name: "erstsz",
421 ty: u32,
422 offset: 0x3028,
423 reset_value: 0,
424 guest_writeable_mask: 0x0000FFFF,
425 guest_write_1_to_clear_mask: 0,);
426 mmio.add_register(erstsz.clone());
427
428 let erstba = register!(
429 name: "erstba",
430 ty: u64,
431 offset: 0x3030,
432 reset_value: 0,
433 guest_writeable_mask: 0xFFFFFFFFFFFFFFC0,
434 guest_write_1_to_clear_mask: 0,);
435 mmio.add_register(erstba.clone());
436
437 let erdp = register!(
438 name: "erdp",
439 ty: u64,
440 offset: 0x3038,
441 reset_value: 0,
442 guest_writeable_mask: 0xFFFFFFFFFFFFFFFF,
443 guest_write_1_to_clear_mask: 0x0000000000000008,);
444 mmio.add_register(erdp.clone());
445
446 /* End of Runtime Registers */
447
448 let xhci_regs = XhciRegs {
449 usbcmd,
450 usbsts,
451 dnctrl,
452 crcr,
453 dcbaap,
454 config,
455 portsc,
456 doorbells,
457 iman,
458 imod,
459 erstsz,
460 erstba,
461 erdp,
462 };
463
464 /* End of Host Controller Operational Registers */
465
466 /* Extended Capability Registers */
467
468 // Extended capability registers. Base offset defined by hccparams1.
469 // Each set of 4 registers represents a "Supported Protocol" extended
470 // capability. The first capability indicates that ports 1-8 are USB 2.0. There is no USB 3.0
471 // port for now. See xHCI spec 7.1 & 7.2 for more details.
472 mmio.add_register(
473 // spcap 1.1
474 static_register!(
475 ty: u32,
476 offset: 0xc000,
477 // "Supported Protocol" capability.
478 // Next capability starts after 0x40 dwords.
479 // USB 2.0. Revision 2.0.
480 value: 0x02004002,
481 ),
482 );
483 mmio.add_register(
484 // spcap 1.2
485 static_register!(
486 ty: u32,
487 offset: 0xc004,
488 value: 0x20425355, // Name string = "USB "
489 ),
490 );
491 mmio.add_register(
492 // spcap 1.3
493 static_register!(
494 ty: u32,
495 offset: 0xc008,
496 value: 0x00000801, // 8 ports starting at port 1. See USB2_PORTS_START and USB2_PORTS_END.
497 ),
498 );
499
500 mmio.add_register(
501 // spcap 1.4
502 static_register!(
503 ty: u32,
504 offset: 0xc00c,
505 // The specification says that this shall be set to 0.
506 // Section 7.2.2.1.4.
507 value: 0,
508 ),
509 );
510
511 mmio.add_register(
512 // spcap 2.1
513 static_register!(
514 ty: u32,
515 offset: 0xc100,
516 // "Supported Protocol" capability.
517 // Not next capability.
518 // USB 3.0. Revision 2.0.
519 value: 0x03000002,
520 ),
521 );
522 mmio.add_register(
523 // spcap 2.2
524 static_register!(
525 ty: u32,
526 offset: 0xc104,
527 value: 0x20425355, // Name string = "USB "
528 ),
529 );
530 mmio.add_register(
531 // spcap 2.3
532 static_register!(
533 ty: u32,
534 offset: 0xc108,
535 value: 0x00000809, // 8 ports starting at port 9. See USB3_PORTS_START and USB3_PORTS_END.
536 ),
537 );
538
539 mmio.add_register(
540 // spcap 2.4
541 static_register!(
542 ty: u32,
543 offset: 0xc10c,
544 // The specification says that this shall be set to 0.
545 // Section 7.2.2.1.4.
546 value: 0,
547 ),
548 );
549
550 /* End of Host Controller Operational Registers */
551
552 (mmio, xhci_regs)
553 }
554