diff options
author | Liangfeng Wu <wulf@rock-chips.com> | 2016-05-24 19:40:46 +0800 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2016-06-12 12:09:55 +0200 |
commit | 8c7e416309a253e1ee2d46de254583e5f09c1329 (patch) | |
tree | 9893a082421b9e647b3e96f004d68137ce6ea72f | |
parent | 2030d257d19920904ad370509404145c18627fac (diff) |
libpayload: usb: xhci: Support rockchip xHCI controller
1. Make the xHCI driver to support xHCI controller v1.1
2. And a new function xhci_ring_doorbell(), it aims to
add a memory barrier before ringing the doorbell, to ensure
all TRB changes are written to memory.
BRANCH=none
BUG=chrome-os-partner:52684
TEST=boot from USB on Kevin rk3399 platform
Change-Id: Ife1070d1265476d0f5b88e2acf3299fc84af5832
Signed-off-by: Martin Roth <martinroth@chromium.org>
Original-Commit-Id: 0c21e92
Original-Change-Id: I4e38e04dc3c7d32ee4bb424a473c70956a3c3ea9
Original-Signed-off-by: Liangfeng Wu <wulf@rock-chips.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/346831
Original-Commit-Ready: Brian Norris <briannorris@chromium.org>
Original-Tested-by: Douglas Anderson <dianders@chromium.org>
Original-Reviewed-by: Douglas Anderson <dianders@chromium.org>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/15111
Tested-by: build bot (Jenkins)
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
-rw-r--r-- | payloads/libpayload/drivers/usb/xhci.c | 19 | ||||
-rw-r--r-- | payloads/libpayload/drivers/usb/xhci_private.h | 2 |
2 files changed, 15 insertions, 6 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c index d223d0f190..2e70316ac7 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -197,7 +197,7 @@ xhci_init (unsigned long physical_bar) xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n", xhci->capreg->hciver_hi, xhci->capreg->hciver_lo); if ((xhci->capreg->hciversion < 0x96) || - (xhci->capreg->hciversion > 0x100)) { + (xhci->capreg->hciversion > 0x110)) { xhci_debug("Unsupported xHCI version\n"); goto _free_xhci; } @@ -534,6 +534,15 @@ xhci_enqueue_trb(transfer_ring_t *const tr) } static void +xhci_ring_doorbell(endpoint_t *const ep) +{ + /* Ensure all TRB changes are written to memory. */ + wmb(); + XHCI_INST(ep->dev->controller)->dbreg[ep->dev->address] = + xhci_ep_id(ep); +} + +static void xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps, const int dalen, void *const data, const int dir) { @@ -670,7 +679,7 @@ xhci_control(usbdev_t *const dev, const direction_t dir, xhci_enqueue_trb(tr); /* Ring doorbell for EP0 */ - xhci->dbreg[dev->address] = 1; + xhci_ring_doorbell(&dev->endpoints[0]); /* Wait for transfer events */ int i, transferred = 0; @@ -745,7 +754,7 @@ xhci_bulk(endpoint_t *const ep, const int size, u8 *const src, const unsigned mps = EC_GET(MPS, epctx); const unsigned dir = (ep->direction == OUT) ? TRB_DIR_OUT : TRB_DIR_IN; xhci_enqueue_td(tr, ep_id, mps, size, data, dir); - xhci->dbreg[ep->dev->address] = ep_id; + xhci_ring_doorbell(ep); /* Wait for transfer event */ const int ret = xhci_wait_for_transfer(xhci, ep->dev->address, ep_id); @@ -852,7 +861,7 @@ xhci_create_intr_queue(endpoint_t *const ep, and ring the doorbell. */ for (i = 0; i < (reqcount - 1); ++i) xhci_enqueue_trb(tr); - xhci->dbreg[slot_id] = ep_id; + xhci_ring_doorbell(ep); return intrq; @@ -930,7 +939,7 @@ xhci_poll_intr_queue(void *const q) /* Enqueue the last (spare) TRB and ring doorbell */ xhci_enqueue_trb(tr); - xhci->dbreg[ep->dev->address] = ep_id; + xhci_ring_doorbell(ep); /* Reuse the current buffer for the next spare TRB */ xhci_clear_trb(tr->cur, tr->pcs); diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h index f64442579d..47a464f4e2 100644 --- a/payloads/libpayload/drivers/usb/xhci_private.h +++ b/payloads/libpayload/drivers/usb/xhci_private.h @@ -515,7 +515,7 @@ int xhci_cmd_stop_endpoint(xhci_t *, int slot_id, int ep); int xhci_cmd_set_tr_dq(xhci_t *, int slot_id, int ep, trb_t *, int dcs); static inline int xhci_ep_id(const endpoint_t *const ep) { - return ((ep->endpoint & 0x7f) << 1) + (ep->direction == IN); + return ((ep->endpoint & 0x7f) * 2) + (ep->direction != OUT); } |