diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-04-28 06:53:42 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 08:44:48 +0400 |
commit | a74588f94655263b96dacbbf14aac0958d8b7409 (patch) | |
tree | 0c4a53d0e6aa00fe9226c9c915f22da9171043ad /drivers/usb | |
parent | 0ebbab37422315a5d0cb29792271085bafdf38c0 (diff) | |
download | linux-a74588f94655263b96dacbbf14aac0958d8b7409.tar.xz |
USB: xhci: Device context array allocation.
Instead of keeping a "frame list" like older host controllers, the xHCI
host controller keeps internal representations of the USB devices, with a
transfer ring per endpoint. The host controller queues Transfer Request
Blocks (TRBs) to the endpoint ring, and then "rings the doorbell" for that
device. The host controller processes the transfer, places a transfer
completion event on the event ring, and interrupts the system.
The device context base address array must be allocated by the xHCI host
controller driver, along with the device contexts it points to.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 21 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 175 |
2 files changed, 196 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7cf15ca854be..be5a05b2021c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -220,6 +220,12 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) dma_pool_destroy(xhci->segment_pool); xhci->segment_pool = NULL; xhci_dbg(xhci, "Freed segment pool\n"); + xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]); + xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]); + if (xhci->dcbaa) + pci_free_consistent(pdev, sizeof(*xhci->dcbaa), + xhci->dcbaa, xhci->dcbaa->dma); + xhci->dcbaa = NULL; xhci->page_size = 0; xhci->page_shift = 0; } @@ -263,6 +269,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_writel(xhci, val, &xhci->op_regs->config_reg); /* + * Section 5.4.8 - doorbell array must be + * "physically contiguous and 64-byte (cache line) aligned". + */ + xhci->dcbaa = pci_alloc_consistent(to_pci_dev(dev), + sizeof(*xhci->dcbaa), &dma); + if (!xhci->dcbaa) + goto fail; + memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); + xhci->dcbaa->dma = dma; + xhci_dbg(xhci, "// Setting device context base array address to 0x%x\n", + xhci->dcbaa->dma); + xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]); + xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]); + + /* * Initialize the ring segment pool. The ring must be a contiguous * structure comprised of TRBs. The TRBs must be 16 byte aligned, * however, the command ring segment needs 64-byte aligned segments, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ed331310f1a8..f168fcac5999 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -436,6 +436,180 @@ struct xhci_doorbell_array { #define DB_MASK (0xff << 8) +/** + * struct xhci_slot_ctx + * @dev_info: Route string, device speed, hub info, and last valid endpoint + * @dev_info2: Max exit latency for device number, root hub port number + * @tt_info: tt_info is used to construct split transaction tokens + * @dev_state: slot state and device address + * + * Slot Context - section 6.2.1.1. This assumes the HC uses 32-byte context + * structures. If the HC uses 64-byte contexts, there is an additional 32 bytes + * reserved at the end of the slot context for HC internal use. + */ +struct xhci_slot_ctx { + u32 dev_info; + u32 dev_info2; + u32 tt_info; + u32 dev_state; + /* offset 0x10 to 0x1f reserved for HC internal use */ + u32 reserved[4]; +} __attribute__ ((packed)); + +/* dev_info bitmasks */ +/* Route String - 0:19 */ +#define ROUTE_STRING_MASK (0xfffff) +/* Device speed - values defined by PORTSC Device Speed field - 20:23 */ +#define DEV_SPEED (0xf << 20) +/* bit 24 reserved */ +/* Is this LS/FS device connected through a HS hub? - bit 25 */ +#define DEV_MTT (0x1 << 25) +/* Set if the device is a hub - bit 26 */ +#define DEV_HUB (0x1 << 26) +/* Index of the last valid endpoint context in this device context - 27:31 */ +#define LAST_EP_MASK (0x1f << 27) +#define LAST_EP(p) ((p) << 27) + +/* dev_info2 bitmasks */ +/* Max Exit Latency (ms) - worst case time to wake up all links in dev path */ +#define MAX_EXIT (0xffff) +/* Root hub port number that is needed to access the USB device */ +#define ROOT_HUB_PORT (0xff << 16) + +/* tt_info bitmasks */ +/* + * TT Hub Slot ID - for low or full speed devices attached to a high-speed hub + * The Slot ID of the hub that isolates the high speed signaling from + * this low or full-speed device. '0' if attached to root hub port. + */ +#define TT_SLOT (0xff) +/* + * The number of the downstream facing port of the high-speed hub + * '0' if the device is not low or full speed. + */ +#define TT_PORT (0xff << 8) + +/* dev_state bitmasks */ +/* USB device address - assigned by the HC */ +#define DEV_ADDR (0xff) +/* bits 8:26 reserved */ +/* Slot state */ +#define SLOT_STATE (0x1f << 27) + + +/** + * struct xhci_ep_ctx + * @ep_info: endpoint state, streams, mult, and interval information. + * @ep_info2: information on endpoint type, max packet size, max burst size, + * error count, and whether the HC will force an event for all + * transactions. + * @ep_ring: 64-bit ring address. If the endpoint only defines one flow, + * this points to the endpoint transfer ring. Otherwise, it points + * to a flow context array, which has a ring pointer for each flow. + * @intr_target: + * 64-bit address of the Interrupter Target that will receive + * events from this endpoint. + * + * Endpoint Context - section 6.2.1.2. This assumes the HC uses 32-byte context + * structures. If the HC uses 64-byte contexts, there is an additional 32 bytes + * reserved at the end of the endpoint context for HC internal use. + */ +struct xhci_ep_ctx { + u32 ep_info; + u32 ep_info2; + /* 64-bit endpoint ring address */ + u32 ep_ring[2]; + /* 64-bit address of the interrupter target */ + u32 intr_target[2]; + /* offset 0x14 - 0x1f reserved for HC internal use */ + u32 reserved[2]; +} __attribute__ ((packed)); + +/* ep_info bitmasks */ +/* + * Endpoint State - bits 0:2 + * 0 - disabled + * 1 - running + * 2 - halted due to halt condition - ok to manipulate endpoint ring + * 3 - stopped + * 4 - TRB error + * 5-7 - reserved + */ +#define EP_STATE (0xf) +/* Mult - Max number of burtst within an interval, in EP companion desc. */ +#define EP_MULT(p) ((p & 0x3) << 8) +/* bits 10:14 are Max Primary Streams */ +/* bit 15 is Linear Stream Array */ +/* Interval - period between requests to an endpoint - 125u increments. */ +#define EP_INTERVAL (0xff << 16) + +/* ep_info2 bitmasks */ +/* + * Force Event - generate transfer events for all TRBs for this endpoint + * This will tell the HC to ignore the IOC and ISP flags (for debugging only). + */ +#define FORCE_EVENT (0x1) +#define ERROR_COUNT(p) (((p) & 0x3) << 1) +#define EP_TYPE(p) ((p) << 3) +#define ISOC_OUT_EP 1 +#define BULK_OUT_EP 2 +#define INT_OUT_EP 3 +#define CTRL_EP 4 +#define ISOC_IN_EP 5 +#define BULK_IN_EP 6 +#define INT_IN_EP 7 +/* bit 6 reserved */ +/* bit 7 is Host Initiate Disable - for disabling stream selection */ +#define MAX_BURST(p) (((p)&0xff) << 8) +#define MAX_PACKET(p) (((p)&0xffff) << 16) + + +/** + * struct xhci_device_control + * Input/Output context; see section 6.2.5. + * + * @drop_context: set the bit of the endpoint context you want to disable + * @add_context: set the bit of the endpoint context you want to enable + */ +struct xhci_device_control { + u32 drop_flags; + u32 add_flags; + u32 rsvd[6]; + struct xhci_slot_ctx slot; + struct xhci_ep_ctx ep[31]; +} __attribute__ ((packed)); + +/* drop context bitmasks */ +#define DROP_EP(x) (0x1 << x) +/* add context bitmasks */ +#define ADD_EP(x) (0x1 << x) + + +/** + * struct xhci_device_context_array + * @dev_context_ptr array of 64-bit DMA addresses for device contexts + */ +struct xhci_device_context_array { + /* 64-bit device addresses; we only write 32-bit addresses */ + u32 dev_context_ptrs[2*MAX_HC_SLOTS]; + /* private xHCD pointers */ + dma_addr_t dma; +} __attribute__ ((packed)); +/* TODO: write function to set the 64-bit device DMA address */ +/* + * TODO: change this to be dynamically sized at HC mem init time since the HC + * might not be able to handle the maximum number of devices possible. + */ + + +struct xhci_stream_ctx { + /* 64-bit stream ring address, cycle state, and stream type */ + u32 stream_ring[2]; + /* offset 0x14 - 0x1f reserved for HC internal use */ + u32 reserved[2]; +} __attribute__ ((packed)); + + struct xhci_transfer_event { /* 64-bit buffer address, or immediate data */ u32 buffer[2]; @@ -725,6 +899,7 @@ struct xhci_hcd { int msix_count; struct msix_entry *msix_entries; /* data structures */ + struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; struct xhci_ring *event_ring; struct xhci_erst erst; |