xref: /aosp_15_r20/external/crosvm/devices/src/usb/xhci/xhci_regs.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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(&register_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(&register_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(&register_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