blob: 654febaad108410d17a2a42c5273c0ceabc68513 [file] [log] [blame]
Kevin O'Connor151d0342014-01-27 12:25:35 -05001// Code for handling XHCI "Super speed" USB controllers.
2//
3// Copyright (C) 2013 Gerd Hoffmann <kraxel@redhat.com>
4// Copyright (C) 2014 Kevin O'Connor <kevin@koconnor.net>
5//
6// This file may be distributed under the terms of the GNU LGPLv3 license.
7
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02008#include "config.h" // CONFIG_*
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02009#include "malloc.h" // memalign_low
Kevin O'Connor347f3632013-12-27 18:30:02 -050010#include "memmap.h" // PAGE_SIZE
11#include "output.h" // dprintf
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020012#include "pci.h" // pci_bdf_to_bus
Kevin O'Connorec443ff2013-12-05 18:43:20 -050013#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_XHCI
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020014#include "pci_regs.h" // PCI_BASE_ADDRESS_0
Kevin O'Connorb2030132014-09-10 08:31:28 -040015#include "string.h" // memcpy
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020016#include "usb.h" // struct usb_s
17#include "usb-xhci.h" // struct ehci_qh
Kevin O'Connor347f3632013-12-27 18:30:02 -050018#include "util.h" // timer_calc
19#include "x86.h" // readl
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020020
21// --------------------------------------------------------------
22// configuration
23
24#define XHCI_RING_ITEMS 16
25#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb))
26
27/*
28 * xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
29 * then we can get it from a trb pointer (provided by evt ring).
30 */
31#define XHCI_RING(_trb) \
32 ((struct xhci_ring*)((u32)(_trb) & ~(XHCI_RING_SIZE-1)))
33
34// --------------------------------------------------------------
35// bit definitions
36
37#define XHCI_CMD_RS (1<<0)
38#define XHCI_CMD_HCRST (1<<1)
39#define XHCI_CMD_INTE (1<<2)
40#define XHCI_CMD_HSEE (1<<3)
41#define XHCI_CMD_LHCRST (1<<7)
42#define XHCI_CMD_CSS (1<<8)
43#define XHCI_CMD_CRS (1<<9)
44#define XHCI_CMD_EWE (1<<10)
45#define XHCI_CMD_EU3S (1<<11)
46
47#define XHCI_STS_HCH (1<<0)
48#define XHCI_STS_HSE (1<<2)
49#define XHCI_STS_EINT (1<<3)
50#define XHCI_STS_PCD (1<<4)
51#define XHCI_STS_SSS (1<<8)
52#define XHCI_STS_RSS (1<<9)
53#define XHCI_STS_SRE (1<<10)
54#define XHCI_STS_CNR (1<<11)
55#define XHCI_STS_HCE (1<<12)
56
57#define XHCI_PORTSC_CCS (1<<0)
58#define XHCI_PORTSC_PED (1<<1)
59#define XHCI_PORTSC_OCA (1<<3)
60#define XHCI_PORTSC_PR (1<<4)
61#define XHCI_PORTSC_PLS_SHIFT 5
62#define XHCI_PORTSC_PLS_MASK 0xf
63#define XHCI_PORTSC_PP (1<<9)
64#define XHCI_PORTSC_SPEED_SHIFT 10
65#define XHCI_PORTSC_SPEED_MASK 0xf
66#define XHCI_PORTSC_SPEED_FULL (1<<10)
67#define XHCI_PORTSC_SPEED_LOW (2<<10)
68#define XHCI_PORTSC_SPEED_HIGH (3<<10)
69#define XHCI_PORTSC_SPEED_SUPER (4<<10)
70#define XHCI_PORTSC_PIC_SHIFT 14
71#define XHCI_PORTSC_PIC_MASK 0x3
72#define XHCI_PORTSC_LWS (1<<16)
73#define XHCI_PORTSC_CSC (1<<17)
74#define XHCI_PORTSC_PEC (1<<18)
75#define XHCI_PORTSC_WRC (1<<19)
76#define XHCI_PORTSC_OCC (1<<20)
77#define XHCI_PORTSC_PRC (1<<21)
78#define XHCI_PORTSC_PLC (1<<22)
79#define XHCI_PORTSC_CEC (1<<23)
80#define XHCI_PORTSC_CAS (1<<24)
81#define XHCI_PORTSC_WCE (1<<25)
82#define XHCI_PORTSC_WDE (1<<26)
83#define XHCI_PORTSC_WOE (1<<27)
84#define XHCI_PORTSC_DR (1<<30)
85#define XHCI_PORTSC_WPR (1<<31)
86
87#define TRB_C (1<<0)
88#define TRB_TYPE_SHIFT 10
89#define TRB_TYPE_MASK 0x3f
90#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
91
92#define TRB_EV_ED (1<<2)
93
94#define TRB_TR_ENT (1<<1)
95#define TRB_TR_ISP (1<<2)
96#define TRB_TR_NS (1<<3)
97#define TRB_TR_CH (1<<4)
98#define TRB_TR_IOC (1<<5)
99#define TRB_TR_IDT (1<<6)
100#define TRB_TR_TBC_SHIFT 7
101#define TRB_TR_TBC_MASK 0x3
102#define TRB_TR_BEI (1<<9)
103#define TRB_TR_TLBPC_SHIFT 16
104#define TRB_TR_TLBPC_MASK 0xf
105#define TRB_TR_FRAMEID_SHIFT 20
106#define TRB_TR_FRAMEID_MASK 0x7ff
107#define TRB_TR_SIA (1<<31)
108
109#define TRB_TR_DIR (1<<16)
110
111#define TRB_CR_SLOTID_SHIFT 24
112#define TRB_CR_SLOTID_MASK 0xff
113#define TRB_CR_EPID_SHIFT 16
114#define TRB_CR_EPID_MASK 0x1f
115
116#define TRB_CR_BSR (1<<9)
117#define TRB_CR_DC (1<<9)
118
119#define TRB_LK_TC (1<<1)
120
121#define TRB_INTR_SHIFT 22
122#define TRB_INTR_MASK 0x3ff
123#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)
124
125typedef enum TRBType {
126 TRB_RESERVED = 0,
127 TR_NORMAL,
128 TR_SETUP,
129 TR_DATA,
130 TR_STATUS,
131 TR_ISOCH,
132 TR_LINK,
133 TR_EVDATA,
134 TR_NOOP,
135 CR_ENABLE_SLOT,
136 CR_DISABLE_SLOT,
137 CR_ADDRESS_DEVICE,
138 CR_CONFIGURE_ENDPOINT,
139 CR_EVALUATE_CONTEXT,
140 CR_RESET_ENDPOINT,
141 CR_STOP_ENDPOINT,
142 CR_SET_TR_DEQUEUE,
143 CR_RESET_DEVICE,
144 CR_FORCE_EVENT,
145 CR_NEGOTIATE_BW,
146 CR_SET_LATENCY_TOLERANCE,
147 CR_GET_PORT_BANDWIDTH,
148 CR_FORCE_HEADER,
149 CR_NOOP,
150 ER_TRANSFER = 32,
151 ER_COMMAND_COMPLETE,
152 ER_PORT_STATUS_CHANGE,
153 ER_BANDWIDTH_REQUEST,
154 ER_DOORBELL,
155 ER_HOST_CONTROLLER,
156 ER_DEVICE_NOTIFICATION,
157 ER_MFINDEX_WRAP,
158} TRBType;
159
160typedef enum TRBCCode {
161 CC_INVALID = 0,
162 CC_SUCCESS,
163 CC_DATA_BUFFER_ERROR,
164 CC_BABBLE_DETECTED,
165 CC_USB_TRANSACTION_ERROR,
166 CC_TRB_ERROR,
167 CC_STALL_ERROR,
168 CC_RESOURCE_ERROR,
169 CC_BANDWIDTH_ERROR,
170 CC_NO_SLOTS_ERROR,
171 CC_INVALID_STREAM_TYPE_ERROR,
172 CC_SLOT_NOT_ENABLED_ERROR,
173 CC_EP_NOT_ENABLED_ERROR,
174 CC_SHORT_PACKET,
175 CC_RING_UNDERRUN,
176 CC_RING_OVERRUN,
177 CC_VF_ER_FULL,
178 CC_PARAMETER_ERROR,
179 CC_BANDWIDTH_OVERRUN,
180 CC_CONTEXT_STATE_ERROR,
181 CC_NO_PING_RESPONSE_ERROR,
182 CC_EVENT_RING_FULL_ERROR,
183 CC_INCOMPATIBLE_DEVICE_ERROR,
184 CC_MISSED_SERVICE_ERROR,
185 CC_COMMAND_RING_STOPPED,
186 CC_COMMAND_ABORTED,
187 CC_STOPPED,
188 CC_STOPPED_LENGTH_INVALID,
189 CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
190 CC_ISOCH_BUFFER_OVERRUN = 31,
191 CC_EVENT_LOST_ERROR,
192 CC_UNDEFINED_ERROR,
193 CC_INVALID_STREAM_ID_ERROR,
194 CC_SECONDARY_BANDWIDTH_ERROR,
195 CC_SPLIT_TRANSACTION_ERROR
196} TRBCCode;
197
198enum {
199 PLS_U0 = 0,
200 PLS_U1 = 1,
201 PLS_U2 = 2,
202 PLS_U3 = 3,
203 PLS_DISABLED = 4,
204 PLS_RX_DETECT = 5,
205 PLS_INACTIVE = 6,
206 PLS_POLLING = 7,
207 PLS_RECOVERY = 8,
208 PLS_HOT_RESET = 9,
209 PLS_COMPILANCE_MODE = 10,
210 PLS_TEST_MODE = 11,
211 PLS_RESUME = 15,
212};
213
214#define xhci_get_field(data, field) \
215 (((data) >> field##_SHIFT) & field##_MASK)
216
217// --------------------------------------------------------------
218// state structs
219
220struct xhci_ring {
221 struct xhci_trb ring[XHCI_RING_ITEMS];
222 struct xhci_trb evt;
223 u32 eidx;
224 u32 nidx;
225 u32 cs;
226 struct mutex_s lock;
227};
228
229struct usb_xhci_s {
230 struct usb_s usb;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200231
232 /* devinfo */
233 u32 baseaddr;
234 u32 xcap;
235 u32 ports;
236 u32 slots;
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500237 u8 context64;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200238
239 /* xhci registers */
240 struct xhci_caps *caps;
241 struct xhci_op *op;
242 struct xhci_pr *pr;
243 struct xhci_ir *ir;
244 struct xhci_db *db;
245
246 /* xhci data structures */
247 struct xhci_devlist *devs;
248 struct xhci_ring *cmds;
249 struct xhci_ring *evts;
250 struct xhci_er_seg *eseg;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200251};
252
253struct xhci_pipe {
254 struct xhci_ring reqs;
255
256 struct usb_pipe pipe;
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500257 u32 slotid;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200258 u32 epid;
259 void *buf;
260 int bufused;
261};
262
263// --------------------------------------------------------------
264// tables
265
266static const char *speed_name[16] = {
267 [ 0 ] = " - ",
268 [ 1 ] = "Full",
269 [ 2 ] = "Low",
270 [ 3 ] = "High",
271 [ 4 ] = "Super",
272};
273
274static const int speed_from_xhci[16] = {
Paul Menzelf08e8472013-10-03 11:55:48 +0200275 [ 0 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200276 [ 1 ] = USB_FULLSPEED,
277 [ 2 ] = USB_LOWSPEED,
278 [ 3 ] = USB_HIGHSPEED,
279 [ 4 ] = USB_SUPERSPEED,
Paul Menzelf08e8472013-10-03 11:55:48 +0200280 [ 5 ... 15 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200281};
282
283static const int speed_to_xhci[] = {
284 [ USB_FULLSPEED ] = 1,
285 [ USB_LOWSPEED ] = 2,
286 [ USB_HIGHSPEED ] = 3,
287 [ USB_SUPERSPEED ] = 4,
288};
289
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200290static const int eptype_to_xhci_in[] = {
291 [ USB_ENDPOINT_XFER_CONTROL] = 4,
292 [ USB_ENDPOINT_XFER_ISOC ] = 5,
293 [ USB_ENDPOINT_XFER_BULK ] = 6,
294 [ USB_ENDPOINT_XFER_INT ] = 7,
295};
296
297static const int eptype_to_xhci_out[] = {
298 [ USB_ENDPOINT_XFER_CONTROL] = 4,
299 [ USB_ENDPOINT_XFER_ISOC ] = 1,
300 [ USB_ENDPOINT_XFER_BULK ] = 2,
301 [ USB_ENDPOINT_XFER_INT ] = 3,
302};
303
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400304static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout)
305{
306 u32 end = timer_calc(timeout);
307
308 while ((readl(reg) & mask) != value) {
309 if (timer_check(end)) {
310 warn_timeout();
311 return -1;
312 }
313 yield();
314 }
315 return 0;
316}
317
318
319/****************************************************************
320 * Root hub
321 ****************************************************************/
322
Kevin O'Connor0f681302014-09-10 11:33:01 -0400323#define XHCI_TIME_POSTPOWER 20
324
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400325// Check if device attached to port
326static void
327xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc)
328{
329 u32 pls = xhci_get_field(portsc, XHCI_PORTSC_PLS);
330 u32 speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED);
331
332 dprintf(loglevel, "%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n",
333 prefix, port + 1, portsc,
334 (portsc & XHCI_PORTSC_PP) ? " powered," : "",
335 (portsc & XHCI_PORTSC_PED) ? " enabled," : "",
336 pls, speed, speed_name[speed]);
337}
338
339static int
340xhci_hub_detect(struct usbhub_s *hub, u32 port)
341{
342 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
343 u32 portsc = readl(&xhci->pr[port].portsc);
Kevin O'Connor0f681302014-09-10 11:33:01 -0400344 return (portsc & XHCI_PORTSC_CCS) ? 1 : 0;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400345}
346
347// Reset device on port
348static int
349xhci_hub_reset(struct usbhub_s *hub, u32 port)
350{
351 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
352 u32 portsc = readl(&xhci->pr[port].portsc);
Kevin O'Connoraa34e4e2015-11-10 08:50:52 -0500353 if (!(portsc & XHCI_PORTSC_CCS))
354 // Device no longer connected?!
355 return -1;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400356
357 switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) {
358 case PLS_U0:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500359 // A USB3 port - controller automatically performs reset
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400360 break;
361 case PLS_POLLING:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500362 // A USB2 port - perform device reset
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400363 xhci_print_port_state(3, __func__, port, portsc);
Kevin O'Connoraa34e4e2015-11-10 08:50:52 -0500364 writel(&xhci->pr[port].portsc, portsc | XHCI_PORTSC_PR);
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400365 break;
366 default:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500367 return -1;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400368 }
369
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500370 // Wait for device to complete reset and be enabled
371 u32 end = timer_calc(100);
372 for (;;) {
373 portsc = readl(&xhci->pr[port].portsc);
374 if (!(portsc & XHCI_PORTSC_CCS))
375 // Device disconnected during reset
376 return -1;
377 if (portsc & XHCI_PORTSC_PED)
378 // Reset complete
379 break;
380 if (timer_check(end)) {
381 warn_timeout();
382 return -1;
383 }
384 yield();
385 }
386
387 int rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)];
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400388 xhci_print_port_state(1, "XHCI", port, portsc);
389 return rc;
390}
391
392static void
393xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
394{
395 // XXX - should turn the port power off.
396}
397
398static struct usbhub_op_s xhci_hub_ops = {
399 .detect = xhci_hub_detect,
400 .reset = xhci_hub_reset,
401 .disconnect = xhci_hub_disconnect,
402};
403
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400404// Find any devices connected to the root hub.
405static int
406xhci_check_ports(struct usb_xhci_s *xhci)
407{
Kevin O'Connor0f681302014-09-10 11:33:01 -0400408 // Wait for port power to stabilize.
409 msleep(XHCI_TIME_POSTPOWER);
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400410
411 struct usbhub_s hub;
412 memset(&hub, 0, sizeof(hub));
413 hub.cntl = &xhci->usb;
414 hub.portcount = xhci->ports;
415 hub.op = &xhci_hub_ops;
416 usb_enumerate(&hub);
417 return hub.devcount;
418}
419
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400420
421/****************************************************************
422 * Setup
423 ****************************************************************/
424
425static void
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400426xhci_free_pipes(struct usb_xhci_s *xhci)
427{
428 // XXX - should walk list of pipes and free unused pipes.
429}
430
431static void
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400432configure_xhci(void *data)
433{
434 struct usb_xhci_s *xhci = data;
435 u32 reg;
436
437 xhci->devs = memalign_high(64, sizeof(*xhci->devs) * (xhci->slots + 1));
438 xhci->eseg = memalign_high(64, sizeof(*xhci->eseg));
439 xhci->cmds = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->cmds));
440 xhci->evts = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->evts));
441 if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) {
442 warn_noalloc();
443 goto fail;
444 }
445 memset(xhci->devs, 0, sizeof(*xhci->devs) * (xhci->slots + 1));
446 memset(xhci->cmds, 0, sizeof(*xhci->cmds));
447 memset(xhci->evts, 0, sizeof(*xhci->evts));
448 memset(xhci->eseg, 0, sizeof(*xhci->eseg));
449
450 reg = readl(&xhci->op->usbcmd);
451 if (reg & XHCI_CMD_RS) {
452 reg &= ~XHCI_CMD_RS;
453 writel(&xhci->op->usbcmd, reg);
454 if (wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32) != 0)
455 goto fail;
456 }
457
458 dprintf(3, "%s: resetting\n", __func__);
459 writel(&xhci->op->usbcmd, XHCI_CMD_HCRST);
460 if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0)
461 goto fail;
462 if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0)
463 goto fail;
464
465 writel(&xhci->op->config, xhci->slots);
466 writel(&xhci->op->dcbaap_low, (u32)xhci->devs);
467 writel(&xhci->op->dcbaap_high, 0);
468 writel(&xhci->op->crcr_low, (u32)xhci->cmds | 1);
469 writel(&xhci->op->crcr_high, 0);
470 xhci->cmds->cs = 1;
471
472 xhci->eseg->ptr_low = (u32)xhci->evts;
473 xhci->eseg->ptr_high = 0;
474 xhci->eseg->size = XHCI_RING_ITEMS;
475 writel(&xhci->ir->erstsz, 1);
476 writel(&xhci->ir->erdp_low, (u32)xhci->evts);
477 writel(&xhci->ir->erdp_high, 0);
478 writel(&xhci->ir->erstba_low, (u32)xhci->eseg);
479 writel(&xhci->ir->erstba_high, 0);
480 xhci->evts->cs = 1;
481
482 reg = readl(&xhci->caps->hcsparams2);
Julius Wernerfd318e42015-08-07 20:07:12 -0700483 u32 spb = (reg >> 21 & 0x1f) << 5 | reg >> 27;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400484 if (spb) {
485 dprintf(3, "%s: setup %d scratch pad buffers\n", __func__, spb);
486 u64 *spba = memalign_high(64, sizeof(*spba) * spb);
487 void *pad = memalign_high(PAGE_SIZE, PAGE_SIZE * spb);
488 if (!spba || !pad) {
489 warn_noalloc();
490 free(spba);
491 free(pad);
492 goto fail;
493 }
494 int i;
495 for (i = 0; i < spb; i++)
496 spba[i] = (u32)pad + (i * PAGE_SIZE);
497 xhci->devs[0].ptr_low = (u32)spba;
498 xhci->devs[0].ptr_high = 0;
499 }
500
501 reg = readl(&xhci->op->usbcmd);
502 reg |= XHCI_CMD_RS;
503 writel(&xhci->op->usbcmd, reg);
504
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400505 // Find devices
506 int count = xhci_check_ports(xhci);
507 xhci_free_pipes(xhci);
508 if (count)
509 // Success
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400510 return;
511
512 // No devices found - shutdown and free controller.
513 dprintf(1, "XHCI no devices found\n");
514 reg = readl(&xhci->op->usbcmd);
515 reg &= ~XHCI_CMD_RS;
516 writel(&xhci->op->usbcmd, reg);
517 wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32);
518
519fail:
520 free(xhci->eseg);
521 free(xhci->evts);
522 free(xhci->cmds);
523 free(xhci->devs);
524 free(xhci);
525}
526
527static void
528xhci_controller_setup(struct pci_device *pci)
529{
530 struct usb_xhci_s *xhci = malloc_high(sizeof(*xhci));
531 if (!xhci) {
532 warn_noalloc();
533 return;
534 }
535 memset(xhci, 0, sizeof(*xhci));
536
537 wait_preempt(); // Avoid pci_config_readl when preempting
538 xhci->baseaddr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
539 & PCI_BASE_ADDRESS_MEM_MASK;
540 xhci->caps = (void*)(xhci->baseaddr);
541 xhci->op = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength));
542 xhci->pr = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength) + 0x400);
543 xhci->db = (void*)(xhci->baseaddr + readl(&xhci->caps->dboff));
544 xhci->ir = (void*)(xhci->baseaddr + readl(&xhci->caps->rtsoff) + 0x20);
545
546 u32 hcs1 = readl(&xhci->caps->hcsparams1);
547 u32 hcc = readl(&xhci->caps->hccparams);
548 xhci->ports = (hcs1 >> 24) & 0xff;
549 xhci->slots = hcs1 & 0xff;
550 xhci->xcap = ((hcc >> 16) & 0xffff) << 2;
551 xhci->context64 = (hcc & 0x04) ? 1 : 0;
552
553 xhci->usb.pci = pci;
554 xhci->usb.type = USB_TYPE_XHCI;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400555
556 dprintf(1, "XHCI init on dev %02x:%02x.%x: regs @ %p, %d ports, %d slots"
557 ", %d byte contexts\n"
558 , pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf)
559 , pci_bdf_to_fn(pci->bdf), xhci->caps
560 , xhci->ports, xhci->slots, xhci->context64 ? 64 : 32);
561
562 if (xhci->xcap) {
563 u32 off, addr = xhci->baseaddr + xhci->xcap;
564 do {
565 struct xhci_xcap *xcap = (void*)addr;
566 u32 ports, name, cap = readl(&xcap->cap);
567 switch (cap & 0xff) {
568 case 0x02:
569 name = readl(&xcap->data[0]);
570 ports = readl(&xcap->data[1]);
571 dprintf(1, "XHCI protocol %c%c%c%c %x.%02x"
572 ", %d ports (offset %d), def %x\n"
573 , (name >> 0) & 0xff
574 , (name >> 8) & 0xff
575 , (name >> 16) & 0xff
576 , (name >> 24) & 0xff
577 , (cap >> 24) & 0xff
578 , (cap >> 16) & 0xff
579 , (ports >> 8) & 0xff
580 , (ports >> 0) & 0xff
581 , ports >> 16);
582 break;
583 default:
584 dprintf(1, "XHCI extcap 0x%x @ %x\n", cap & 0xff, addr);
585 break;
586 }
587 off = (cap >> 8) & 0xff;
588 addr += off << 2;
589 } while (off > 0);
590 }
591
592 u32 pagesize = readl(&xhci->op->pagesize);
593 if (PAGE_SIZE != (pagesize<<12)) {
594 dprintf(1, "XHCI driver does not support page size code %d\n"
595 , pagesize<<12);
596 free(xhci);
597 return;
598 }
599
600 pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
601
602 run_thread(configure_xhci, xhci);
603}
604
605void
606xhci_setup(void)
607{
608 if (! CONFIG_USB_XHCI)
609 return;
610 struct pci_device *pci;
611 foreachpci(pci) {
612 if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI)
613 xhci_controller_setup(pci);
614 }
615}
616
617
618/****************************************************************
619 * End point communication
620 ****************************************************************/
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200621
622static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value)
623{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400624 struct xhci_db *db = xhci->db;
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500625 void *addr = &db[slotid].doorbell;
626 writel(addr, value);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200627}
628
629static void xhci_process_events(struct usb_xhci_s *xhci)
630{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400631 struct xhci_ring *evts = xhci->evts;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200632
633 for (;;) {
634 /* check for event */
Kevin O'Connorb2030132014-09-10 08:31:28 -0400635 u32 nidx = evts->nidx;
636 u32 cs = evts->cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200637 struct xhci_trb *etrb = evts->ring + nidx;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400638 u32 control = etrb->control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200639 if ((control & TRB_C) != (cs ? 1 : 0))
640 return;
641
642 /* process event */
643 u32 evt_type = TRB_TYPE(control);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400644 u32 evt_cc = (etrb->status >> 24) & 0xff;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200645 switch (evt_type) {
646 case ER_TRANSFER:
647 case ER_COMMAND_COMPLETE:
648 {
Kevin O'Connorb2030132014-09-10 08:31:28 -0400649 struct xhci_trb *rtrb = (void*)etrb->ptr_low;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200650 struct xhci_ring *ring = XHCI_RING(rtrb);
651 struct xhci_trb *evt = &ring->evt;
652 u32 eidx = rtrb - ring->ring + 1;
653 dprintf(5, "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n",
654 __func__, ring, rtrb, evt, evt_type, eidx, evt_cc);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400655 memcpy(evt, etrb, sizeof(*etrb));
656 ring->eidx = eidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200657 break;
658 }
659 case ER_PORT_STATUS_CHANGE:
660 {
Kevin O'Connorb2030132014-09-10 08:31:28 -0400661 u32 portid = (etrb->ptr_low >> 24) & 0xff;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200662 dprintf(3, "%s: status change port #%d\n",
663 __func__, portid);
664 break;
665 }
666 default:
667 dprintf(1, "%s: unknown event, type %d, cc %d\n",
668 __func__, evt_type, evt_cc);
669 break;
670 }
671
672 /* move ring index, notify xhci */
673 nidx++;
674 if (nidx == XHCI_RING_ITEMS) {
675 nidx = 0;
676 cs = cs ? 0 : 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400677 evts->cs = cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200678 }
Kevin O'Connorb2030132014-09-10 08:31:28 -0400679 evts->nidx = nidx;
680 struct xhci_ir *ir = xhci->ir;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200681 u32 erdp = (u32)(evts->ring + nidx);
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500682 writel(&ir->erdp_low, erdp);
683 writel(&ir->erdp_high, 0);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200684 }
685}
686
687static int xhci_ring_busy(struct xhci_ring *ring)
688{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400689 u32 eidx = ring->eidx;
690 u32 nidx = ring->nidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200691 return (eidx != nidx);
692}
693
694static int xhci_event_wait(struct usb_xhci_s *xhci,
695 struct xhci_ring *ring,
696 u32 timeout)
697{
698 u32 end = timer_calc(timeout);
699
700 for (;;) {
701 xhci_process_events(xhci);
702 if (!xhci_ring_busy(ring)) {
Kevin O'Connorb2030132014-09-10 08:31:28 -0400703 u32 status = ring->evt.status;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200704 return (status >> 24) & 0xff;
705 }
706 if (timer_check(end)) {
707 warn_timeout();
708 return -1;
709 }
710 yield();
711 }
712}
713
714static void xhci_trb_queue(struct xhci_ring *ring,
715 struct xhci_trb *trb)
716{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400717 u32 nidx = ring->nidx;
718 u32 cs = ring->cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200719 struct xhci_trb *dst;
720 u32 control;
721
722 if (nidx == XHCI_RING_ITEMS-1) {
723 dst = ring->ring + nidx;
724 control = (TR_LINK << 10); // trb type
725 control |= TRB_LK_TC;
726 control |= (cs ? TRB_C : 0);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400727 dst->ptr_low = (u32)&ring[0];
728 dst->ptr_high = 0;
729 dst->status = 0;
730 dst->control = control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200731 nidx = 0;
732 cs = cs ? 0 : 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400733 ring->nidx = nidx;
734 ring->cs = cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200735
736 dprintf(5, "%s: ring %p [linked]\n", __func__, ring);
737 }
738
739 dst = ring->ring + nidx;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400740 control = trb->control | (cs ? TRB_C : 0);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200741
Kevin O'Connorb2030132014-09-10 08:31:28 -0400742 dst->ptr_low = trb->ptr_low;
743 dst->ptr_high = trb->ptr_high;
744 dst->status = trb->status;
745 dst->control = control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200746 nidx++;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400747 ring->nidx = nidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200748
749 dprintf(5, "%s: ring %p [nidx %d, len %d]\n",
750 __func__, ring, nidx,
Kevin O'Connorb2030132014-09-10 08:31:28 -0400751 trb->status & 0xffff);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200752}
753
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200754static int xhci_cmd_submit(struct usb_xhci_s *xhci,
755 struct xhci_trb *cmd)
756{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200757 int rc;
758
759 mutex_lock(&xhci->cmds->lock);
760 xhci_trb_queue(xhci->cmds, cmd);
761 xhci_doorbell(xhci, 0, 0);
762 rc = xhci_event_wait(xhci, xhci->cmds, 1000);
763 mutex_unlock(&xhci->cmds->lock);
764 return rc;
765}
766
767static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci)
768{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200769 struct xhci_trb cmd = {
770 .ptr_low = 0,
771 .ptr_high = 0,
772 .status = 0,
773 .control = (CR_ENABLE_SLOT << 10)
774 };
775 dprintf(3, "%s:\n", __func__);
776 int cc = xhci_cmd_submit(xhci, &cmd);
777 if (cc != CC_SUCCESS)
778 return -1;
779 return (xhci->cmds->evt.control >> 24) & 0xff;
780}
781
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500782#if 0
783static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200784{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200785 struct xhci_trb cmd = {
786 .ptr_low = 0,
787 .ptr_high = 0,
788 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500789 .control = (slotid << 24) | (CR_DISABLE_SLOT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200790 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500791 dprintf(3, "%s: slotid %d\n", __func__, slotid);
792 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200793}
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500794#endif
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200795
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500796static int xhci_cmd_address_device(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500797 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200798{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200799 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500800 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200801 .ptr_high = 0,
802 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500803 .control = (slotid << 24) | (CR_ADDRESS_DEVICE << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200804 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500805 dprintf(3, "%s: slotid %d\n", __func__, slotid);
806 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200807}
808
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500809static int xhci_cmd_configure_endpoint(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500810 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200811{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200812 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500813 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200814 .ptr_high = 0,
815 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500816 .control = (slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200817 };
818 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500819 slotid, inctx->add, inctx->del);
820 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200821}
822
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500823static int xhci_cmd_evaluate_context(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500824 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200825{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200826 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500827 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200828 .ptr_high = 0,
829 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500830 .control = (slotid << 24) | (CR_EVALUATE_CONTEXT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200831 };
832 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500833 slotid, inctx->add, inctx->del);
834 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200835}
836
Kevin O'Connord477d552013-12-27 18:09:16 -0500837static struct xhci_inctx *
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500838xhci_alloc_inctx(struct usbdevice_s *usbdev, int maxepid)
Kevin O'Connord477d552013-12-27 18:09:16 -0500839{
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500840 struct usb_xhci_s *xhci = container_of(
841 usbdev->hub->cntl, struct usb_xhci_s, usb);
842 int size = (sizeof(struct xhci_inctx) * 33) << xhci->context64;
843 struct xhci_inctx *in = memalign_tmphigh(2048 << xhci->context64, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500844 if (!in) {
845 warn_noalloc();
846 return NULL;
847 }
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500848 memset(in, 0, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500849
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500850 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500851 slot->ctx[0] |= maxepid << 27; // context entries
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500852 slot->ctx[0] |= speed_to_xhci[usbdev->speed] << 20;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500853
854 // Set high-speed hub flags.
855 struct usbdevice_s *hubdev = usbdev->hub->usbdev;
856 if (hubdev) {
857 if (usbdev->speed == USB_LOWSPEED || usbdev->speed == USB_FULLSPEED) {
858 struct xhci_pipe *hpipe = container_of(
859 hubdev->defpipe, struct xhci_pipe, pipe);
860 if (hubdev->speed == USB_HIGHSPEED) {
861 slot->ctx[2] |= hpipe->slotid;
862 slot->ctx[2] |= (usbdev->port+1) << 8;
863 } else {
864 struct xhci_slotctx *hslot = (void*)xhci->devs[hpipe->slotid].ptr_low;
865 slot->ctx[2] = hslot->ctx[2];
866 }
867 }
868 u32 route = 0;
869 while (usbdev->hub->usbdev) {
870 route <<= 4;
871 route |= (usbdev->port+1) & 0xf;
872 usbdev = usbdev->hub->usbdev;
873 }
874 slot->ctx[0] |= route;
875 }
876
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500877 slot->ctx[1] |= (usbdev->port+1) << 16;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500878
Kevin O'Connord477d552013-12-27 18:09:16 -0500879 return in;
880}
881
Kevin O'Connor1540f922013-12-29 20:18:37 -0500882static int xhci_config_hub(struct usbhub_s *hub)
883{
884 struct usb_xhci_s *xhci = container_of(
885 hub->cntl, struct usb_xhci_s, usb);
886 struct xhci_pipe *pipe = container_of(
887 hub->usbdev->defpipe, struct xhci_pipe, pipe);
888 struct xhci_slotctx *hdslot = (void*)xhci->devs[pipe->slotid].ptr_low;
889 if ((hdslot->ctx[3] >> 27) == 3)
890 // Already configured
891 return 0;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500892 struct xhci_inctx *in = xhci_alloc_inctx(hub->usbdev, 1);
Kevin O'Connor1540f922013-12-29 20:18:37 -0500893 if (!in)
894 return -1;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500895 in->add = 0x01;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500896 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
897 slot->ctx[0] |= 1 << 26;
898 slot->ctx[1] |= hub->portcount << 24;
899
900 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
901 free(in);
902 if (cc != CC_SUCCESS) {
903 dprintf(1, "%s: configure hub: failed (cc %d)\n", __func__, cc);
904 return -1;
905 }
906 return 0;
907}
908
Kevin O'Connorc427def2014-10-16 13:23:08 -0400909static struct usb_pipe *
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200910xhci_alloc_pipe(struct usbdevice_s *usbdev
911 , struct usb_endpoint_descriptor *epdesc)
912{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200913 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
914 struct usb_xhci_s *xhci = container_of(
915 usbdev->hub->cntl, struct usb_xhci_s, usb);
916 struct xhci_pipe *pipe;
917 u32 epid;
918
919 if (epdesc->bEndpointAddress == 0) {
920 epid = 1;
921 } else {
922 epid = (epdesc->bEndpointAddress & 0x0f) * 2;
923 epid += (epdesc->bEndpointAddress & USB_DIR_IN) ? 1 : 0;
924 }
925
926 if (eptype == USB_ENDPOINT_XFER_CONTROL)
927 pipe = memalign_high(XHCI_RING_SIZE, sizeof(*pipe));
928 else
929 pipe = memalign_low(XHCI_RING_SIZE, sizeof(*pipe));
930 if (!pipe) {
931 warn_noalloc();
932 return NULL;
933 }
934 memset(pipe, 0, sizeof(*pipe));
935
936 usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200937 pipe->epid = epid;
938 pipe->reqs.cs = 1;
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -0400939 if (eptype == USB_ENDPOINT_XFER_INT) {
Kevin O'Connorc46f5a92014-09-10 09:31:43 -0400940 pipe->buf = malloc_high(pipe->pipe.maxpacket);
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -0400941 if (!pipe->buf) {
942 warn_noalloc();
943 free(pipe);
944 return NULL;
945 }
946 }
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200947
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500948 // Allocate input context and initialize endpoint info.
949 struct xhci_inctx *in = xhci_alloc_inctx(usbdev, epid);
950 if (!in)
951 goto fail;
952 in->add = 0x01 | (1 << epid);
953 struct xhci_epctx *ep = (void*)&in[(pipe->epid+1) << xhci->context64];
954 if (eptype == USB_ENDPOINT_XFER_INT)
Kevin O'Connor98cdad32014-10-16 12:05:09 -0400955 ep->ctx[0] = (usb_get_period(usbdev, epdesc) + 3) << 16;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500956 ep->ctx[1] |= eptype << 3;
957 if (epdesc->bEndpointAddress & USB_DIR_IN
958 || eptype == USB_ENDPOINT_XFER_CONTROL)
959 ep->ctx[1] |= 1 << 5;
960 ep->ctx[1] |= pipe->pipe.maxpacket << 16;
961 ep->deq_low = (u32)&pipe->reqs.ring[0];
962 ep->deq_low |= 1; // dcs
963 ep->length = pipe->pipe.maxpacket;
964
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200965 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500966 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500967 if (pipe->epid == 1) {
Kevin O'Connor1540f922013-12-29 20:18:37 -0500968 if (usbdev->hub->usbdev) {
969 // Make sure parent hub is configured.
970 int ret = xhci_config_hub(usbdev->hub);
971 if (ret)
972 goto fail;
973 }
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500974 // Enable slot.
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500975 u32 size = (sizeof(struct xhci_slotctx) * 32) << xhci->context64;
976 struct xhci_slotctx *dev = memalign_high(1024 << xhci->context64, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500977 if (!dev) {
978 warn_noalloc();
979 goto fail;
980 }
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500981 int slotid = xhci_cmd_enable_slot(xhci);
982 if (slotid < 0) {
983 dprintf(1, "%s: enable slot: failed\n", __func__);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500984 free(dev);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500985 goto fail;
986 }
987 dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid);
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500988 memset(dev, 0, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500989 pipe->slotid = usbdev->slotid = slotid;
990 xhci->devs[slotid].ptr_low = (u32)dev;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500991 xhci->devs[slotid].ptr_high = 0;
992
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500993 // Send set_address command.
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500994 int cc = xhci_cmd_address_device(xhci, slotid, in);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500995 if (cc != CC_SUCCESS) {
996 dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc);
997 goto fail;
998 }
999 } else {
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001000 pipe->slotid = usbdev->slotid;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001001 // Send configure command.
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001002 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001003 if (cc != CC_SUCCESS) {
1004 dprintf(1, "%s: configure endpoint: failed (cc %d)\n", __func__, cc);
Kevin O'Connord477d552013-12-27 18:09:16 -05001005 goto fail;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001006 }
1007 }
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001008 free(in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001009 return &pipe->pipe;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001010
Kevin O'Connord477d552013-12-27 18:09:16 -05001011fail:
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -04001012 free(pipe->buf);
Kevin O'Connord477d552013-12-27 18:09:16 -05001013 free(pipe);
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001014 free(in);
Kevin O'Connord477d552013-12-27 18:09:16 -05001015 return NULL;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001016}
1017
1018struct usb_pipe *
Kevin O'Connorc427def2014-10-16 13:23:08 -04001019xhci_realloc_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe
1020 , struct usb_endpoint_descriptor *epdesc)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001021{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001022 if (!CONFIG_USB_XHCI)
1023 return NULL;
Kevin O'Connorc427def2014-10-16 13:23:08 -04001024 if (!epdesc) {
1025 usb_add_freelist(upipe);
1026 return NULL;
1027 }
1028 if (!upipe)
1029 return xhci_alloc_pipe(usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001030 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001031 int oldmaxpacket = upipe->maxpacket;
1032 usb_desc2pipe(upipe, usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001033 struct xhci_pipe *pipe = container_of(upipe, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001034 struct usb_xhci_s *xhci = container_of(
1035 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001036 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001037 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001038 if (eptype != USB_ENDPOINT_XFER_CONTROL || upipe->maxpacket == oldmaxpacket)
1039 return upipe;
1040
1041 // maxpacket has changed on control endpoint - update controller.
1042 dprintf(1, "%s: reconf ctl endpoint pkt size: %d -> %d\n",
1043 __func__, oldmaxpacket, pipe->pipe.maxpacket);
1044 struct xhci_inctx *in = xhci_alloc_inctx(usbdev, 1);
1045 if (!in)
1046 return upipe;
1047 in->add = (1 << 1);
1048 struct xhci_epctx *ep = (void*)&in[2 << xhci->context64];
1049 ep->ctx[1] |= (pipe->pipe.maxpacket << 16);
1050 int cc = xhci_cmd_evaluate_context(xhci, pipe->slotid, in);
1051 if (cc != CC_SUCCESS) {
1052 dprintf(1, "%s: reconf ctl endpoint: failed (cc %d)\n",
1053 __func__, cc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001054 }
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001055 free(in);
1056
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001057 return upipe;
1058}
1059
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001060static void xhci_xfer_queue(struct xhci_pipe *pipe,
Kevin O'Connor65034a42014-12-31 11:05:39 -05001061 void *data, int datalen, u32 flags)
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001062{
Kevin O'Connor65034a42014-12-31 11:05:39 -05001063 struct xhci_trb trb;
1064 memset(&trb, 0, sizeof(trb));
1065 if (flags & TRB_TR_IDT)
1066 memcpy(&trb.ptr_low, data, datalen);
1067 else
1068 trb.ptr_low = (u32)data;
1069 trb.status = datalen;
1070 trb.control = flags;
1071 xhci_trb_queue(&pipe->reqs, &trb);
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001072}
1073
1074static void xhci_xfer_kick(struct xhci_pipe *pipe)
1075{
1076 struct usb_xhci_s *xhci = container_of(
1077 pipe->pipe.cntl, struct usb_xhci_s, usb);
1078 u32 slotid = pipe->slotid;
1079 u32 epid = pipe->epid;
1080
1081 dprintf(5, "%s: ring %p, slotid %d, epid %d\n",
1082 __func__, &pipe->reqs, slotid, epid);
1083 xhci_doorbell(xhci, slotid, epid);
1084}
1085
1086static void xhci_xfer_normal(struct xhci_pipe *pipe,
1087 void *data, int datalen)
1088{
Kevin O'Connor65034a42014-12-31 11:05:39 -05001089 xhci_xfer_queue(pipe, data, datalen, (TR_NORMAL << 10) | TRB_TR_IOC);
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001090 xhci_xfer_kick(pipe);
1091}
1092
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001093int
Kevin O'Connor2891a832014-12-31 17:41:14 -05001094xhci_send_pipe(struct usb_pipe *p, int dir, const void *cmd
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001095 , void *data, int datalen)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001096{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001097 if (!CONFIG_USB_XHCI)
1098 return -1;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001099 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001100 struct usb_xhci_s *xhci = container_of(
1101 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001102
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001103 if (cmd) {
1104 const struct usb_ctrlrequest *req = cmd;
1105 if (req->bRequest == USB_REQ_SET_ADDRESS)
1106 // Set address command sent during xhci_alloc_pipe.
1107 return 0;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001108
Kevin O'Connor2891a832014-12-31 17:41:14 -05001109 xhci_xfer_queue(pipe, (void*)req, USB_CONTROL_SETUP_SIZE
1110 , (TR_SETUP << 10) | TRB_TR_IDT
Kevin O'Connor65034a42014-12-31 11:05:39 -05001111 | ((datalen ? (dir ? 3 : 2) : 0) << 16));
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001112 if (datalen)
Kevin O'Connor65034a42014-12-31 11:05:39 -05001113 xhci_xfer_queue(pipe, data, datalen, (TR_DATA << 10)
1114 | ((dir ? 1 : 0) << 16));
1115 xhci_xfer_queue(pipe, NULL, 0, (TR_STATUS << 10) | TRB_TR_IOC
1116 | ((dir ? 0 : 1) << 16));
1117 xhci_xfer_kick(pipe);
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001118 } else {
1119 xhci_xfer_normal(pipe, data, datalen);
1120 }
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001121
Kevin O'Connor88fa2272014-06-14 12:25:17 -04001122 int cc = xhci_event_wait(xhci, &pipe->reqs, usb_xfer_time(p, datalen));
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001123 if (cc != CC_SUCCESS) {
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001124 dprintf(1, "%s: xfer failed (cc %d)\n", __func__, cc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001125 return -1;
1126 }
1127
1128 return 0;
1129}
1130
Kevin O'Connorde30dad2013-12-30 22:09:04 -05001131int VISIBLE32FLAT
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001132xhci_poll_intr(struct usb_pipe *p, void *data)
1133{
1134 if (!CONFIG_USB_XHCI)
1135 return -1;
1136
1137 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001138 struct usb_xhci_s *xhci = container_of(
Kevin O'Connorb2030132014-09-10 08:31:28 -04001139 pipe->pipe.cntl, struct usb_xhci_s, usb);
1140 u32 len = pipe->pipe.maxpacket;
1141 void *buf = pipe->buf;
1142 int bufused = pipe->bufused;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001143
1144 if (!bufused) {
1145 xhci_xfer_normal(pipe, buf, len);
1146 bufused = 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -04001147 pipe->bufused = bufused;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001148 return -1;
1149 }
1150
1151 xhci_process_events(xhci);
1152 if (xhci_ring_busy(&pipe->reqs))
1153 return -1;
1154 dprintf(5, "%s: st %x ct %x [ %p <= %p / %d ]\n", __func__,
Kevin O'Connorb2030132014-09-10 08:31:28 -04001155 pipe->reqs.evt.status,
1156 pipe->reqs.evt.control,
1157 data, buf, len);
1158 memcpy(data, buf, len);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001159 xhci_xfer_normal(pipe, buf, len);
1160 return 0;
1161}