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>
This commit is contained in:
parent
2030d257d1
commit
8c7e416309
|
@ -197,7 +197,7 @@ xhci_init (unsigned long physical_bar)
|
||||||
xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n",
|
xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n",
|
||||||
xhci->capreg->hciver_hi, xhci->capreg->hciver_lo);
|
xhci->capreg->hciver_hi, xhci->capreg->hciver_lo);
|
||||||
if ((xhci->capreg->hciversion < 0x96) ||
|
if ((xhci->capreg->hciversion < 0x96) ||
|
||||||
(xhci->capreg->hciversion > 0x100)) {
|
(xhci->capreg->hciversion > 0x110)) {
|
||||||
xhci_debug("Unsupported xHCI version\n");
|
xhci_debug("Unsupported xHCI version\n");
|
||||||
goto _free_xhci;
|
goto _free_xhci;
|
||||||
}
|
}
|
||||||
|
@ -533,6 +533,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
|
static void
|
||||||
xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps,
|
xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps,
|
||||||
const int dalen, void *const data, const int dir)
|
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);
|
xhci_enqueue_trb(tr);
|
||||||
|
|
||||||
/* Ring doorbell for EP0 */
|
/* Ring doorbell for EP0 */
|
||||||
xhci->dbreg[dev->address] = 1;
|
xhci_ring_doorbell(&dev->endpoints[0]);
|
||||||
|
|
||||||
/* Wait for transfer events */
|
/* Wait for transfer events */
|
||||||
int i, transferred = 0;
|
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 mps = EC_GET(MPS, epctx);
|
||||||
const unsigned dir = (ep->direction == OUT) ? TRB_DIR_OUT : TRB_DIR_IN;
|
const unsigned dir = (ep->direction == OUT) ? TRB_DIR_OUT : TRB_DIR_IN;
|
||||||
xhci_enqueue_td(tr, ep_id, mps, size, data, dir);
|
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 */
|
/* Wait for transfer event */
|
||||||
const int ret = xhci_wait_for_transfer(xhci, ep->dev->address, ep_id);
|
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. */
|
and ring the doorbell. */
|
||||||
for (i = 0; i < (reqcount - 1); ++i)
|
for (i = 0; i < (reqcount - 1); ++i)
|
||||||
xhci_enqueue_trb(tr);
|
xhci_enqueue_trb(tr);
|
||||||
xhci->dbreg[slot_id] = ep_id;
|
xhci_ring_doorbell(ep);
|
||||||
|
|
||||||
return intrq;
|
return intrq;
|
||||||
|
|
||||||
|
@ -930,7 +939,7 @@ xhci_poll_intr_queue(void *const q)
|
||||||
|
|
||||||
/* Enqueue the last (spare) TRB and ring doorbell */
|
/* Enqueue the last (spare) TRB and ring doorbell */
|
||||||
xhci_enqueue_trb(tr);
|
xhci_enqueue_trb(tr);
|
||||||
xhci->dbreg[ep->dev->address] = ep_id;
|
xhci_ring_doorbell(ep);
|
||||||
|
|
||||||
/* Reuse the current buffer for the next spare TRB */
|
/* Reuse the current buffer for the next spare TRB */
|
||||||
xhci_clear_trb(tr->cur, tr->pcs);
|
xhci_clear_trb(tr->cur, tr->pcs);
|
||||||
|
|
|
@ -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);
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue