1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
|
/******************************************************************************
* Copyright (c) 2013 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/
/*
* Definitions for XHCI Controller - Revision 1.0 (5/21/10)
*
*/
#ifndef USB_XHCI_H
#define USB_XHCI_H
#include <stdint.h>
#include "usb-core.h"
#define BIT(x) (1 << x)
/* 5.3 Host Controller Capability Registers
* Table 19
*/
struct xhci_cap_regs {
uint8_t caplength;
uint8_t reserved;
uint16_t hciversion;
uint32_t hcsparams1;
uint32_t hcsparams2;
uint32_t hcsparams3;
uint32_t hccparams;
#define XHCI_HCCPARAMS_CSZ BIT(2)
#define XHCI_HCCPARAMS_XECP(x) ((x & 0xFFFF0000) >> 16)
uint32_t dboff;
uint32_t rtsoff;
} __attribute__ ((packed));
/* USB 3.0: Section 7 and 7.2 */
#define XHCI_XECP_CAP_ID(x) ((x & 0xF))
#define XHCI_XECP_CAP_SP 2
#define XHCI_XECP_CAP_SP_MN(x) ((x & 0xFF0000) >> 16)
#define XHCI_XECP_CAP_SP_MJ(x) ((x & 0xFF000000) >> 24)
#define XHCI_XECP_CAP_SP_PC(x) ((x & 0xFF00) >> 8)
#define XHCI_XECP_CAP_SP_PO(x) (x & 0xFF)
#define XHCI_XECP_NEXT_PTR(x) ((x & 0xFF00) >> 8)
/* Table 27: Host Controller USB Port Register Set */
struct xhci_port_regs {
uint32_t portsc;
#define PORTSC_CCS BIT(0)
#define PORTSC_PED BIT(1)
#define PORTSC_OCA BIT(3)
#define PORTSC_PR BIT(4)
#define PORTSC_PLS_MASK (0xF << 5)
#define PORTSC_PLS_U0 0
#define PORTSC_PLS_U1 1
#define PORTSC_PLS_U2 2
#define PORTSC_PLS_U3 3
#define PORTSC_PLS_DISABLED 4
#define PORTSC_PLS_RXDETECT 5
#define PORTSC_PLS_INACTIVE 6
#define PORTSC_PLS_POLLING 7
#define PORTSC_PLS_RECOVERY 8
#define PORTSC_PLS_HOTRESET 9
#define PORTSC_PLS_COMP_MODE 10
#define PORTSC_PLS_TEST_MODE 11
#define PORTSC_PLS_RESUME 15
#define PORTSC_PP BIT(9)
#define PORTSC_PS_MASK (0xF << 10)
#define PORTSC_PIC_MASK (0x3 << 14)
#define PORTSC_LWS BIT(16)
#define PORTSC_CSC BIT(17)
#define PORTSC_PEC BIT(18)
#define PORTSC_WRC BIT(19)
#define PORTSC_OCC BIT(20)
#define PORTSC_PRC BIT(21)
#define PORTSC_PLC BIT(22)
#define PORTSC_CEC BIT(23)
#define PORTSC_CAS BIT(24)
#define PORTSC_WCE BIT(25)
#define PORTSC_WDE BIT(26)
#define PORTSC_WOE BIT(27)
#define PORTSC_DR BIT(30)
#define PORTSC_WPR BIT(31)
uint32_t portpmsc;
uint32_t portli;
uint32_t reserved;
} __attribute__ ((packed));
struct port_state {
bool PP;
bool CCS;
bool PED;
bool PR;
uint8_t PLS;
char *state;
};
struct port_state ps_array_usb2[] = {
{1, 0, 0, 0, PORTSC_PLS_U0, "ERROR"}
};
struct port_state ps_array_usb3[] = {
{0, 0, 0, 0, PORTSC_PLS_DISABLED, "Powered-OFF"},
{1, 0, 0, 0, PORTSC_PLS_POLLING, "Polling"},
{1, 0, 0, 0, PORTSC_PLS_U0, "Polling"},
{1, 0, 0, 0, PORTSC_PLS_RXDETECT, "*** Disconnected ***"},
{1, 0, 0, 0, PORTSC_PLS_DISABLED, "Disabled"},
{1, 0, 0, 0, PORTSC_PLS_INACTIVE, "Error"},
{1, 0, 0, 0, PORTSC_PLS_TEST_MODE,"Loopback"},
{1, 0, 0, 0, PORTSC_PLS_COMP_MODE,"Compliancek"},
{1, 1, 0, 1, PORTSC_PLS_U0, "****** Reset ******"},
{1, 1, 1, 0, PORTSC_PLS_U0, "****** Enabled ******"},
};
/* 5.4 Host Controller Operational Registers
* Table 26
*/
struct xhci_op_regs {
uint32_t usbcmd;
#define XHCI_USBCMD_RS BIT(0)
#define XHCI_USBCMD_HCRST BIT(1)
uint32_t usbsts;
#define XHCI_USBSTS_HCH BIT(0)
#define XHCI_USBSTS_CNR BIT(11)
uint32_t pagesize;
uint8_t reserved[8]; /* 0C - 13 */
uint32_t dnctrl; /* Device notification control */
uint64_t crcr; /* Command ring control */
#define XHCI_CRCR_CRP_MASK 0xFFFFFFFFFFFFFFC0
#define XHCI_CRCR_CRR BIT(3)
#define XHCI_CRCR_CRP_SIZE 4096
uint8_t reserved1[16]; /* 20 - 2F */
uint64_t dcbaap; /* Device Context Base Address Array Pointer */
#define XHCI_DCBAAP_MAX_SIZE 2048
uint32_t config; /* Configure */
#define XHCI_CONFIG_MAX_SLOT 4
uint8_t reserved2[964]; /* 3C - 3FF */
/* USB Port register set */
#define XHCI_PORT_MAX 256
struct xhci_port_regs prs[XHCI_PORT_MAX];
} __attribute__ ((packed));
/*
* 5.5.2 Interrupter Register Set
* Table 42: Interrupter Registers
*/
struct xhci_int_regs {
uint32_t iman;
uint32_t imod;
uint32_t erstsz;
#define XHCI_ERST_SIZE_MASK 0xFFFF
uint32_t reserved;
uint64_t erstba;
#define XHCI_ERST_ADDR_MASK (~(0x3FUL))
uint64_t erdp;
#define XHCI_ERDP_MASK (~(0xFUL))
} __attribute__ ((packed));
/* 5.5 Host Controller Runtime Registers */
struct xhci_run_regs {
uint32_t mfindex; /* microframe index */
uint8_t reserved[28];
#define XHCI_IRS_MAX 1024
struct xhci_int_regs irs[XHCI_IRS_MAX];
} __attribute__ ((packed));
/* 5.6 Doorbell Registers*/
struct xhci_db_regs {
uint32_t db[256];
} __attribute__ ((packed));
#define COMP_SUCCESS 1
#define TRB_SLOT_ID(x) (((x) & (0xFF << 24)) >> 24)
#define TRB_CMD_SLOT_ID(x) ((x & 0xFF) << 24)
#define TRB_TYPE(x) (((x) & (0x3F << 10)) >> 10)
#define TRB_CMD_TYPE(x) ((x & 0x3F) << 10)
#define TRB_STATUS(x) (((x) & (0xFF << 24)) >> 24)
#define TRB_ADDR_LOW(x) ((uint32_t)((uint64_t)(x)))
#define TRB_ADDR_HIGH(x) ((uint32_t)((uint64_t)(x) >> 32))
#define TRB_TRT(x) (((x) & 0x3) << 16 )
#define TRB_DIR_IN BIT(16)
#define TRB_IOC BIT(5)
#define TRB_IDT BIT(6)
#define TRB_CYCLE_STATE BIT(0)
struct xhci_transfer_trb {
uint64_t addr;
uint32_t len;
uint32_t flags;
} __attribute__ ((packed));
struct xhci_link_trb {
uint64_t addr;
uint32_t field2;
uint32_t field3;
} __attribute__ ((packed));
/* Event TRB */
struct xhci_event_trb {
uint64_t addr;
uint32_t status;
uint32_t flags;
} __attribute__ ((packed));
#define TRB_NORMAL 1
#define TRB_SETUP_STAGE 2
#define TRB_DATA_STAGE 3
#define TRB_STATUS_STAGE 4
#define TRB_ISOCH 5
#define TRB_LINK 6
#define TRB_EVENT_DATA 7
#define TRB_NOOP 8
#define TRB_ENABLE_SLOT 9
#define TRB_DISABLE_SLOT 10
#define TRB_ADDRESS_DEV 11
#define TRB_CONFIG_EP 12
#define TRB_EVAL_CNTX 13
#define TRB_TRANSFER_EVENT 32
#define TRB_CMD_COMPLETION 33
#define TRB_PORT_STATUS 34
struct xhci_command_trb {
uint32_t field[4];
}__attribute__ ((packed));
union xhci_trb {
struct xhci_event_trb event;
struct xhci_transfer_trb xfer;
struct xhci_command_trb cmd;
struct xhci_link_trb link;
};
enum xhci_seg_type {
TYPE_CTRL = 0,
TYPE_BULK,
TYPE_COMMAND,
TYPE_EVENT,
};
struct xhci_seg {
union xhci_trb *trbs;
struct xhci_seg *next;
uint64_t enq;
uint64_t deq;
uint64_t trbs_dma;
uint32_t size;
uint32_t cycle_state;
enum xhci_seg_type type;
};
#define XHCI_TRB_SIZE 16
#define XHCI_EVENT_TRBS_SIZE 4096
#define XHCI_CONTROL_TRBS_SIZE 4096
#define XHCI_DATA_TRBS_SIZE 4096
#define XHCI_ERST_NUM_SEGS 1
#define XHCI_MAX_BULK_SIZE 0xF000
struct xhci_erst_entry {
uint64_t addr;
uint32_t size;
uint32_t reserved;
} __attribute__ ((packed));
struct xhci_erst {
struct xhci_erst_entry *entries;
uint64_t dma;
uint32_t num_segs; /* number of segments */
};
struct xhci_control_ctx {
uint32_t d_flags;
uint32_t a_flags;
uint32_t reserved[6];
} __attribute__ ((packed));
struct xhci_slot_ctx {
uint32_t field1;
#define SLOT_SPEED_FS BIT(20)
#define SLOT_SPEED_LS BIT(21)
#define SLOT_SPEED_HS BIT(22)
#define SLOT_SPEED_SS BIT(23)
#define LAST_CONTEXT(x) (x << 27)
uint32_t field2;
#define ROOT_HUB_PORT(x) ((x & 0xff) << 16)
uint32_t field3;
uint32_t field4;
#define USB_DEV_ADDRESS(x) (x & 0xFFU)
#define SLOT_STATE(x) ((x >> 27) & 0x1FU)
#define SLOT_STATE_DIS_ENA 0
#define SLOT_STATE_DEFAULT 1
#define SLOT_STATE_ADDRESSED 2
#define SLOT_STATE_CONFIGURED 3
uint32_t reserved[4];
} __attribute__ ((packed));
struct xhci_ep_ctx {
uint32_t field1;
uint32_t field2;
#define MAX_PACKET_SIZE(x) (((x) & 0xFFFF) << 16)
#define MAX_BURST(x) (((x) & 0xFF) << 8)
#define EP_TYPE(x) (((x) & 0x07) << 3)
#define EP_ISOC_OUT 1
#define EP_BULK_OUT 2
#define EP_INT_OUT 3
#define EP_CTRL 4
#define EP_ISOC_IN 5
#define EP_BULK_IN 6
#define EP_INT_IN 7
#define ERROR_COUNT(x) (((x) & 0x03) << 1)
uint64_t deq_addr;
uint32_t field4;
uint32_t reserved[3];
} __attribute__ ((packed));
struct xhci_ctx {
uint8_t type;
#define XHCI_CTX_TYPE_DEVICE 0x1
#define XHCI_CTX_TYPE_INPUT 0x2
uint32_t size;
uint8_t *addr;
#define XHCI_CTX_BUF_SIZE 4096
uint64_t dma_addr;
};
struct xhci_dev {
struct usb_dev *dev;
uint32_t slot_id;
struct xhci_ctx in_ctx;
struct xhci_ctx out_ctx;
struct xhci_seg control;
struct xhci_seg bulk_in;
struct xhci_seg bulk_out;
uint32_t ctx_size;
};
struct xhci_hcd {
struct xhci_cap_regs *cap_regs;
struct xhci_op_regs *op_regs;
struct xhci_run_regs *run_regs;
struct xhci_db_regs *db_regs;
struct usb_hcd_dev *hcidev;
struct xhci_dev xdevs[XHCI_CONFIG_MAX_SLOT + 1];
struct usb_pipe *freelist;
struct usb_pipe *end;
uint64_t *dcbaap;
uint64_t dcbaap_dma;
struct xhci_seg ering;
struct xhci_seg crseg;
struct xhci_erst erst;
uint64_t erds_dma;
uint32_t erds_size;
uint32_t slot_id;
uint32_t hcc_csz_64;
void *pool;
#define XHCI_PIPE_POOL_SIZE 4096
long pool_phys;
};
struct xhci_pipe {
struct usb_pipe pipe;
struct xhci_seg *seg;
};
#endif /* USB_XHCI_H */
|