blob: dc54182927492416f76905f5a11647e5f9c85dae [file] [log] [blame]
Kevin O'Connor347f3632013-12-27 18:30:02 -05001#include "biosvar.h" // GET_LOWFLAT
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02002#include "config.h" // CONFIG_*
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02003#include "malloc.h" // memalign_low
Kevin O'Connor347f3632013-12-27 18:30:02 -05004#include "memmap.h" // PAGE_SIZE
5#include "output.h" // dprintf
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02006#include "pci.h" // pci_bdf_to_bus
Kevin O'Connorec443ff2013-12-05 18:43:20 -05007#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_XHCI
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02008#include "pci_regs.h" // PCI_BASE_ADDRESS_0
Kevin O'Connor347f3632013-12-27 18:30:02 -05009#include "string.h" // memcpy_fl
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020010#include "usb.h" // struct usb_s
11#include "usb-xhci.h" // struct ehci_qh
Kevin O'Connor347f3632013-12-27 18:30:02 -050012#include "util.h" // timer_calc
13#include "x86.h" // readl
Gerd Hoffmanne144bb72013-06-03 16:30:18 +020014
15// --------------------------------------------------------------
16// configuration
17
18#define XHCI_RING_ITEMS 16
19#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb))
20
21/*
22 * xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
23 * then we can get it from a trb pointer (provided by evt ring).
24 */
25#define XHCI_RING(_trb) \
26 ((struct xhci_ring*)((u32)(_trb) & ~(XHCI_RING_SIZE-1)))
27
28// --------------------------------------------------------------
29// bit definitions
30
31#define XHCI_CMD_RS (1<<0)
32#define XHCI_CMD_HCRST (1<<1)
33#define XHCI_CMD_INTE (1<<2)
34#define XHCI_CMD_HSEE (1<<3)
35#define XHCI_CMD_LHCRST (1<<7)
36#define XHCI_CMD_CSS (1<<8)
37#define XHCI_CMD_CRS (1<<9)
38#define XHCI_CMD_EWE (1<<10)
39#define XHCI_CMD_EU3S (1<<11)
40
41#define XHCI_STS_HCH (1<<0)
42#define XHCI_STS_HSE (1<<2)
43#define XHCI_STS_EINT (1<<3)
44#define XHCI_STS_PCD (1<<4)
45#define XHCI_STS_SSS (1<<8)
46#define XHCI_STS_RSS (1<<9)
47#define XHCI_STS_SRE (1<<10)
48#define XHCI_STS_CNR (1<<11)
49#define XHCI_STS_HCE (1<<12)
50
51#define XHCI_PORTSC_CCS (1<<0)
52#define XHCI_PORTSC_PED (1<<1)
53#define XHCI_PORTSC_OCA (1<<3)
54#define XHCI_PORTSC_PR (1<<4)
55#define XHCI_PORTSC_PLS_SHIFT 5
56#define XHCI_PORTSC_PLS_MASK 0xf
57#define XHCI_PORTSC_PP (1<<9)
58#define XHCI_PORTSC_SPEED_SHIFT 10
59#define XHCI_PORTSC_SPEED_MASK 0xf
60#define XHCI_PORTSC_SPEED_FULL (1<<10)
61#define XHCI_PORTSC_SPEED_LOW (2<<10)
62#define XHCI_PORTSC_SPEED_HIGH (3<<10)
63#define XHCI_PORTSC_SPEED_SUPER (4<<10)
64#define XHCI_PORTSC_PIC_SHIFT 14
65#define XHCI_PORTSC_PIC_MASK 0x3
66#define XHCI_PORTSC_LWS (1<<16)
67#define XHCI_PORTSC_CSC (1<<17)
68#define XHCI_PORTSC_PEC (1<<18)
69#define XHCI_PORTSC_WRC (1<<19)
70#define XHCI_PORTSC_OCC (1<<20)
71#define XHCI_PORTSC_PRC (1<<21)
72#define XHCI_PORTSC_PLC (1<<22)
73#define XHCI_PORTSC_CEC (1<<23)
74#define XHCI_PORTSC_CAS (1<<24)
75#define XHCI_PORTSC_WCE (1<<25)
76#define XHCI_PORTSC_WDE (1<<26)
77#define XHCI_PORTSC_WOE (1<<27)
78#define XHCI_PORTSC_DR (1<<30)
79#define XHCI_PORTSC_WPR (1<<31)
80
81#define TRB_C (1<<0)
82#define TRB_TYPE_SHIFT 10
83#define TRB_TYPE_MASK 0x3f
84#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
85
86#define TRB_EV_ED (1<<2)
87
88#define TRB_TR_ENT (1<<1)
89#define TRB_TR_ISP (1<<2)
90#define TRB_TR_NS (1<<3)
91#define TRB_TR_CH (1<<4)
92#define TRB_TR_IOC (1<<5)
93#define TRB_TR_IDT (1<<6)
94#define TRB_TR_TBC_SHIFT 7
95#define TRB_TR_TBC_MASK 0x3
96#define TRB_TR_BEI (1<<9)
97#define TRB_TR_TLBPC_SHIFT 16
98#define TRB_TR_TLBPC_MASK 0xf
99#define TRB_TR_FRAMEID_SHIFT 20
100#define TRB_TR_FRAMEID_MASK 0x7ff
101#define TRB_TR_SIA (1<<31)
102
103#define TRB_TR_DIR (1<<16)
104
105#define TRB_CR_SLOTID_SHIFT 24
106#define TRB_CR_SLOTID_MASK 0xff
107#define TRB_CR_EPID_SHIFT 16
108#define TRB_CR_EPID_MASK 0x1f
109
110#define TRB_CR_BSR (1<<9)
111#define TRB_CR_DC (1<<9)
112
113#define TRB_LK_TC (1<<1)
114
115#define TRB_INTR_SHIFT 22
116#define TRB_INTR_MASK 0x3ff
117#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)
118
119typedef enum TRBType {
120 TRB_RESERVED = 0,
121 TR_NORMAL,
122 TR_SETUP,
123 TR_DATA,
124 TR_STATUS,
125 TR_ISOCH,
126 TR_LINK,
127 TR_EVDATA,
128 TR_NOOP,
129 CR_ENABLE_SLOT,
130 CR_DISABLE_SLOT,
131 CR_ADDRESS_DEVICE,
132 CR_CONFIGURE_ENDPOINT,
133 CR_EVALUATE_CONTEXT,
134 CR_RESET_ENDPOINT,
135 CR_STOP_ENDPOINT,
136 CR_SET_TR_DEQUEUE,
137 CR_RESET_DEVICE,
138 CR_FORCE_EVENT,
139 CR_NEGOTIATE_BW,
140 CR_SET_LATENCY_TOLERANCE,
141 CR_GET_PORT_BANDWIDTH,
142 CR_FORCE_HEADER,
143 CR_NOOP,
144 ER_TRANSFER = 32,
145 ER_COMMAND_COMPLETE,
146 ER_PORT_STATUS_CHANGE,
147 ER_BANDWIDTH_REQUEST,
148 ER_DOORBELL,
149 ER_HOST_CONTROLLER,
150 ER_DEVICE_NOTIFICATION,
151 ER_MFINDEX_WRAP,
152} TRBType;
153
154typedef enum TRBCCode {
155 CC_INVALID = 0,
156 CC_SUCCESS,
157 CC_DATA_BUFFER_ERROR,
158 CC_BABBLE_DETECTED,
159 CC_USB_TRANSACTION_ERROR,
160 CC_TRB_ERROR,
161 CC_STALL_ERROR,
162 CC_RESOURCE_ERROR,
163 CC_BANDWIDTH_ERROR,
164 CC_NO_SLOTS_ERROR,
165 CC_INVALID_STREAM_TYPE_ERROR,
166 CC_SLOT_NOT_ENABLED_ERROR,
167 CC_EP_NOT_ENABLED_ERROR,
168 CC_SHORT_PACKET,
169 CC_RING_UNDERRUN,
170 CC_RING_OVERRUN,
171 CC_VF_ER_FULL,
172 CC_PARAMETER_ERROR,
173 CC_BANDWIDTH_OVERRUN,
174 CC_CONTEXT_STATE_ERROR,
175 CC_NO_PING_RESPONSE_ERROR,
176 CC_EVENT_RING_FULL_ERROR,
177 CC_INCOMPATIBLE_DEVICE_ERROR,
178 CC_MISSED_SERVICE_ERROR,
179 CC_COMMAND_RING_STOPPED,
180 CC_COMMAND_ABORTED,
181 CC_STOPPED,
182 CC_STOPPED_LENGTH_INVALID,
183 CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
184 CC_ISOCH_BUFFER_OVERRUN = 31,
185 CC_EVENT_LOST_ERROR,
186 CC_UNDEFINED_ERROR,
187 CC_INVALID_STREAM_ID_ERROR,
188 CC_SECONDARY_BANDWIDTH_ERROR,
189 CC_SPLIT_TRANSACTION_ERROR
190} TRBCCode;
191
192enum {
193 PLS_U0 = 0,
194 PLS_U1 = 1,
195 PLS_U2 = 2,
196 PLS_U3 = 3,
197 PLS_DISABLED = 4,
198 PLS_RX_DETECT = 5,
199 PLS_INACTIVE = 6,
200 PLS_POLLING = 7,
201 PLS_RECOVERY = 8,
202 PLS_HOT_RESET = 9,
203 PLS_COMPILANCE_MODE = 10,
204 PLS_TEST_MODE = 11,
205 PLS_RESUME = 15,
206};
207
208#define xhci_get_field(data, field) \
209 (((data) >> field##_SHIFT) & field##_MASK)
210
211// --------------------------------------------------------------
212// state structs
213
214struct xhci_ring {
215 struct xhci_trb ring[XHCI_RING_ITEMS];
216 struct xhci_trb evt;
217 u32 eidx;
218 u32 nidx;
219 u32 cs;
220 struct mutex_s lock;
221};
222
223struct usb_xhci_s {
224 struct usb_s usb;
225 struct usbhub_s hub;
226
227 /* devinfo */
228 u32 baseaddr;
229 u32 xcap;
230 u32 ports;
231 u32 slots;
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500232 u8 context64;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200233
234 /* xhci registers */
235 struct xhci_caps *caps;
236 struct xhci_op *op;
237 struct xhci_pr *pr;
238 struct xhci_ir *ir;
239 struct xhci_db *db;
240
241 /* xhci data structures */
242 struct xhci_devlist *devs;
243 struct xhci_ring *cmds;
244 struct xhci_ring *evts;
245 struct xhci_er_seg *eseg;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200246};
247
248struct xhci_pipe {
249 struct xhci_ring reqs;
250
251 struct usb_pipe pipe;
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500252 u32 slotid;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200253 u32 epid;
254 void *buf;
255 int bufused;
256};
257
258// --------------------------------------------------------------
259// tables
260
261static const char *speed_name[16] = {
262 [ 0 ] = " - ",
263 [ 1 ] = "Full",
264 [ 2 ] = "Low",
265 [ 3 ] = "High",
266 [ 4 ] = "Super",
267};
268
269static const int speed_from_xhci[16] = {
Paul Menzelf08e8472013-10-03 11:55:48 +0200270 [ 0 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200271 [ 1 ] = USB_FULLSPEED,
272 [ 2 ] = USB_LOWSPEED,
273 [ 3 ] = USB_HIGHSPEED,
274 [ 4 ] = USB_SUPERSPEED,
Paul Menzelf08e8472013-10-03 11:55:48 +0200275 [ 5 ... 15 ] = -1,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200276};
277
278static const int speed_to_xhci[] = {
279 [ USB_FULLSPEED ] = 1,
280 [ USB_LOWSPEED ] = 2,
281 [ USB_HIGHSPEED ] = 3,
282 [ USB_SUPERSPEED ] = 4,
283};
284
285static const int speed_to_ctlsize[] = {
286 [ USB_FULLSPEED ] = 8,
287 [ USB_LOWSPEED ] = 8,
288 [ USB_HIGHSPEED ] = 64,
289 [ USB_SUPERSPEED ] = 256,
290};
291
292static const int eptype_to_xhci_in[] = {
293 [ USB_ENDPOINT_XFER_CONTROL] = 4,
294 [ USB_ENDPOINT_XFER_ISOC ] = 5,
295 [ USB_ENDPOINT_XFER_BULK ] = 6,
296 [ USB_ENDPOINT_XFER_INT ] = 7,
297};
298
299static const int eptype_to_xhci_out[] = {
300 [ USB_ENDPOINT_XFER_CONTROL] = 4,
301 [ USB_ENDPOINT_XFER_ISOC ] = 1,
302 [ USB_ENDPOINT_XFER_BULK ] = 2,
303 [ USB_ENDPOINT_XFER_INT ] = 3,
304};
305
306// --------------------------------------------------------------
307// internal functions, 16bit + 32bit
308
309static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value)
310{
311 struct xhci_db *db = GET_LOWFLAT(xhci->db);
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500312 void *addr = &db[slotid].doorbell;
313 writel(addr, value);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200314}
315
316static void xhci_process_events(struct usb_xhci_s *xhci)
317{
318 struct xhci_ring *evts = GET_LOWFLAT(xhci->evts);
319
320 for (;;) {
321 /* check for event */
322 u32 nidx = GET_LOWFLAT(evts->nidx);
323 u32 cs = GET_LOWFLAT(evts->cs);
324 struct xhci_trb *etrb = evts->ring + nidx;
325 u32 control = GET_LOWFLAT(etrb->control);
326 if ((control & TRB_C) != (cs ? 1 : 0))
327 return;
328
329 /* process event */
330 u32 evt_type = TRB_TYPE(control);
331 u32 evt_cc = (GET_LOWFLAT(etrb->status) >> 24) & 0xff;
332 switch (evt_type) {
333 case ER_TRANSFER:
334 case ER_COMMAND_COMPLETE:
335 {
336 struct xhci_trb *rtrb = (void*)GET_LOWFLAT(etrb->ptr_low);
337 struct xhci_ring *ring = XHCI_RING(rtrb);
338 struct xhci_trb *evt = &ring->evt;
339 u32 eidx = rtrb - ring->ring + 1;
340 dprintf(5, "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n",
341 __func__, ring, rtrb, evt, evt_type, eidx, evt_cc);
342 memcpy_fl(evt, etrb, sizeof(*etrb));
343 SET_LOWFLAT(ring->eidx, eidx);
344 break;
345 }
346 case ER_PORT_STATUS_CHANGE:
347 {
348 u32 portid = (GET_LOWFLAT(etrb->ptr_low) >> 24) & 0xff;
349 dprintf(3, "%s: status change port #%d\n",
350 __func__, portid);
351 break;
352 }
353 default:
354 dprintf(1, "%s: unknown event, type %d, cc %d\n",
355 __func__, evt_type, evt_cc);
356 break;
357 }
358
359 /* move ring index, notify xhci */
360 nidx++;
361 if (nidx == XHCI_RING_ITEMS) {
362 nidx = 0;
363 cs = cs ? 0 : 1;
364 SET_LOWFLAT(evts->cs, cs);
365 }
366 SET_LOWFLAT(evts->nidx, nidx);
367 struct xhci_ir *ir = GET_LOWFLAT(xhci->ir);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200368 u32 erdp = (u32)(evts->ring + nidx);
Kevin O'Connorde30dad2013-12-30 22:09:04 -0500369 writel(&ir->erdp_low, erdp);
370 writel(&ir->erdp_high, 0);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200371 }
372}
373
374static int xhci_ring_busy(struct xhci_ring *ring)
375{
376 u32 eidx = GET_LOWFLAT(ring->eidx);
377 u32 nidx = GET_LOWFLAT(ring->nidx);
378 return (eidx != nidx);
379}
380
381static int xhci_event_wait(struct usb_xhci_s *xhci,
382 struct xhci_ring *ring,
383 u32 timeout)
384{
385 u32 end = timer_calc(timeout);
386
387 for (;;) {
388 xhci_process_events(xhci);
389 if (!xhci_ring_busy(ring)) {
390 u32 status = GET_LOWFLAT(ring->evt.status);
391 return (status >> 24) & 0xff;
392 }
393 if (timer_check(end)) {
394 warn_timeout();
395 return -1;
396 }
397 yield();
398 }
399}
400
401static void xhci_trb_queue(struct xhci_ring *ring,
402 struct xhci_trb *trb)
403{
404 u32 nidx = GET_LOWFLAT(ring->nidx);
405 u32 cs = GET_LOWFLAT(ring->cs);
406 struct xhci_trb *dst;
407 u32 control;
408
409 if (nidx == XHCI_RING_ITEMS-1) {
410 dst = ring->ring + nidx;
411 control = (TR_LINK << 10); // trb type
412 control |= TRB_LK_TC;
413 control |= (cs ? TRB_C : 0);
414 SET_LOWFLAT(dst->ptr_low, (u32)&ring[0]);
415 SET_LOWFLAT(dst->ptr_high, 0);
416 SET_LOWFLAT(dst->status, 0);
417 SET_LOWFLAT(dst->control, control);
418 nidx = 0;
419 cs = cs ? 0 : 1;
420 SET_LOWFLAT(ring->nidx, nidx);
421 SET_LOWFLAT(ring->cs, cs);
422
423 dprintf(5, "%s: ring %p [linked]\n", __func__, ring);
424 }
425
426 dst = ring->ring + nidx;
427 control = GET_LOWFLAT(trb->control) | (cs ? TRB_C : 0);
428
429 SET_LOWFLAT(dst->ptr_low, GET_LOWFLAT(trb->ptr_low));
430 SET_LOWFLAT(dst->ptr_high, GET_LOWFLAT(trb->ptr_high));
431 SET_LOWFLAT(dst->status, GET_LOWFLAT(trb->status));
432 SET_LOWFLAT(dst->control, control);
433 nidx++;
434 SET_LOWFLAT(ring->nidx, nidx);
435
436 dprintf(5, "%s: ring %p [nidx %d, len %d]\n",
437 __func__, ring, nidx,
438 GET_LOWFLAT(trb->status) & 0xffff);
439}
440
441static void xhci_xfer_queue(struct xhci_pipe *pipe,
442 struct xhci_trb *trb)
443{
444 xhci_trb_queue(&pipe->reqs, trb);
445}
446
447static void xhci_xfer_kick(struct xhci_pipe *pipe)
448{
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500449 struct usb_xhci_s *xhci = container_of(
450 GET_LOWFLAT(pipe->pipe.cntl), struct usb_xhci_s, usb);
451 u32 slotid = GET_LOWFLAT(pipe->slotid);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200452 u32 epid = GET_LOWFLAT(pipe->epid);
453
454 dprintf(5, "%s: ring %p, slotid %d, epid %d\n",
455 __func__, &pipe->reqs, slotid, epid);
456 xhci_doorbell(xhci, slotid, epid);
457}
458
459static void xhci_xfer_normal(struct xhci_pipe *pipe,
460 void *data, int datalen)
461{
462 struct xhci_trb trb;
463
464 memset(&trb, 0, sizeof(trb));
465 trb.ptr_low = (u32)data;
466 trb.status = datalen;
467 trb.control |= (TR_NORMAL << 10); // trb type
468 trb.control |= TRB_TR_IOC;
469
470 xhci_xfer_queue(pipe, MAKE_FLATPTR(GET_SEG(SS), &trb));
471 xhci_xfer_kick(pipe);
472}
473
474// --------------------------------------------------------------
475// internal functions, pure 32bit
476
477static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout)
478{
479 ASSERT32FLAT();
480 u32 end = timer_calc(timeout);
481
482 while ((readl(reg) & mask) != value) {
483 if (timer_check(end)) {
484 warn_timeout();
485 return -1;
486 }
487 yield();
488 }
489 return 0;
490}
491
492static int xhci_cmd_submit(struct usb_xhci_s *xhci,
493 struct xhci_trb *cmd)
494{
495 ASSERT32FLAT();
496 int rc;
497
498 mutex_lock(&xhci->cmds->lock);
499 xhci_trb_queue(xhci->cmds, cmd);
500 xhci_doorbell(xhci, 0, 0);
501 rc = xhci_event_wait(xhci, xhci->cmds, 1000);
502 mutex_unlock(&xhci->cmds->lock);
503 return rc;
504}
505
506static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci)
507{
508 ASSERT32FLAT();
509 struct xhci_trb cmd = {
510 .ptr_low = 0,
511 .ptr_high = 0,
512 .status = 0,
513 .control = (CR_ENABLE_SLOT << 10)
514 };
515 dprintf(3, "%s:\n", __func__);
516 int cc = xhci_cmd_submit(xhci, &cmd);
517 if (cc != CC_SUCCESS)
518 return -1;
519 return (xhci->cmds->evt.control >> 24) & 0xff;
520}
521
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500522#if 0
523static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200524{
525 ASSERT32FLAT();
526 struct xhci_trb cmd = {
527 .ptr_low = 0,
528 .ptr_high = 0,
529 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500530 .control = (slotid << 24) | (CR_DISABLE_SLOT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200531 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500532 dprintf(3, "%s: slotid %d\n", __func__, slotid);
533 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200534}
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500535#endif
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200536
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500537static int xhci_cmd_address_device(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500538 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200539{
540 ASSERT32FLAT();
541 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500542 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200543 .ptr_high = 0,
544 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500545 .control = (slotid << 24) | (CR_ADDRESS_DEVICE << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200546 };
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500547 dprintf(3, "%s: slotid %d\n", __func__, slotid);
548 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200549}
550
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500551static int xhci_cmd_configure_endpoint(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500552 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200553{
554 ASSERT32FLAT();
555 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500556 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200557 .ptr_high = 0,
558 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500559 .control = (slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200560 };
561 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500562 slotid, inctx->add, inctx->del);
563 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200564}
565
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500566static int xhci_cmd_evaluate_context(struct usb_xhci_s *xhci, u32 slotid
Kevin O'Connord477d552013-12-27 18:09:16 -0500567 , struct xhci_inctx *inctx)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200568{
569 ASSERT32FLAT();
570 struct xhci_trb cmd = {
Kevin O'Connord477d552013-12-27 18:09:16 -0500571 .ptr_low = (u32)inctx,
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200572 .ptr_high = 0,
573 .status = 0,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500574 .control = (slotid << 24) | (CR_EVALUATE_CONTEXT << 10)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200575 };
576 dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500577 slotid, inctx->add, inctx->del);
578 return xhci_cmd_submit(xhci, &cmd);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200579}
580
581static void xhci_xfer_setup(struct xhci_pipe *pipe,
582 const struct usb_ctrlrequest *req,
583 int dir, int datalen)
584{
585 ASSERT32FLAT();
586 struct xhci_trb trb;
587
588 memset(&trb, 0, sizeof(trb));
589 trb.ptr_low |= req->bRequestType;
590 trb.ptr_low |= (req->bRequest) << 8;
591 trb.ptr_low |= (req->wValue) << 16;
592 trb.ptr_high |= req->wIndex;
593 trb.ptr_high |= (req->wLength) << 16;
594 trb.status |= 8; // length
595 trb.control |= (TR_SETUP << 10); // trb type
596 trb.control |= TRB_TR_IDT;
597 if (datalen)
598 trb.control |= (dir ? 3 : 2) << 16; // transfer type
599 xhci_xfer_queue(pipe, &trb);
600}
601
602static void xhci_xfer_data(struct xhci_pipe *pipe,
603 int dir, void *data, int datalen)
604{
605 ASSERT32FLAT();
606 struct xhci_trb trb;
607
608 memset(&trb, 0, sizeof(trb));
609 trb.ptr_low = (u32)data;
610 trb.status = datalen;
611 trb.control |= (TR_DATA << 10); // trb type
612 if (dir)
613 trb.control |= (1 << 16);
614 xhci_xfer_queue(pipe, &trb);
615}
616
Kevin O'Connor1b830fe2013-12-27 13:41:28 -0500617static void xhci_xfer_status(struct xhci_pipe *pipe, int dir, int datalen)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200618{
619 ASSERT32FLAT();
620 struct xhci_trb trb;
621
622 memset(&trb, 0, sizeof(trb));
623 trb.control |= (TR_STATUS << 10); // trb type
624 trb.control |= TRB_TR_IOC;
Kevin O'Connor1b830fe2013-12-27 13:41:28 -0500625 if (!datalen || !dir)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200626 trb.control |= (1 << 16);
627
628 xhci_xfer_queue(pipe, &trb);
629 xhci_xfer_kick(pipe);
630}
631
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200632static void
633configure_xhci(void *data)
634{
635 ASSERT32FLAT();
636 struct usb_xhci_s *xhci = data;
637 u32 reg;
638
639 xhci->devs = memalign_high(64, sizeof(*xhci->devs) * (xhci->slots + 1));
640 xhci->eseg = memalign_high(64, sizeof(*xhci->eseg));
641 xhci->cmds = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->cmds));
642 xhci->evts = memalign_low(XHCI_RING_SIZE, sizeof(*xhci->evts));
643 if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) {
644 warn_noalloc();
645 goto fail;
646 }
647 memset(xhci->devs, 0, sizeof(*xhci->devs) * (xhci->slots + 1));
648 memset(xhci->cmds, 0, sizeof(*xhci->cmds));
649 memset(xhci->evts, 0, sizeof(*xhci->evts));
650 memset(xhci->eseg, 0, sizeof(*xhci->eseg));
651
652 reg = readl(&xhci->op->usbcmd);
653 if (reg & XHCI_CMD_RS) {
654 reg &= ~XHCI_CMD_RS;
655 writel(&xhci->op->usbcmd, reg);
656 if (wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32) != 0)
657 goto fail;
658 }
659
660 dprintf(3, "%s: resetting\n", __func__);
661 writel(&xhci->op->usbcmd, XHCI_CMD_HCRST);
662 if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0)
663 goto fail;
664 if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0)
665 goto fail;
666
667 writel(&xhci->op->config, xhci->slots);
668 writel(&xhci->op->dcbaap_low, (u32)xhci->devs);
669 writel(&xhci->op->dcbaap_high, 0);
670 writel(&xhci->op->crcr_low, (u32)xhci->cmds | 1);
671 writel(&xhci->op->crcr_high, 0);
672 xhci->cmds->cs = 1;
673
674 xhci->eseg->ptr_low = (u32)xhci->evts;
675 xhci->eseg->ptr_high = 0;
676 xhci->eseg->size = XHCI_RING_ITEMS;
677 writel(&xhci->ir->erstsz, 1);
678 writel(&xhci->ir->erdp_low, (u32)xhci->evts);
679 writel(&xhci->ir->erdp_high, 0);
680 writel(&xhci->ir->erstba_low, (u32)xhci->eseg);
681 writel(&xhci->ir->erstba_high, 0);
682 xhci->evts->cs = 1;
683
Gerd Hoffmannd42b7952013-12-06 16:08:01 +0100684 reg = readl(&xhci->caps->hcsparams2);
685 u32 spb = reg >> 27;
686 if (spb) {
687 dprintf(3, "%s: setup %d scratch pad buffers\n", __func__, spb);
688 u64 *spba = memalign_high(64, sizeof(*spba) * spb);
Kevin O'Connor347f3632013-12-27 18:30:02 -0500689 void *pad = memalign_high(PAGE_SIZE, PAGE_SIZE * spb);
Gerd Hoffmannd42b7952013-12-06 16:08:01 +0100690 int i;
691 for (i = 0; i < spb; i++)
Kevin O'Connor347f3632013-12-27 18:30:02 -0500692 spba[i] = (u32)pad + (i * PAGE_SIZE);
Gerd Hoffmannd42b7952013-12-06 16:08:01 +0100693 xhci->devs[0].ptr_low = (u32)spba;
694 xhci->devs[0].ptr_high = 0;
695 }
696
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200697 reg = readl(&xhci->op->usbcmd);
698 reg |= XHCI_CMD_RS;
699 writel(&xhci->op->usbcmd, reg);
700
701 // FIXME: try find a more elegant way than a fixed delay
702 mdelay(100);
703
704 usb_enumerate(&xhci->hub);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500705 // XXX - should walk list of pipes and free unused pipes.
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200706 if (xhci->hub.devcount)
707 return;
708
709 // No devices found - shutdown and free controller.
710 dprintf(1, "XHCI no devices found\n");
711 reg = readl(&xhci->op->usbcmd);
712 reg &= ~XHCI_CMD_RS;
713 writel(&xhci->op->usbcmd, reg);
714 wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32);
715
716fail:
717 free(xhci->eseg);
718 free(xhci->evts);
719 free(xhci->cmds);
720 free(xhci->devs);
721 free(xhci);
722}
723
724// --------------------------------------------------------------
725// xhci root hub
726
727// Check if device attached to port
728static void
729xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc)
730{
731 ASSERT32FLAT();
732 u32 pls = xhci_get_field(portsc, XHCI_PORTSC_PLS);
733 u32 speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED);
734
735 dprintf(loglevel, "%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n",
736 prefix, port + 1, portsc,
737 (portsc & XHCI_PORTSC_PP) ? " powered," : "",
738 (portsc & XHCI_PORTSC_PED) ? " enabled," : "",
739 pls, speed, speed_name[speed]);
740}
741
742static int
743xhci_hub_detect(struct usbhub_s *hub, u32 port)
744{
745 ASSERT32FLAT();
746 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
747 u32 portsc = readl(&xhci->pr[port].portsc);
748
749 xhci_print_port_state(3, __func__, port, portsc);
750 switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) {
751 case PLS_U0:
752 case PLS_POLLING:
753 return 0;
754 default:
755 return -1;
756 }
757}
758
759// Reset device on port
760static int
761xhci_hub_reset(struct usbhub_s *hub, u32 port)
762{
763 ASSERT32FLAT();
764 struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
765 u32 portsc = readl(&xhci->pr[port].portsc);
766 int rc;
767
768 switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) {
769 case PLS_U0:
770 rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)];
771 break;
772 case PLS_POLLING:
773 xhci_print_port_state(3, __func__, port, portsc);
774 portsc |= XHCI_PORTSC_PR;
775 writel(&xhci->pr[port].portsc, portsc);
776 if (wait_bit(&xhci->pr[port].portsc, XHCI_PORTSC_PED, XHCI_PORTSC_PED, 100) != 0)
777 return -1;
778 portsc = readl(&xhci->pr[port].portsc);
779 rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)];
780 break;
781 default:
782 rc = -1;
783 break;
784 }
785
786 xhci_print_port_state(1, "XHCI", port, portsc);
787 return rc;
788}
789
790static void
791xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
792{
793 ASSERT32FLAT();
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500794 // XXX - should turn the port power off.
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200795}
796
797static struct usbhub_op_s xhci_hub_ops = {
798 .detect = xhci_hub_detect,
799 .reset = xhci_hub_reset,
800 .disconnect = xhci_hub_disconnect,
801};
802
803// --------------------------------------------------------------
804// external interface
805
Kevin O'Connord477d552013-12-27 18:09:16 -0500806
807static struct xhci_inctx *
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500808xhci_alloc_inctx(struct usbdevice_s *usbdev)
Kevin O'Connord477d552013-12-27 18:09:16 -0500809{
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500810 struct usb_xhci_s *xhci = container_of(
811 usbdev->hub->cntl, struct usb_xhci_s, usb);
812 int size = (sizeof(struct xhci_inctx) * 33) << xhci->context64;
813 struct xhci_inctx *in = memalign_tmphigh(2048 << xhci->context64, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500814 if (!in) {
815 warn_noalloc();
816 return NULL;
817 }
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500818 memset(in, 0, size);
Kevin O'Connord477d552013-12-27 18:09:16 -0500819
Kevin O'Connord477d552013-12-27 18:09:16 -0500820 in->add = 0x01;
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500821 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
822 slot->ctx[0] |= (1 << 27); // context entries
823 slot->ctx[0] |= speed_to_xhci[usbdev->speed] << 20;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500824
825 // Set high-speed hub flags.
826 struct usbdevice_s *hubdev = usbdev->hub->usbdev;
827 if (hubdev) {
828 if (usbdev->speed == USB_LOWSPEED || usbdev->speed == USB_FULLSPEED) {
829 struct xhci_pipe *hpipe = container_of(
830 hubdev->defpipe, struct xhci_pipe, pipe);
831 if (hubdev->speed == USB_HIGHSPEED) {
832 slot->ctx[2] |= hpipe->slotid;
833 slot->ctx[2] |= (usbdev->port+1) << 8;
834 } else {
835 struct xhci_slotctx *hslot = (void*)xhci->devs[hpipe->slotid].ptr_low;
836 slot->ctx[2] = hslot->ctx[2];
837 }
838 }
839 u32 route = 0;
840 while (usbdev->hub->usbdev) {
841 route <<= 4;
842 route |= (usbdev->port+1) & 0xf;
843 usbdev = usbdev->hub->usbdev;
844 }
845 slot->ctx[0] |= route;
846 }
847
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500848 slot->ctx[1] |= (usbdev->port+1) << 16;
Kevin O'Connor1540f922013-12-29 20:18:37 -0500849
Kevin O'Connord477d552013-12-27 18:09:16 -0500850 return in;
851}
852
Kevin O'Connor1540f922013-12-29 20:18:37 -0500853static int xhci_config_hub(struct usbhub_s *hub)
854{
855 struct usb_xhci_s *xhci = container_of(
856 hub->cntl, struct usb_xhci_s, usb);
857 struct xhci_pipe *pipe = container_of(
858 hub->usbdev->defpipe, struct xhci_pipe, pipe);
859 struct xhci_slotctx *hdslot = (void*)xhci->devs[pipe->slotid].ptr_low;
860 if ((hdslot->ctx[3] >> 27) == 3)
861 // Already configured
862 return 0;
863 struct xhci_inctx *in = xhci_alloc_inctx(hub->usbdev);
864 if (!in)
865 return -1;
866 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
867 slot->ctx[0] |= 1 << 26;
868 slot->ctx[1] |= hub->portcount << 24;
869
870 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
871 free(in);
872 if (cc != CC_SUCCESS) {
873 dprintf(1, "%s: configure hub: failed (cc %d)\n", __func__, cc);
874 return -1;
875 }
876 return 0;
877}
878
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200879struct usb_pipe *
880xhci_alloc_pipe(struct usbdevice_s *usbdev
881 , struct usb_endpoint_descriptor *epdesc)
882{
883 ASSERT32FLAT();
884 if (!CONFIG_USB_XHCI)
885 return NULL;
886 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
887 struct usb_xhci_s *xhci = container_of(
888 usbdev->hub->cntl, struct usb_xhci_s, usb);
889 struct xhci_pipe *pipe;
890 u32 epid;
891
892 if (epdesc->bEndpointAddress == 0) {
893 epid = 1;
894 } else {
895 epid = (epdesc->bEndpointAddress & 0x0f) * 2;
896 epid += (epdesc->bEndpointAddress & USB_DIR_IN) ? 1 : 0;
897 }
898
899 if (eptype == USB_ENDPOINT_XFER_CONTROL)
900 pipe = memalign_high(XHCI_RING_SIZE, sizeof(*pipe));
901 else
902 pipe = memalign_low(XHCI_RING_SIZE, sizeof(*pipe));
903 if (!pipe) {
904 warn_noalloc();
905 return NULL;
906 }
907 memset(pipe, 0, sizeof(*pipe));
908
909 usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200910 pipe->epid = epid;
911 pipe->reqs.cs = 1;
912 if (eptype == USB_ENDPOINT_XFER_INT)
913 pipe->buf = malloc_low(pipe->pipe.maxpacket);
914
915 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500916 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500917 if (pipe->epid == 1) {
Kevin O'Connor1540f922013-12-29 20:18:37 -0500918 if (usbdev->hub->usbdev) {
919 // Make sure parent hub is configured.
920 int ret = xhci_config_hub(usbdev->hub);
921 if (ret)
922 goto fail;
923 }
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500924 // Enable slot and send set_address command.
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500925 u32 size = (sizeof(struct xhci_slotctx) * 32) << xhci->context64;
926 struct xhci_slotctx *dev = memalign_high(1024 << xhci->context64, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500927 if (!dev) {
928 warn_noalloc();
929 goto fail;
930 }
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500931 int slotid = xhci_cmd_enable_slot(xhci);
932 if (slotid < 0) {
933 dprintf(1, "%s: enable slot: failed\n", __func__);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500934 free(dev);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500935 goto fail;
936 }
937 dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500938
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500939 memset(dev, 0, size);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500940 pipe->slotid = usbdev->slotid = slotid;
941 xhci->devs[slotid].ptr_low = (u32)dev;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500942 xhci->devs[slotid].ptr_high = 0;
943
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500944 struct xhci_inctx *in = xhci_alloc_inctx(usbdev);
945 if (!in)
946 goto fail;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500947 in->add |= (1 << 1);
948
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500949 struct xhci_epctx *ep = (void*)&in[2 << xhci->context64];
950 ep->ctx[0] |= (3 << 16); // interval: 1ms
951 ep->ctx[1] |= (4 << 3); // control pipe
952 ep->ctx[1] |= (speed_to_ctlsize[usbdev->speed] << 16);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500953
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500954 ep->deq_low = (u32)&pipe->reqs.ring[0];
955 ep->deq_low |= 1; // dcs
956 ep->deq_high = 0;
957 ep->length = 8;
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500958
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500959 int cc = xhci_cmd_address_device(xhci, slotid, in);
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -0500960 free(in);
961 if (cc != CC_SUCCESS) {
962 dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc);
963 goto fail;
964 }
965 } else {
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500966 struct xhci_inctx *in = xhci_alloc_inctx(usbdev);
Kevin O'Connord477d552013-12-27 18:09:16 -0500967 if (!in)
968 goto fail;
969 in->add |= (1 << pipe->epid);
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500970 struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64];
Kevin O'Connor81b64822013-12-29 18:17:57 -0500971 slot->ctx[0] = (slot->ctx[0] & ~0xf8000000) | (pipe->epid << 27);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200972
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500973 struct xhci_epctx *ep = (void*)&in[(pipe->epid+1) << xhci->context64];
Kevin O'Connorb6a40652013-12-27 13:37:11 -0500974 if (eptype == USB_ENDPOINT_XFER_INT)
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500975 ep->ctx[0] = (usb_getFrameExp(usbdev, epdesc) + 3) << 16;
976 ep->ctx[1] |= (eptype << 3);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200977 if (epdesc->bEndpointAddress & USB_DIR_IN)
Kevin O'Connor20aeae72013-12-27 21:46:35 -0500978 ep->ctx[1] |= (1 << 5);
979 ep->ctx[1] |= (pipe->pipe.maxpacket << 16);
980 ep->deq_low = (u32)&pipe->reqs.ring[0];
981 ep->deq_low |= 1; // dcs
982 ep->deq_high = 0;
983 ep->length = pipe->pipe.maxpacket;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200984
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -0500985 pipe->slotid = usbdev->slotid;
986 int cc = xhci_cmd_configure_endpoint(xhci, pipe->slotid, in);
Kevin O'Connord477d552013-12-27 18:09:16 -0500987 free(in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200988 if (cc != CC_SUCCESS) {
989 dprintf(1, "%s: configure endpoint: failed (cc %d)\n", __func__, cc);
Kevin O'Connord477d552013-12-27 18:09:16 -0500990 goto fail;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200991 }
992 }
993
994 return &pipe->pipe;
Kevin O'Connord477d552013-12-27 18:09:16 -0500995fail:
996 free(pipe);
997 return NULL;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +0200998}
999
1000struct usb_pipe *
1001xhci_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe
1002 , struct usb_endpoint_descriptor *epdesc)
1003{
1004 ASSERT32FLAT();
1005 if (!CONFIG_USB_XHCI)
1006 return NULL;
1007 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
1008 struct xhci_pipe *pipe = container_of(upipe, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001009 struct usb_xhci_s *xhci = container_of(
1010 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001011 dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__,
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001012 usbdev, &pipe->reqs, pipe->slotid, pipe->epid);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001013 if (eptype == USB_ENDPOINT_XFER_CONTROL &&
1014 pipe->pipe.maxpacket != epdesc->wMaxPacketSize) {
1015 dprintf(1, "%s: reconf ctl endpoint pkt size: %d -> %d\n",
1016 __func__, pipe->pipe.maxpacket, epdesc->wMaxPacketSize);
1017 pipe->pipe.maxpacket = epdesc->wMaxPacketSize;
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001018 struct xhci_inctx *in = xhci_alloc_inctx(usbdev);
Kevin O'Connord477d552013-12-27 18:09:16 -05001019 if (!in)
1020 return upipe;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001021 in->add = (1 << 1);
Kevin O'Connor20aeae72013-12-27 21:46:35 -05001022 struct xhci_epctx *ep = (void*)&in[2 << xhci->context64];
1023 ep->ctx[1] |= (pipe->pipe.maxpacket << 16);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001024 int cc = xhci_cmd_evaluate_context(xhci, pipe->slotid, in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001025 if (cc != CC_SUCCESS) {
1026 dprintf(1, "%s: reconf ctl endpoint: failed (cc %d)\n",
1027 __func__, cc);
1028 }
Kevin O'Connord477d552013-12-27 18:09:16 -05001029 free(in);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001030 }
1031 return upipe;
1032}
1033
1034int
1035xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
1036 , void *data, int datalen)
1037{
1038 ASSERT32FLAT();
1039 if (!CONFIG_USB_XHCI)
1040 return -1;
1041 const struct usb_ctrlrequest *req = cmd;
1042 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001043 struct usb_xhci_s *xhci = container_of(
1044 pipe->pipe.cntl, struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001045
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -05001046 if (req->bRequest == USB_REQ_SET_ADDRESS)
1047 // Set address command sent during xhci_alloc_pipe.
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001048 return 0;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001049
1050 xhci_xfer_setup(pipe, req, dir, datalen);
1051 if (datalen)
1052 xhci_xfer_data(pipe, dir, data, datalen);
Kevin O'Connor1b830fe2013-12-27 13:41:28 -05001053 xhci_xfer_status(pipe, dir, datalen);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001054
Kevin O'Connor4ea2fa92013-12-27 19:25:46 -05001055 int cc = xhci_event_wait(xhci, &pipe->reqs, 1000);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001056 if (cc != CC_SUCCESS) {
1057 dprintf(1, "%s: control xfer failed (cc %d)\n", __func__, cc);
1058 return -1;
1059 }
1060
1061 return 0;
1062}
1063
Kevin O'Connorde30dad2013-12-30 22:09:04 -05001064int VISIBLE32FLAT
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001065xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datalen)
1066{
1067 if (!CONFIG_USB_XHCI)
1068 return -1;
1069
1070 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001071 struct usb_xhci_s *xhci = container_of(
1072 GET_LOWFLAT(pipe->pipe.cntl), struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001073
1074 xhci_xfer_normal(pipe, data, datalen);
1075 int cc = xhci_event_wait(xhci, &pipe->reqs, 1000);
1076 if (cc != CC_SUCCESS) {
1077 dprintf(1, "%s: bulk xfer failed (cc %d)\n", __func__, cc);
1078 return -1;
1079 }
1080 return 0;
1081}
1082
Kevin O'Connorde30dad2013-12-30 22:09:04 -05001083int VISIBLE32FLAT
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001084xhci_poll_intr(struct usb_pipe *p, void *data)
1085{
1086 if (!CONFIG_USB_XHCI)
1087 return -1;
1088
1089 struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe);
Kevin O'Connor81ee3bb2013-12-27 21:09:53 -05001090 struct usb_xhci_s *xhci = container_of(
1091 GET_LOWFLAT(pipe->pipe.cntl), struct usb_xhci_s, usb);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001092 u32 len = GET_LOWFLAT(pipe->pipe.maxpacket);
1093 void *buf = GET_LOWFLAT(pipe->buf);
1094 int bufused = GET_LOWFLAT(pipe->bufused);
1095
1096 if (!bufused) {
1097 xhci_xfer_normal(pipe, buf, len);
1098 bufused = 1;
1099 SET_LOWFLAT(pipe->bufused, bufused);
1100 return -1;
1101 }
1102
1103 xhci_process_events(xhci);
1104 if (xhci_ring_busy(&pipe->reqs))
1105 return -1;
1106 dprintf(5, "%s: st %x ct %x [ %p <= %p / %d ]\n", __func__,
1107 GET_LOWFLAT(pipe->reqs.evt.status),
1108 GET_LOWFLAT(pipe->reqs.evt.control),
1109 MAKE_FLATPTR(GET_SEG(SS), data), buf, len);
1110 memcpy_fl(MAKE_FLATPTR(GET_SEG(SS), data), buf, len);
1111 xhci_xfer_normal(pipe, buf, len);
1112 return 0;
1113}
1114
Kevin O'Connorec443ff2013-12-05 18:43:20 -05001115static void
1116xhci_controller_setup(struct pci_device *pci)
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001117{
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001118 struct usb_xhci_s *xhci = malloc_low(sizeof(*xhci));
1119 if (!xhci) {
1120 warn_noalloc();
Kevin O'Connorec443ff2013-12-05 18:43:20 -05001121 return;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001122 }
1123 memset(xhci, 0, sizeof(*xhci));
1124
Kevin O'Connorec443ff2013-12-05 18:43:20 -05001125 wait_preempt(); // Avoid pci_config_readl when preempting
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001126 xhci->baseaddr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
1127 & PCI_BASE_ADDRESS_MEM_MASK;
1128 xhci->caps = (void*)(xhci->baseaddr);
1129 xhci->op = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength));
1130 xhci->pr = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength) + 0x400);
1131 xhci->db = (void*)(xhci->baseaddr + readl(&xhci->caps->dboff));
1132 xhci->ir = (void*)(xhci->baseaddr + readl(&xhci->caps->rtsoff) + 0x20);
1133
1134 u32 hcs1 = readl(&xhci->caps->hcsparams1);
1135 u32 hcc = readl(&xhci->caps->hccparams);
1136 xhci->ports = (hcs1 >> 24) & 0xff;
1137 xhci->slots = hcs1 & 0xff;
1138 xhci->xcap = ((hcc >> 16) & 0xffff) << 2;
Kevin O'Connor20aeae72013-12-27 21:46:35 -05001139 xhci->context64 = (hcc & 0x04) ? 1 : 0;
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001140
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001141 xhci->usb.pci = pci;
1142 xhci->usb.type = USB_TYPE_XHCI;
1143 xhci->hub.cntl = &xhci->usb;
1144 xhci->hub.portcount = xhci->ports;
1145 xhci->hub.op = &xhci_hub_ops;
1146
Kevin O'Connor20aeae72013-12-27 21:46:35 -05001147 dprintf(1, "XHCI init on dev %02x:%02x.%x: regs @ %p, %d ports, %d slots"
1148 ", %d byte contexts\n"
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001149 , pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf)
1150 , pci_bdf_to_fn(pci->bdf), xhci->caps
Kevin O'Connor20aeae72013-12-27 21:46:35 -05001151 , xhci->ports, xhci->slots, xhci->context64 ? 64 : 32);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001152
1153 if (xhci->xcap) {
1154 u32 off, addr = xhci->baseaddr + xhci->xcap;
1155 do {
1156 struct xhci_xcap *xcap = (void*)addr;
1157 u32 ports, name, cap = readl(&xcap->cap);
1158 switch (cap & 0xff) {
1159 case 0x02:
1160 name = readl(&xcap->data[0]);
1161 ports = readl(&xcap->data[1]);
Kevin O'Connor6ba9df02013-12-29 13:13:42 -05001162 dprintf(1, "XHCI protocol %c%c%c%c %x.%02x"
1163 ", %d ports (offset %d), def %x\n"
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001164 , (name >> 0) & 0xff
1165 , (name >> 8) & 0xff
1166 , (name >> 16) & 0xff
1167 , (name >> 24) & 0xff
1168 , (cap >> 24) & 0xff
1169 , (cap >> 16) & 0xff
1170 , (ports >> 8) & 0xff
Kevin O'Connor6ba9df02013-12-29 13:13:42 -05001171 , (ports >> 0) & 0xff
1172 , ports >> 16);
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001173 break;
1174 default:
1175 dprintf(1, "XHCI extcap 0x%x @ %x\n", cap & 0xff, addr);
1176 break;
1177 }
1178 off = (cap >> 8) & 0xff;
1179 addr += off << 2;
1180 } while (off > 0);
1181 }
1182
Kevin O'Connor347f3632013-12-27 18:30:02 -05001183 u32 pagesize = readl(&xhci->op->pagesize);
1184 if (PAGE_SIZE != (pagesize<<12)) {
1185 dprintf(1, "XHCI driver does not support page size code %d\n"
1186 , pagesize<<12);
1187 free(xhci);
1188 return;
1189 }
1190
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001191 pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
1192
1193 run_thread(configure_xhci, xhci);
Kevin O'Connorec443ff2013-12-05 18:43:20 -05001194}
1195
1196void
1197xhci_setup(void)
1198{
1199 if (! CONFIG_USB_XHCI)
1200 return;
1201 struct pci_device *pci;
1202 foreachpci(pci) {
1203 if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI)
1204 xhci_controller_setup(pci);
1205 }
Gerd Hoffmanne144bb72013-06-03 16:30:18 +02001206}