summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/drivers/usb/xhci.c41
-rw-r--r--payloads/libpayload/drivers/usb/xhci_private.h116
-rw-r--r--payloads/libpayload/drivers/usb/xhci_rh.c2
3 files changed, 81 insertions, 78 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index 0a69c5137b..2f61f8658a 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -185,26 +185,27 @@ xhci_init (unsigned long physical_bar)
goto _free_xhci;
}
- xhci->capreg = phys_to_virt(physical_bar);
- xhci->opreg = ((void *)xhci->capreg) + xhci->capreg->caplength;
- xhci->hcrreg = ((void *)xhci->capreg) + xhci->capreg->rtsoff;
- xhci->dbreg = ((void *)xhci->capreg) + xhci->capreg->dboff;
+ memcpy(&xhci->capreg, phys_to_virt(physical_bar), sizeof(xhci->capreg));
+ xhci->opreg = phys_to_virt(physical_bar) + CAP_GET(CAPLEN, xhci->capreg);
+ xhci->hcrreg = phys_to_virt(physical_bar) + xhci->capreg.rtsoff;
+ xhci->dbreg = phys_to_virt(physical_bar) + xhci->capreg.dboff;
+
xhci_debug("regbase: 0x%"PRIx32"\n", physical_bar);
- xhci_debug("caplen: 0x%"PRIx32"\n", xhci->capreg->caplength);
- xhci_debug("rtsoff: 0x%"PRIx32"\n", xhci->capreg->rtsoff);
- xhci_debug("dboff: 0x%"PRIx32"\n", xhci->capreg->dboff);
+ xhci_debug("caplen: 0x%"PRIx32"\n", CAP_GET(CAPLEN, xhci->capreg));
+ xhci_debug("rtsoff: 0x%"PRIx32"\n", xhci->capreg.rtsoff);
+ xhci_debug("dboff: 0x%"PRIx32"\n", xhci->capreg.dboff);
xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n",
- xhci->capreg->hciver_hi, xhci->capreg->hciver_lo);
- if ((xhci->capreg->hciversion < 0x96) ||
- (xhci->capreg->hciversion > 0x110)) {
+ CAP_GET(CAPVER_HI, xhci->capreg), CAP_GET(CAPVER_LO, xhci->capreg));
+ if ((CAP_GET(CAPVER, xhci->capreg) < 0x96) ||
+ (CAP_GET(CAPVER, xhci->capreg) > 0x110)) {
xhci_debug("Unsupported xHCI version\n");
goto _free_xhci;
}
xhci_debug("context size: %dB\n", CTXSIZE(xhci));
- xhci_debug("maxslots: 0x%02lx\n", xhci->capreg->MaxSlots);
- xhci_debug("maxports: 0x%02lx\n", xhci->capreg->MaxPorts);
+ xhci_debug("maxslots: 0x%02lx\n", CAP_GET(MAXSLOTS, xhci->capreg));
+ xhci_debug("maxports: 0x%02lx\n", CAP_GET(MAXPORTS, xhci->capreg));
const unsigned pagesize = xhci->opreg->pagesize << 12;
xhci_debug("pagesize: 0x%04x\n", pagesize);
@@ -213,7 +214,8 @@ xhci_init (unsigned long physical_bar)
* structures at first and can still chicken out easily if we run out
* of memory.
*/
- xhci->max_slots_en = xhci->capreg->MaxSlots & CONFIG_LP_MASK_MaxSlotsEn;
+ xhci->max_slots_en = CAP_GET(MAXSLOTS, xhci->capreg) &
+ CONFIG_LP_MASK_MaxSlotsEn;
xhci->dcbaa = xhci_align(64, (xhci->max_slots_en + 1) * sizeof(u64));
xhci->dev = malloc((xhci->max_slots_en + 1) * sizeof(*xhci->dev));
if (!xhci->dcbaa || !xhci->dev) {
@@ -227,8 +229,9 @@ xhci_init (unsigned long physical_bar)
* Let dcbaa[0] point to another array of pointers, sp_ptrs.
* The pointers therein point to scratchpad buffers (pages).
*/
- const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs_Hi << 5 |
- xhci->capreg->Max_Scratchpad_Bufs_Lo;
+ const size_t max_sp_bufs =
+ CAP_GET(MAX_SCRATCH_BUFS_HI, xhci->capreg) << 5 |
+ CAP_GET(MAX_SCRATCH_BUFS_LO, xhci->capreg);
xhci_debug("max scratchpad bufs: 0x%zx\n", max_sp_bufs);
if (max_sp_bufs) {
const size_t sp_ptrs_size = max_sp_bufs * sizeof(u64);
@@ -376,7 +379,8 @@ xhci_reinit (hci_t *controller)
xhci_debug("event ring @%p (0x%08x)\n",
xhci->er.ring, virt_to_phys(xhci->er.ring));
xhci_debug("ERST Max: 0x%lx -> 0x%lx entries\n",
- xhci->capreg->ERST_Max, 1 << xhci->capreg->ERST_Max);
+ CAP_GET(ERST_MAX, xhci->capreg),
+ 1 << CAP_GET(ERST_MAX, xhci->capreg));
memset((void*)xhci->ev_ring_table, 0x00, sizeof(erst_entry_t));
xhci->ev_ring_table[0].seg_base_lo = virt_to_phys(xhci->er.ring);
xhci->ev_ring_table[0].seg_base_hi = 0;
@@ -432,8 +436,9 @@ xhci_shutdown(hci_t *const controller)
#endif
if (xhci->sp_ptrs) {
- size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs_Hi << 5 |
- xhci->capreg->Max_Scratchpad_Bufs_Lo;
+ const size_t max_sp_bufs =
+ CAP_GET(MAX_SCRATCH_BUFS_HI, xhci->capreg) << 5 |
+ CAP_GET(MAX_SCRATCH_BUFS_LO, xhci->capreg);
for (i = 0; i < max_sp_bufs; ++i) {
if (xhci->sp_ptrs[i])
free(phys_to_virt(xhci->sp_ptrs[i]));
diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h
index ab1dfa98e1..65c3fdd6cc 100644
--- a/payloads/libpayload/drivers/usb/xhci_private.h
+++ b/payloads/libpayload/drivers/usb/xhci_private.h
@@ -274,7 +274,6 @@ typedef volatile struct epctx {
} epctx_t;
#define NUM_EPS 32
-#define CTXSIZE(xhci) ((xhci)->capreg->csz ? 64 : 32)
typedef union devctx {
/* set of pointers, so we can dynamically adjust Slot/EP context size */
@@ -321,66 +320,65 @@ typedef struct erst_entry {
u32 rsvd;
} erst_entry_t;
+#define CAP_CAPLEN_FIELD hciparams
+#define CAP_CAPLEN_START 0
+#define CAP_CAPLEN_LEN 8
+#define CAP_CAPVER_FIELD hciparams
+#define CAP_CAPVER_START 16
+#define CAP_CAPVER_LEN 16
+#define CAP_CAPVER_HI_FIELD hciparams
+#define CAP_CAPVER_HI_START 24
+#define CAP_CAPVER_HI_LEN 8
+#define CAP_CAPVER_LO_FIELD hciparams
+#define CAP_CAPVER_LO_START 16
+#define CAP_CAPVER_LO_LEN 8
+#define CAP_MAXSLOTS_FIELD hcsparams1
+#define CAP_MAXSLOTS_START 0
+#define CAP_MAXSLOTS_LEN 7
+#define CAP_MAXINTRS_FIELD hcsparams1
+#define CAP_MAXINTRS_START 7
+#define CAP_MAXINTRS_LEN 11
+#define CAP_MAXPORTS_FIELD hcsparams1
+#define CAP_MAXPORTS_START 24
+#define CAP_MAXPORTS_LEN 8
+#define CAP_IST_FIELD hcsparams2
+#define CAP_IST_START 0
+#define CAP_IST_LEN 4
+#define CAP_ERST_MAX_FIELD hcsparams2
+#define CAP_ERST_MAX_START 4
+#define CAP_ERST_MAX_LEN 4
+#define CAP_MAX_SCRATCH_BUFS_HI_FIELD hcsparams2
+#define CAP_MAX_SCRATCH_BUFS_HI_START 21
+#define CAP_MAX_SCRATCH_BUFS_HI_LEN 5
+#define CAP_MAX_SCRATCH_BUFS_LO_FIELD hcsparams2
+#define CAP_MAX_SCRATCH_BUFS_LO_START 27
+#define CAP_MAX_SCRATCH_BUFS_LO_LEN 5
+#define CAP_U1_LATENCY_FIELD hcsparams3
+#define CAP_U1_LATENCY_START 0
+#define CAP_U1_LATENCY_LEN 8
+#define CAP_U2_LATENCY_FIELD hcsparams3
+#define CAP_U2_LATENCY_START 16
+#define CAP_U2_LATENCY_LEN 16
+#define CAP_CSZ_FIELD hccparams
+#define CAP_CSZ_START 2
+#define CAP_CSZ_LEN 1
+
+#define CAP_MASK(tok) MASK(CAP_##tok##_START, CAP_##tok##_LEN)
+#define CAP_GET(tok, cap) (((cap).CAP_##tok##_FIELD & CAP_MASK(tok)) \
+ >> CAP_##tok##_START)
+
+#define CTXSIZE(xhci) (CAP_GET(CSZ, (xhci)->capreg) ? 64 : 32)
+
typedef struct xhci {
- /* capreg is read-only, so no need for volatile,
- and thus 32bit accesses can be assumed. */
struct capreg {
- u8 caplength; /* 0x00 */
- u8 res1; /* 0x01 */
- union { /* 0x02 */
- u16 hciversion;
- struct {
- u8 hciver_lo;
- u8 hciver_hi;
- } __packed;
- } __packed;
- union { /* 0x04 */
- u32 hcsparams1;
- struct {
- unsigned long MaxSlots:7;
- unsigned long MaxIntrs:11;
- unsigned long:6;
- unsigned long MaxPorts:8;
- } __packed;
- } __packed;
- union { /* 0x08 */
- u32 hcsparams2;
- struct {
- unsigned long IST:4;
- unsigned long ERST_Max:4;
- unsigned long:13;
- unsigned long Max_Scratchpad_Bufs_Hi:5;
- unsigned long SPR:1;
- unsigned long Max_Scratchpad_Bufs_Lo:5;
- } __packed;
- } __packed;
- union { /* 0x0C */
- u32 hcsparams3;
- struct {
- unsigned long u1latency:8;
- unsigned long:8;
- unsigned long u2latency:16;
- } __packed;
- } __packed;
- union { /* 0x10 */
- u32 hccparams;
- struct {
- unsigned long ac64:1;
- unsigned long bnc:1;
- unsigned long csz:1;
- unsigned long ppc:1;
- unsigned long pind:1;
- unsigned long lhrc:1;
- unsigned long ltc:1;
- unsigned long nss:1;
- unsigned long:4;
- unsigned long MaxPSASize:4;
- unsigned long xECP:16;
- } __packed;
- } __packed;
- u32 dboff; /* 0x14 */
- u32 rtsoff; /* 0x18 */
- } __packed *capreg;
+ u32 hciparams;
+ u32 hcsparams1;
+ u32 hcsparams2;
+ u32 hcsparams3;
+ u32 hccparams;
+ u32 dboff;
+ u32 rtsoff;
+ } __packed capreg;
/* opreg is R/W is most places, so volatile access is necessary.
volatile means that the compiler seeks byte writes if possible,
diff --git a/payloads/libpayload/drivers/usb/xhci_rh.c b/payloads/libpayload/drivers/usb/xhci_rh.c
index 453fa5b409..865b9ac18b 100644
--- a/payloads/libpayload/drivers/usb/xhci_rh.c
+++ b/payloads/libpayload/drivers/usb/xhci_rh.c
@@ -160,7 +160,7 @@ xhci_rh_init (usbdev_t *dev)
dev->port = -1;
const int num_ports = /* TODO: maybe we need to read extended caps */
- (XHCI_INST(dev->controller)->capreg->hcsparams1 >> 24) & 0xff;
+ CAP_GET(MAXPORTS, XHCI_INST(dev->controller)->capreg);
generic_hub_init(dev, num_ports, &xhci_rh_ops);
usb_debug("xHCI: root hub init done\n");