blob: 69954b9d8d7f7a7681c3b288c5ca937d960713d7 [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
Kevin O'Connor4d8510c2016-02-03 01:28:20 -050012#include "pcidevice.h" // foreachpci
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 */
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200233 u32 xcap;
234 u32 ports;
235 u32 slots;
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500236 u8 context64;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200237
238 /* xhci registers */
239 struct xhci_caps *caps;
240 struct xhci_op *op;
241 struct xhci_pr *pr;
242 struct xhci_ir *ir;
243 struct xhci_db *db;
244
245 /* xhci data structures */
246 struct xhci_devlist *devs;
247 struct xhci_ring *cmds;
248 struct xhci_ring *evts;
249 struct xhci_er_seg *eseg;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200250};
251
252struct xhci_pipe {
253 struct xhci_ring reqs;
254
255 struct usb_pipe pipe;
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500256 u32 slotid;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200257 u32 epid;
258 void *buf;
259 int bufused;
260};
261
262// --------------------------------------------------------------
263// tables
264
265static const char *speed_name[16] = {
266 [ 0 ] = " - ",
267 [ 1 ] = "Full",
268 [ 2 ] = "Low",
269 [ 3 ] = "High",
270 [ 4 ] = "Super",
271};
272
273static const int speed_from_xhci[16] = {
Paul Menzelf08e8472013-10-03 11:55:48 +0200274 [ 0 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200275 [ 1 ] = USB_FULLSPEED,
276 [ 2 ] = USB_LOWSPEED,
277 [ 3 ] = USB_HIGHSPEED,
278 [ 4 ] = USB_SUPERSPEED,
Paul Menzelf08e8472013-10-03 11:55:48 +0200279 [ 5 ... 15 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200280};
281
282static const int speed_to_xhci[] = {
283 [ USB_FULLSPEED ] = 1,
284 [ USB_LOWSPEED ] = 2,
285 [ USB_HIGHSPEED ] = 3,
286 [ USB_SUPERSPEED ] = 4,
287};
288
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400289static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout)
290{
291 u32 end = timer_calc(timeout);
292
293 while ((readl(reg) & mask) != value) {
294 if (timer_check(end)) {
295 warn_timeout();
296 return -1;
297 }
298 yield();
299 }
300 return 0;
301}
302
303
304/****************************************************************
305 * Root hub
306 ****************************************************************/
307
Kevin O'Connor0f681302014-09-10 11:33:01 -0400308#define XHCI_TIME_POSTPOWER 20
309
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400310// Check if device attached to port
311static void
312xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc)
313{
314 u32 pls = xhci_get_field(portsc, XHCI_PORTSC_PLS);
315 u32 speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED);
316
317 dprintf(loglevel, "%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n",
318 prefix, port + 1, portsc,
319 (portsc & XHCI_PORTSC_PP) ? " powered," : "",
320 (portsc & XHCI_PORTSC_PED) ? " enabled," : "",
321 pls, speed, speed_name[speed]);
322}
323
324static int
325xhci_hub_detect(struct usbhub_s *hub, u32 port)
326{
327 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
328 u32 portsc = readl(&xhci->pr[port].portsc);
Kevin O'Connor0f681302014-09-10 11:33:01 -0400329 return (portsc & XHCI_PORTSC_CCS) ? 1 : 0;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400330}
331
332// Reset device on port
333static int
334xhci_hub_reset(struct usbhub_s *hub, u32 port)
335{
336 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
337 u32 portsc = readl(&xhci->pr[port].portsc);
Kevin O'Connoraa34e4e2015-11-10 08:50:52 -0500338 if (!(portsc & XHCI_PORTSC_CCS))
339 // Device no longer connected?!
340 return -1;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400341
342 switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) {
343 case PLS_U0:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500344 // A USB3 port - controller automatically performs reset
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400345 break;
346 case PLS_POLLING:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500347 // A USB2 port - perform device reset
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400348 xhci_print_port_state(3, __func__, port, portsc);
Kevin O'Connoraa34e4e2015-11-10 08:50:52 -0500349 writel(&xhci->pr[port].portsc, portsc | XHCI_PORTSC_PR);
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400350 break;
351 default:
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500352 return -1;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400353 }
354
Kevin O'Connorc01b41c2015-12-13 14:49:41 -0500355 // Wait for device to complete reset and be enabled
356 u32 end = timer_calc(100);
357 for (;;) {
358 portsc = readl(&xhci->pr[port].portsc);
359 if (!(portsc & XHCI_PORTSC_CCS))
360 // Device disconnected during reset
361 return -1;
362 if (portsc & XHCI_PORTSC_PED)
363 // Reset complete
364 break;
365 if (timer_check(end)) {
366 warn_timeout();
367 return -1;
368 }
369 yield();
370 }
371
372 int rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)];
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400373 xhci_print_port_state(1, "XHCI", port, portsc);
374 return rc;
375}
376
377static void
378xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
379{
380 // XXX - should turn the port power off.
381}
382
383static struct usbhub_op_s xhci_hub_ops = {
384 .detect = xhci_hub_detect,
385 .reset = xhci_hub_reset,
386 .disconnect = xhci_hub_disconnect,
387};
388
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400389// Find any devices connected to the root hub.
390static int
391xhci_check_ports(struct usb_xhci_s *xhci)
392{
Kevin O'Connor0f681302014-09-10 11:33:01 -0400393 // Wait for port power to stabilize.
394 msleep(XHCI_TIME_POSTPOWER);
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400395
396 struct usbhub_s hub;
397 memset(&hub, 0, sizeof(hub));
398 hub.cntl = &xhci->usb;
399 hub.portcount = xhci->ports;
400 hub.op = &xhci_hub_ops;
401 usb_enumerate(&hub);
402 return hub.devcount;
403}
404
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400405
406/****************************************************************
407 * Setup
408 ****************************************************************/
409
410static void
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400411xhci_free_pipes(struct usb_xhci_s *xhci)
412{
413 // XXX - should walk list of pipes and free unused pipes.
414}
415
416static void
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400417configure_xhci(void *data)
418{
419 struct usb_xhci_s *xhci = data;
420 u32 reg;
421
422 xhci->devs = memalign_high(64, sizeof(*xhci->devs) * (xhci->slots + 1));
423 xhci->eseg = memalign_high(64, sizeof(*xhci->eseg));
424 xhci->cmds = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->cmds));
425 xhci->evts = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->evts));
426 if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) {
427 warn_noalloc();
428 goto fail;
429 }
430 memset(xhci->devs, 0, sizeof(*xhci->devs) * (xhci->slots + 1));
431 memset(xhci->cmds, 0, sizeof(*xhci->cmds));
432 memset(xhci->evts, 0, sizeof(*xhci->evts));
433 memset(xhci->eseg, 0, sizeof(*xhci->eseg));
434
435 reg = readl(&xhci->op->usbcmd);
436 if (reg & XHCI_CMD_RS) {
437 reg &= ~XHCI_CMD_RS;
438 writel(&xhci->op->usbcmd, reg);
439 if (wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32) != 0)
440 goto fail;
441 }
442
443 dprintf(3, "%s: resetting\n", __func__);
444 writel(&xhci->op->usbcmd, XHCI_CMD_HCRST);
445 if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0)
446 goto fail;
447 if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0)
448 goto fail;
449
450 writel(&xhci->op->config, xhci->slots);
451 writel(&xhci->op->dcbaap_low, (u32)xhci->devs);
452 writel(&xhci->op->dcbaap_high, 0);
453 writel(&xhci->op->crcr_low, (u32)xhci->cmds | 1);
454 writel(&xhci->op->crcr_high, 0);
455 xhci->cmds->cs = 1;
456
457 xhci->eseg->ptr_low = (u32)xhci->evts;
458 xhci->eseg->ptr_high = 0;
459 xhci->eseg->size = XHCI_RING_ITEMS;
460 writel(&xhci->ir->erstsz, 1);
461 writel(&xhci->ir->erdp_low, (u32)xhci->evts);
462 writel(&xhci->ir->erdp_high, 0);
463 writel(&xhci->ir->erstba_low, (u32)xhci->eseg);
464 writel(&xhci->ir->erstba_high, 0);
465 xhci->evts->cs = 1;
466
467 reg = readl(&xhci->caps->hcsparams2);
Julius Wernerfd318e42015-08-07 20:07:12 -0700468 u32 spb = (reg >> 21 & 0x1f) << 5 | reg >> 27;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400469 if (spb) {
470 dprintf(3, "%s: setup %d scratch pad buffers\n", __func__, spb);
471 u64 *spba = memalign_high(64, sizeof(*spba) * spb);
472 void *pad = memalign_high(PAGE_SIZE, PAGE_SIZE * spb);
473 if (!spba || !pad) {
474 warn_noalloc();
475 free(spba);
476 free(pad);
477 goto fail;
478 }
479 int i;
480 for (i = 0; i < spb; i++)
481 spba[i] = (u32)pad + (i * PAGE_SIZE);
482 xhci->devs[0].ptr_low = (u32)spba;
483 xhci->devs[0].ptr_high = 0;
484 }
485
486 reg = readl(&xhci->op->usbcmd);
487 reg |= XHCI_CMD_RS;
488 writel(&xhci->op->usbcmd, reg);
489
Kevin O'Connor7fb82b72014-09-10 09:10:42 -0400490 // Find devices
491 int count = xhci_check_ports(xhci);
492 xhci_free_pipes(xhci);
493 if (count)
494 // Success
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400495 return;
496
497 // No devices found - shutdown and free controller.
498 dprintf(1, "XHCI no devices found\n");
499 reg = readl(&xhci->op->usbcmd);
500 reg &= ~XHCI_CMD_RS;
501 writel(&xhci->op->usbcmd, reg);
502 wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32);
503
504fail:
505 free(xhci->eseg);
506 free(xhci->evts);
507 free(xhci->cmds);
508 free(xhci->devs);
509 free(xhci);
510}
511
512static void
513xhci_controller_setup(struct pci_device *pci)
514{
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500515 void *baseaddr = pci_enable_membar(pci, PCI_BASE_ADDRESS_0);
516 if (!baseaddr)
517 return;
518
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400519 struct usb_xhci_s *xhci = malloc_high(sizeof(*xhci));
520 if (!xhci) {
521 warn_noalloc();
522 return;
523 }
524 memset(xhci, 0, sizeof(*xhci));
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500525 xhci->caps = baseaddr;
526 xhci->op = baseaddr + readb(&xhci->caps->caplength);
527 xhci->pr = baseaddr + readb(&xhci->caps->caplength) + 0x400;
528 xhci->db = baseaddr + readl(&xhci->caps->dboff);
529 xhci->ir = baseaddr + readl(&xhci->caps->rtsoff) + 0x20;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400530
531 u32 hcs1 = readl(&xhci->caps->hcsparams1);
532 u32 hcc = readl(&xhci->caps->hccparams);
533 xhci->ports = (hcs1 >> 24) & 0xff;
534 xhci->slots = hcs1 & 0xff;
535 xhci->xcap = ((hcc >> 16) & 0xffff) << 2;
536 xhci->context64 = (hcc & 0x04) ? 1 : 0;
537
538 xhci->usb.pci = pci;
539 xhci->usb.type = USB_TYPE_XHCI;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400540
Kevin O'Connor7b673002016-02-03 03:03:15 -0500541 dprintf(1, "XHCI init on dev %pP: regs @ %p, %d ports, %d slots"
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400542 ", %d byte contexts\n"
Kevin O'Connor7b673002016-02-03 03:03:15 -0500543 , pci, xhci->caps, xhci->ports, xhci->slots
544 , xhci->context64 ? 64 : 32);
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400545
546 if (xhci->xcap) {
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500547 u32 off;
548 void *addr = baseaddr + xhci->xcap;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400549 do {
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500550 struct xhci_xcap *xcap = addr;
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400551 u32 ports, name, cap = readl(&xcap->cap);
552 switch (cap & 0xff) {
553 case 0x02:
554 name = readl(&xcap->data[0]);
555 ports = readl(&xcap->data[1]);
556 dprintf(1, "XHCI protocol %c%c%c%c %x.%02x"
557 ", %d ports (offset %d), def %x\n"
558 , (name >> 0) & 0xff
559 , (name >> 8) & 0xff
560 , (name >> 16) & 0xff
561 , (name >> 24) & 0xff
562 , (cap >> 24) & 0xff
563 , (cap >> 16) & 0xff
564 , (ports >> 8) & 0xff
565 , (ports >> 0) & 0xff
566 , ports >> 16);
567 break;
568 default:
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500569 dprintf(1, "XHCI extcap 0x%x @ %p\n", cap & 0xff, addr);
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400570 break;
571 }
572 off = (cap >> 8) & 0xff;
573 addr += off << 2;
574 } while (off > 0);
575 }
576
577 u32 pagesize = readl(&xhci->op->pagesize);
578 if (PAGE_SIZE != (pagesize<<12)) {
579 dprintf(1, "XHCI driver does not support page size code %d\n"
580 , pagesize<<12);
581 free(xhci);
582 return;
583 }
584
Kevin O'Connorc53953a2016-02-02 22:33:17 -0500585 pci_enable_busmaster(pci);
Kevin O'Connora76a4e12014-09-10 08:51:50 -0400586
587 run_thread(configure_xhci, xhci);
588}
589
590void
591xhci_setup(void)
592{
593 if (! CONFIG_USB_XHCI)
594 return;
595 struct pci_device *pci;
596 foreachpci(pci) {
597 if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI)
598 xhci_controller_setup(pci);
599 }
600}
601
602
603/****************************************************************
604 * End point communication
605 ****************************************************************/
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200606
607static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value)
608{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400609 struct xhci_db *db = xhci->db;
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500610 void *addr = &db[slotid].doorbell;
611 writel(addr, value);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200612}
613
614static void xhci_process_events(struct usb_xhci_s *xhci)
615{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400616 struct xhci_ring *evts = xhci->evts;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200617
618 for (;;) {
619 /* check for event */
Kevin O'Connorb2030132014-09-10 08:31:28 -0400620 u32 nidx = evts->nidx;
621 u32 cs = evts->cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200622 struct xhci_trb *etrb = evts->ring + nidx;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400623 u32 control = etrb->control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200624 if ((control & TRB_C) != (cs ? 1 : 0))
625 return;
626
627 /* process event */
628 u32 evt_type = TRB_TYPE(control);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400629 u32 evt_cc = (etrb->status >> 24) & 0xff;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200630 switch (evt_type) {
631 case ER_TRANSFER:
632 case ER_COMMAND_COMPLETE:
633 {
Kevin O'Connorb2030132014-09-10 08:31:28 -0400634 struct xhci_trb *rtrb = (void*)etrb->ptr_low;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200635 struct xhci_ring *ring = XHCI_RING(rtrb);
636 struct xhci_trb *evt = &ring->evt;
637 u32 eidx = rtrb - ring->ring + 1;
638 dprintf(5, "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n",
639 __func__, ring, rtrb, evt, evt_type, eidx, evt_cc);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400640 memcpy(evt, etrb, sizeof(*etrb));
641 ring->eidx = eidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200642 break;
643 }
644 case ER_PORT_STATUS_CHANGE:
645 {
Kevin O'Connor49fb0342015-12-18 12:56:33 -0500646 u32 port = ((etrb->ptr_low >> 24) & 0xff) - 1;
647 // Read status, and clear port status change bits
648 u32 portsc = readl(&xhci->pr[port].portsc);
649 u32 pclear = (((portsc & ~(XHCI_PORTSC_PED|XHCI_PORTSC_PR))
650 & ~(XHCI_PORTSC_PLS_MASK<<XHCI_PORTSC_PLS_SHIFT))
651 | (1<<XHCI_PORTSC_PLS_SHIFT));
652 writel(&xhci->pr[port].portsc, pclear);
653
654 xhci_print_port_state(3, __func__, port, portsc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200655 break;
656 }
657 default:
658 dprintf(1, "%s: unknown event, type %d, cc %d\n",
659 __func__, evt_type, evt_cc);
660 break;
661 }
662
663 /* move ring index, notify xhci */
664 nidx++;
665 if (nidx == XHCI_RING_ITEMS) {
666 nidx = 0;
667 cs = cs ? 0 : 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400668 evts->cs = cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200669 }
Kevin O'Connorb2030132014-09-10 08:31:28 -0400670 evts->nidx = nidx;
671 struct xhci_ir *ir = xhci->ir;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200672 u32 erdp = (u32)(evts->ring + nidx);
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500673 writel(&ir->erdp_low, erdp);
674 writel(&ir->erdp_high, 0);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200675 }
676}
677
678static int xhci_ring_busy(struct xhci_ring *ring)
679{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400680 u32 eidx = ring->eidx;
681 u32 nidx = ring->nidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200682 return (eidx != nidx);
683}
684
685static int xhci_event_wait(struct usb_xhci_s *xhci,
686 struct xhci_ring *ring,
687 u32 timeout)
688{
689 u32 end = timer_calc(timeout);
690
691 for (;;) {
692 xhci_process_events(xhci);
693 if (!xhci_ring_busy(ring)) {
Kevin O'Connorb2030132014-09-10 08:31:28 -0400694 u32 status = ring->evt.status;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200695 return (status >> 24) & 0xff;
696 }
697 if (timer_check(end)) {
698 warn_timeout();
699 return -1;
700 }
701 yield();
702 }
703}
704
705static void xhci_trb_queue(struct xhci_ring *ring,
706 struct xhci_trb *trb)
707{
Kevin O'Connorb2030132014-09-10 08:31:28 -0400708 u32 nidx = ring->nidx;
709 u32 cs = ring->cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200710 struct xhci_trb *dst;
711 u32 control;
712
713 if (nidx == XHCI_RING_ITEMS-1) {
714 dst = ring->ring + nidx;
715 control = (TR_LINK << 10); // trb type
716 control |= TRB_LK_TC;
717 control |= (cs ? TRB_C : 0);
Kevin O'Connorb2030132014-09-10 08:31:28 -0400718 dst->ptr_low = (u32)&ring[0];
719 dst->ptr_high = 0;
720 dst->status = 0;
721 dst->control = control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200722 nidx = 0;
723 cs = cs ? 0 : 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400724 ring->nidx = nidx;
725 ring->cs = cs;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200726
727 dprintf(5, "%s: ring %p [linked]\n", __func__, ring);
728 }
729
730 dst = ring->ring + nidx;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400731 control = trb->control | (cs ? TRB_C : 0);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200732
Kevin O'Connorb2030132014-09-10 08:31:28 -0400733 dst->ptr_low = trb->ptr_low;
734 dst->ptr_high = trb->ptr_high;
735 dst->status = trb->status;
736 dst->control = control;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200737 nidx++;
Kevin O'Connorb2030132014-09-10 08:31:28 -0400738 ring->nidx = nidx;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200739
740 dprintf(5, "%s: ring %p [nidx %d, len %d]\n",
741 __func__, ring, nidx,
Kevin O'Connorb2030132014-09-10 08:31:28 -0400742 trb->status & 0xffff);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200743}
744
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200745static int xhci_cmd_submit(struct usb_xhci_s *xhci,
746 struct xhci_trb *cmd)
747{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200748 int rc;
749
750 mutex_lock(&xhci->cmds->lock);
751 xhci_trb_queue(xhci->cmds, cmd);
752 xhci_doorbell(xhci, 0, 0);
753 rc = xhci_event_wait(xhci, xhci->cmds, 1000);
754 mutex_unlock(&xhci->cmds->lock);
755 return rc;
756}
757
758static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci)
759{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200760 struct xhci_trb cmd = {
761 .ptr_low = 0,
762 .ptr_high = 0,
763 .status = 0,
764 .control = (CR_ENABLE_SLOT << 10)
765 };
766 dprintf(3, "%s:\n", __func__);
767 int cc = xhci_cmd_submit(xhci, &cmd);
768 if (cc != CC_SUCCESS)
769 return -1;
770 return (xhci->cmds->evt.control >> 24) & 0xff;
771}
772
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500773static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200774{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200775 struct xhci_trb cmd = {
776 .ptr_low = 0,
777 .ptr_high = 0,
778 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500779 .control = (slotid << 24) | (CR_DISABLE_SLOT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200780 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500781 dprintf(3, "%s: slotid %d\n", __func__, slotid);
782 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200783}
784
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500785static int xhci_cmd_address_device(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500786 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200787{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200788 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500789 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200790 .ptr_high = 0,
791 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500792 .control = (slotid << 24) | (CR_ADDRESS_DEVICE << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200793 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500794 dprintf(3, "%s: slotid %d\n", __func__, slotid);
795 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200796}
797
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500798static int xhci_cmd_configure_endpoint(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500799 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200800{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200801 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500802 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200803 .ptr_high = 0,
804 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500805 .control = (slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200806 };
807 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500808 slotid, inctx->add, inctx->del);
809 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200810}
811
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500812static int xhci_cmd_evaluate_context(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500813 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200814{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200815 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500816 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200817 .ptr_high = 0,
818 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500819 .control = (slotid << 24) | (CR_EVALUATE_CONTEXT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200820 };
821 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500822 slotid, inctx->add, inctx->del);
823 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200824}
825
Kevin O'Connord477d552013-12-27 18:09:16 -0500826static struct xhci_inctx *
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500827xhci_alloc_inctx(struct usbdevice_s *usbdev, int maxepid)
Kevin O'Connord477d552013-12-27 18:09:16 -0500828{
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500829 struct usb_xhci_s *xhci = container_of(
830 usbdev->hub->cntl, struct usb_xhci_s, usb);
831 int size = (sizeof(struct xhci_inctx) * 33) << xhci->context64;
832 struct xhci_inctx *in = memalign_tmphigh(2048 << xhci->context64, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500833 if (!in) {
834 warn_noalloc();
835 return NULL;
836 }
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500837 memset(in, 0, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500838
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500839 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500840 slot->ctx[0] |= maxepid << 27; // context entries
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500841 slot->ctx[0] |= speed_to_xhci[usbdev->speed] << 20;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500842
843 // Set high-speed hub flags.
844 struct usbdevice_s *hubdev = usbdev->hub->usbdev;
845 if (hubdev) {
846 if (usbdev->speed == USB_LOWSPEED || usbdev->speed == USB_FULLSPEED) {
847 struct xhci_pipe *hpipe = container_of(
848 hubdev->defpipe, struct xhci_pipe, pipe);
849 if (hubdev->speed == USB_HIGHSPEED) {
850 slot->ctx[2] |= hpipe->slotid;
851 slot->ctx[2] |= (usbdev->port+1) << 8;
852 } else {
853 struct xhci_slotctx *hslot = (void*)xhci->devs[hpipe->slotid].ptr_low;
854 slot->ctx[2] = hslot->ctx[2];
855 }
856 }
857 u32 route = 0;
858 while (usbdev->hub->usbdev) {
859 route <<= 4;
860 route |= (usbdev->port+1) & 0xf;
861 usbdev = usbdev->hub->usbdev;
862 }
863 slot->ctx[0] |= route;
864 }
865
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500866 slot->ctx[1] |= (usbdev->port+1) << 16;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500867
Kevin O'Connord477d552013-12-27 18:09:16 -0500868 return in;
869}
870
Kevin O'Connor1540f922013-12-29 20:18:37 -0500871static int xhci_config_hub(struct usbhub_s *hub)
872{
873 struct usb_xhci_s *xhci = container_of(
874 hub->cntl, struct usb_xhci_s, usb);
875 struct xhci_pipe *pipe = container_of(
876 hub->usbdev->defpipe, struct xhci_pipe, pipe);
877 struct xhci_slotctx *hdslot = (void*)xhci->devs[pipe->slotid].ptr_low;
878 if ((hdslot->ctx[3] >> 27) == 3)
879 // Already configured
880 return 0;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500881 struct xhci_inctx *in = xhci_alloc_inctx(hub->usbdev, 1);
Kevin O'Connor1540f922013-12-29 20:18:37 -0500882 if (!in)
883 return -1;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500884 in->add = 0x01;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500885 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
886 slot->ctx[0] |= 1 << 26;
887 slot->ctx[1] |= hub->portcount << 24;
888
889 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
890 free(in);
891 if (cc != CC_SUCCESS) {
892 dprintf(1, "%s: configure hub: failed (cc %d)\n", __func__, cc);
893 return -1;
894 }
895 return 0;
896}
897
Kevin O'Connorc427def2014-10-16 13:23:08 -0400898static struct usb_pipe *
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200899xhci_alloc_pipe(struct usbdevice_s *usbdev
900 , struct usb_endpoint_descriptor *epdesc)
901{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200902 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
903 struct usb_xhci_s *xhci = container_of(
904 usbdev->hub->cntl, struct usb_xhci_s, usb);
905 struct xhci_pipe *pipe;
906 u32 epid;
907
908 if (epdesc->bEndpointAddress == 0) {
909 epid = 1;
910 } else {
911 epid = (epdesc->bEndpointAddress & 0x0f) * 2;
912 epid += (epdesc->bEndpointAddress & USB_DIR_IN) ? 1 : 0;
913 }
914
915 if (eptype == USB_ENDPOINT_XFER_CONTROL)
916 pipe = memalign_high(XHCI_RING_SIZE, sizeof(*pipe));
917 else
918 pipe = memalign_low(XHCI_RING_SIZE, sizeof(*pipe));
919 if (!pipe) {
920 warn_noalloc();
921 return NULL;
922 }
923 memset(pipe, 0, sizeof(*pipe));
924
925 usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200926 pipe->epid = epid;
927 pipe->reqs.cs = 1;
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -0400928 if (eptype == USB_ENDPOINT_XFER_INT) {
Kevin O'Connorc46f5a92014-09-10 09:31:43 -0400929 pipe->buf = malloc_high(pipe->pipe.maxpacket);
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -0400930 if (!pipe->buf) {
931 warn_noalloc();
932 free(pipe);
933 return NULL;
934 }
935 }
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200936
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500937 // Allocate input context and initialize endpoint info.
938 struct xhci_inctx *in = xhci_alloc_inctx(usbdev, epid);
939 if (!in)
940 goto fail;
941 in->add = 0x01 | (1 << epid);
942 struct xhci_epctx *ep = (void*)&in[(pipe->epid+1) << xhci->context64];
943 if (eptype == USB_ENDPOINT_XFER_INT)
Kevin O'Connor98cdad32014-10-16 12:05:09 -0400944 ep->ctx[0] = (usb_get_period(usbdev, epdesc) + 3) << 16;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500945 ep->ctx[1] |= eptype << 3;
946 if (epdesc->bEndpointAddress & USB_DIR_IN
947 || eptype == USB_ENDPOINT_XFER_CONTROL)
948 ep->ctx[1] |= 1 << 5;
949 ep->ctx[1] |= pipe->pipe.maxpacket << 16;
950 ep->deq_low = (u32)&pipe->reqs.ring[0];
951 ep->deq_low |= 1; // dcs
952 ep->length = pipe->pipe.maxpacket;
953
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200954 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500955 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500956 if (pipe->epid == 1) {
Kevin O'Connor1540f922013-12-29 20:18:37 -0500957 if (usbdev->hub->usbdev) {
958 // Make sure parent hub is configured.
959 int ret = xhci_config_hub(usbdev->hub);
960 if (ret)
961 goto fail;
962 }
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500963 // Enable slot.
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500964 u32 size = (sizeof(struct xhci_slotctx) * 32) << xhci->context64;
965 struct xhci_slotctx *dev = memalign_high(1024 << xhci->context64, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500966 if (!dev) {
967 warn_noalloc();
968 goto fail;
969 }
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500970 int slotid = xhci_cmd_enable_slot(xhci);
971 if (slotid < 0) {
972 dprintf(1, "%s: enable slot: failed\n", __func__);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500973 free(dev);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500974 goto fail;
975 }
976 dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid);
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500977 memset(dev, 0, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500978 xhci->devs[slotid].ptr_low = (u32)dev;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500979 xhci->devs[slotid].ptr_high = 0;
980
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500981 // Send set_address command.
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500982 int cc = xhci_cmd_address_device(xhci, slotid, in);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500983 if (cc != CC_SUCCESS) {
984 dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc);
Kevin O'Connor636cbb42015-12-20 15:50:10 -0500985 cc = xhci_cmd_disable_slot(xhci, slotid);
986 if (cc != CC_SUCCESS) {
987 dprintf(1, "%s: disable failed (cc %d)\n", __func__, cc);
988 goto fail;
989 }
990 xhci->devs[slotid].ptr_low = 0;
991 free(dev);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500992 goto fail;
993 }
Kevin O'Connor3c577a72016-01-05 13:41:09 -0500994 pipe->slotid = slotid;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500995 } else {
Kevin O'Connor3c577a72016-01-05 13:41:09 -0500996 struct xhci_pipe *defpipe = container_of(
997 usbdev->defpipe, struct xhci_pipe, pipe);
998 pipe->slotid = defpipe->slotid;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -0500999 // Send configure command.
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001000 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001001 if (cc != CC_SUCCESS) {
1002 dprintf(1, "%s: configure endpoint: failed (cc %d)\n", __func__, cc);
Kevin O'Connord477d552013-12-27 18:09:16 -05001003 goto fail;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001004 }
1005 }
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001006 free(in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001007 return &pipe->pipe;
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001008
Kevin O'Connord477d552013-12-27 18:09:16 -05001009fail:
Kevin O'Connor3abdc7c2015-06-30 11:10:41 -04001010 free(pipe->buf);
Kevin O'Connord477d552013-12-27 18:09:16 -05001011 free(pipe);
Kevin O'Connor5c6fa332014-01-27 11:49:51 -05001012 free(in);
Kevin O'Connord477d552013-12-27 18:09:16 -05001013 return NULL;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001014}
1015
1016struct usb_pipe *
Kevin O'Connorc427def2014-10-16 13:23:08 -04001017xhci_realloc_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe
1018 , struct usb_endpoint_descriptor *epdesc)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001019{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001020 if (!CONFIG_USB_XHCI)
1021 return NULL;
Kevin O'Connorc427def2014-10-16 13:23:08 -04001022 if (!epdesc) {
1023 usb_add_freelist(upipe);
1024 return NULL;
1025 }
1026 if (!upipe)
1027 return xhci_alloc_pipe(usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001028 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001029 int oldmaxpacket = upipe->maxpacket;
1030 usb_desc2pipe(upipe, usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001031 struct xhci_pipe *pipe = container_of(upipe, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001032 struct usb_xhci_s *xhci = container_of(
1033 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001034 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001035 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001036 if (eptype != USB_ENDPOINT_XFER_CONTROL || upipe->maxpacket == oldmaxpacket)
1037 return upipe;
1038
1039 // maxpacket has changed on control endpoint - update controller.
1040 dprintf(1, "%s: reconf ctl endpoint pkt size: %d -> %d\n",
1041 __func__, oldmaxpacket, pipe->pipe.maxpacket);
1042 struct xhci_inctx *in = xhci_alloc_inctx(usbdev, 1);
1043 if (!in)
1044 return upipe;
1045 in->add = (1 << 1);
1046 struct xhci_epctx *ep = (void*)&in[2 << xhci->context64];
1047 ep->ctx[1] |= (pipe->pipe.maxpacket << 16);
1048 int cc = xhci_cmd_evaluate_context(xhci, pipe->slotid, in);
1049 if (cc != CC_SUCCESS) {
1050 dprintf(1, "%s: reconf ctl endpoint: failed (cc %d)\n",
1051 __func__, cc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001052 }
Kevin O'Connorab8ef4a2014-09-09 19:31:45 -04001053 free(in);
1054
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001055 return upipe;
1056}
1057
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001058static void xhci_xfer_queue(struct xhci_pipe *pipe,
Kevin O'Connor65034a42014-12-31 11:05:39 -05001059 void *data, int datalen, u32 flags)
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001060{
Kevin O'Connor65034a42014-12-31 11:05:39 -05001061 struct xhci_trb trb;
1062 memset(&trb, 0, sizeof(trb));
1063 if (flags & TRB_TR_IDT)
1064 memcpy(&trb.ptr_low, data, datalen);
1065 else
1066 trb.ptr_low = (u32)data;
1067 trb.status = datalen;
1068 trb.control = flags;
1069 xhci_trb_queue(&pipe->reqs, &trb);
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001070}
1071
1072static void xhci_xfer_kick(struct xhci_pipe *pipe)
1073{
1074 struct usb_xhci_s *xhci = container_of(
1075 pipe->pipe.cntl, struct usb_xhci_s, usb);
1076 u32 slotid = pipe->slotid;
1077 u32 epid = pipe->epid;
1078
1079 dprintf(5, "%s: ring %p, slotid %d, epid %d\n",
1080 __func__, &pipe->reqs, slotid, epid);
1081 xhci_doorbell(xhci, slotid, epid);
1082}
1083
1084static void xhci_xfer_normal(struct xhci_pipe *pipe,
1085 void *data, int datalen)
1086{
Kevin O'Connor65034a42014-12-31 11:05:39 -05001087 xhci_xfer_queue(pipe, data, datalen, (TR_NORMAL << 10) | TRB_TR_IOC);
Kevin O'Connor2ba89072014-12-31 02:25:58 -05001088 xhci_xfer_kick(pipe);
1089}
1090
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001091int
Kevin O'Connor2891a832014-12-31 17:41:14 -05001092xhci_send_pipe(struct usb_pipe *p, int dir, const void *cmd
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001093 , void *data, int datalen)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001094{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001095 if (!CONFIG_USB_XHCI)
1096 return -1;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001097 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001098 struct usb_xhci_s *xhci = container_of(
1099 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001100
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001101 if (cmd) {
1102 const struct usb_ctrlrequest *req = cmd;
1103 if (req->bRequest == USB_REQ_SET_ADDRESS)
1104 // Set address command sent during xhci_alloc_pipe.
1105 return 0;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001106
Kevin O'Connor2891a832014-12-31 17:41:14 -05001107 xhci_xfer_queue(pipe, (void*)req, USB_CONTROL_SETUP_SIZE
1108 , (TR_SETUP << 10) | TRB_TR_IDT
Kevin O'Connor65034a42014-12-31 11:05:39 -05001109 | ((datalen ? (dir ? 3 : 2) : 0) << 16));
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001110 if (datalen)
Kevin O'Connor65034a42014-12-31 11:05:39 -05001111 xhci_xfer_queue(pipe, data, datalen, (TR_DATA << 10)
1112 | ((dir ? 1 : 0) << 16));
1113 xhci_xfer_queue(pipe, NULL, 0, (TR_STATUS << 10) | TRB_TR_IOC
1114 | ((dir ? 0 : 1) << 16));
1115 xhci_xfer_kick(pipe);
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001116 } else {
1117 xhci_xfer_normal(pipe, data, datalen);
1118 }
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001119
Kevin O'Connor88fa2272014-06-14 12:25:17 -04001120 int cc = xhci_event_wait(xhci, &pipe->reqs, usb_xfer_time(p, datalen));
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001121 if (cc != CC_SUCCESS) {
Kevin O'Connorb33e31d2014-12-31 02:07:37 -05001122 dprintf(1, "%s: xfer failed (cc %d)\n", __func__, cc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001123 return -1;
1124 }
1125
1126 return 0;
1127}
1128
Kevin O'Connorde30dad2013-12-30 22:09:04 -05001129int VISIBLE32FLAT
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001130xhci_poll_intr(struct usb_pipe *p, void *data)
1131{
1132 if (!CONFIG_USB_XHCI)
1133 return -1;
1134
1135 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001136 struct usb_xhci_s *xhci = container_of(
Kevin O'Connorb2030132014-09-10 08:31:28 -04001137 pipe->pipe.cntl, struct usb_xhci_s, usb);
1138 u32 len = pipe->pipe.maxpacket;
1139 void *buf = pipe->buf;
1140 int bufused = pipe->bufused;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001141
1142 if (!bufused) {
1143 xhci_xfer_normal(pipe, buf, len);
1144 bufused = 1;
Kevin O'Connorb2030132014-09-10 08:31:28 -04001145 pipe->bufused = bufused;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001146 return -1;
1147 }
1148
1149 xhci_process_events(xhci);
1150 if (xhci_ring_busy(&pipe->reqs))
1151 return -1;
1152 dprintf(5, "%s: st %x ct %x [ %p <= %p / %d ]\n", __func__,
Kevin O'Connorb2030132014-09-10 08:31:28 -04001153 pipe->reqs.evt.status,
1154 pipe->reqs.evt.control,
1155 data, buf, len);
1156 memcpy(data, buf, len);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001157 xhci_xfer_normal(pipe, buf, len);
1158 return 0;
1159}