aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci.h
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 19:57:38 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-15 21:44:49 -0700
commit3ffbba9511b4148cbe1f6b6238686adaeaca8feb (patch)
treef69e42d07d596039e049fe2b14b720ddc6be2694 /drivers/usb/host/xhci.h
parentc6515272b858742962c1de0f3bf497a048b9abd7 (diff)
USB: xhci: Allocate and address USB devices
xHCI needs to get a "Slot ID" from the host controller and allocate other data structures for every USB device. Make usb_alloc_dev() and usb_release_dev() allocate and free these device structures. After setting up the xHC device structures, usb_alloc_dev() must wait for the hardware to respond to an Enable Slot command. usb_alloc_dev() fires off a Disable Slot command and does not wait for it to complete. When the USB core wants to choose an address for the device, the xHCI driver must issue a Set Address command and wait for an event for that command. 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/host/xhci.h')
-rw-r--r--drivers/usb/host/xhci.h94
1 files changed, 74 insertions, 20 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 059c659d3f3..4ef6b9e8850 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -285,12 +285,21 @@ struct xhci_op_regs {
* 4 - super speed
* 5-15 reserved
*/
-#define DEV_SPEED_MASK (0xf<<10)
+#define DEV_SPEED_MASK (0xf << 10)
+#define XDEV_FS (0x1 << 10)
+#define XDEV_LS (0x2 << 10)
+#define XDEV_HS (0x3 << 10)
+#define XDEV_SS (0x4 << 10)
#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10))
-#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == (0x1<<10))
-#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == (0x2<<10))
-#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == (0x3<<10))
-#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == (0x4<<10))
+#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS)
+#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS)
+#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS)
+#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS)
+/* Bits 20:23 in the Slot Context are the speed for the device */
+#define SLOT_SPEED_FS (XDEV_FS << 10)
+#define SLOT_SPEED_LS (XDEV_LS << 10)
+#define SLOT_SPEED_HS (XDEV_HS << 10)
+#define SLOT_SPEED_SS (XDEV_SS << 10)
/* Port Indicator Control */
#define PORT_LED_OFF (0 << 14)
#define PORT_LED_AMBER (1 << 14)
@@ -471,14 +480,19 @@ struct xhci_slot_ctx {
/* 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)
+#define LAST_CTX_MASK (0x1f << 27)
+#define LAST_CTX(p) ((p) << 27)
+#define LAST_CTX_TO_EP_NUM(p) (((p) >> 27) - 1)
+/* Plus one for the slot context flag */
+#define EPI_TO_FLAG(p) (1 << ((p) + 1))
+#define SLOT_FLAG (1 << 0)
+#define EP0_FLAG (1 << 1)
/* 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)
+#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16)
/* tt_info bitmasks */
/*
@@ -495,7 +509,7 @@ struct xhci_slot_ctx {
/* dev_state bitmasks */
/* USB device address - assigned by the HC */
-#define DEV_ADDR (0xff)
+#define DEV_ADDR_MASK (0xff)
/* bits 8:26 reserved */
/* Slot state */
#define SLOT_STATE (0x1f << 27)
@@ -507,12 +521,13 @@ struct xhci_slot_ctx {
* @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.
+ * @deq: 64-bit ring dequeue pointer address. If the endpoint only
+ * defines one stream, this points to the endpoint transfer ring.
+ * Otherwise, it points to a stream context array, which has a
+ * ring pointer for each flow.
+ * @tx_info:
+ * Average TRB lengths for the endpoint ring and
+ * max payload within an Endpoint Service Interval Time (ESIT).
*
* 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
@@ -521,12 +536,10 @@ struct xhci_slot_ctx {
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];
+ u32 deq[2];
+ u32 tx_info;
/* offset 0x14 - 0x1f reserved for HC internal use */
- u32 reserved[2];
+ u32 reserved[3];
} __attribute__ ((packed));
/* ep_info bitmasks */
@@ -589,6 +602,28 @@ struct xhci_device_control {
#define ADD_EP(x) (0x1 << x)
+struct xhci_virt_device {
+ /*
+ * Commands to the hardware are passed an "input context" that
+ * tells the hardware what to change in its data structures.
+ * The hardware will return changes in an "output context" that
+ * software must allocate for the hardware. We need to keep
+ * track of input and output contexts separately because
+ * these commands might fail and we don't trust the hardware.
+ */
+ struct xhci_device_control *out_ctx;
+ dma_addr_t out_ctx_dma;
+ /* Used for addressing devices and configuration changes */
+ struct xhci_device_control *in_ctx;
+ dma_addr_t in_ctx_dma;
+ /* FIXME when stream support is added */
+ struct xhci_ring *ep_rings[31];
+ dma_addr_t ep_dma[31];
+ /* Status of the last command issued for this device */
+ u32 cmd_status;
+};
+
+
/**
* struct xhci_device_context_array
* @dev_context_ptr array of 64-bit DMA addresses for device contexts
@@ -711,6 +746,11 @@ struct xhci_event_cmd {
u32 flags;
} __attribute__ ((packed));
+/* flags bitmasks */
+/* bits 16:23 are the virtual function ID */
+/* bits 24:31 are the slot ID */
+#define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24)
+#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24)
/* Port Status Change Event TRB fields */
/* Port ID - bits 31:24 */
@@ -931,6 +971,11 @@ struct xhci_hcd {
struct xhci_ring *cmd_ring;
struct xhci_ring *event_ring;
struct xhci_erst erst;
+ /* slot enabling and address device helpers */
+ struct completion addr_dev;
+ int slot_id;
+ /* Internal mirror of the HW's dcbaa */
+ struct xhci_virt_device *devs[MAX_HC_SLOTS];
/* DMA pools */
struct dma_pool *device_pool;
@@ -1002,10 +1047,14 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring);
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst);
void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
+void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep);
/* xHCI memory managment */
void xhci_mem_cleanup(struct xhci_hcd *xhci);
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);
+void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
+int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);
+int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
#ifdef CONFIG_PCI
/* xHCI PCI glue */
@@ -1022,6 +1071,9 @@ void xhci_stop(struct usb_hcd *hcd);
void xhci_shutdown(struct usb_hcd *hcd);
int xhci_get_frame(struct usb_hcd *hcd);
irqreturn_t xhci_irq(struct usb_hcd *hcd);
+int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
+void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
/* xHCI ring, segment, TRB, and TD functions */
dma_addr_t trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
@@ -1029,6 +1081,8 @@ void ring_cmd_db(struct xhci_hcd *xhci);
void *setup_one_noop(struct xhci_hcd *xhci);
void handle_event(struct xhci_hcd *xhci);
void set_hc_event_deq(struct xhci_hcd *xhci);
+int queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
+int queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id);
/* xHCI roothub code */
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,