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");