From patchwork Tue Jul 2 15:15:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Murphy X-Patchwork-Id: 256453 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 242622C007B for ; Wed, 3 Jul 2013 01:17:17 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 35F964A3AC; Tue, 2 Jul 2013 17:16:53 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wx7mCEhhxiqi; Tue, 2 Jul 2013 17:16:52 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1F67C4A430; Tue, 2 Jul 2013 17:16:24 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B300E4A39E for ; Tue, 2 Jul 2013 17:15:56 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ax7twHkMm80x for ; Tue, 2 Jul 2013 17:15:49 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by theia.denx.de (Postfix) with ESMTPS id 763BC4A39F for ; Tue, 2 Jul 2013 17:15:33 +0200 (CEST) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id r62FFTV8024189; Tue, 2 Jul 2013 10:15:29 -0500 Received: from DLEE70.ent.ti.com (dlee70.ent.ti.com [157.170.170.113]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id r62FFTf8009143; Tue, 2 Jul 2013 10:15:29 -0500 Received: from dlelxv23.itg.ti.com (172.17.1.198) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.2.342.3; Tue, 2 Jul 2013 10:15:28 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlelxv23.itg.ti.com (8.13.8/8.13.8) with ESMTP id r62FFSDR019024; Tue, 2 Jul 2013 10:15:28 -0500 Received: from localhost (h0-228.vpn.ti.com [172.24.0.228]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id r62FFSt10253; Tue, 2 Jul 2013 10:15:28 -0500 (CDT) From: Dan Murphy To: , , Date: Tue, 2 Jul 2013 10:15:13 -0500 Message-ID: <1372778113-26053-8-git-send-email-dmurphy@ti.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1372778113-26053-1-git-send-email-dmurphy@ti.com> References: <1372778113-26053-1-git-send-email-dmurphy@ti.com> MIME-Version: 1.0 Cc: balbi@ti.com, gautam.vivek@samsung.com, rogerq@ti.com, ruchika@ti.com Subject: [U-Boot] [RFC] [UBOOT] [PATCH v3 7/7] USB: Modify the xHCI to adapt to the uBoot code base X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Modify the xHCI Linux kernel code base with #ifdefs __UBOOT__ to adapt the xHCI to the uBoot code. DMA and Radix needs investigating. Signed-off-by: Dan Murphy --- common/usb.c | 1 + common/usb_hub.c | 1 + drivers/usb/host/Makefile | 7 + drivers/usb/host/xhci-ext-caps.h | 12 ++ drivers/usb/host/xhci-hub.c | 19 +- drivers/usb/host/xhci-mem.c | 113 ++++++++++-- drivers/usb/host/xhci-pci.c | 356 ------------------------------------- drivers/usb/host/xhci-plat.c | 8 +- drivers/usb/host/xhci-ring.c | 52 +++++- drivers/usb/host/xhci.c | 82 +++++++-- drivers/usb/host/xhci.h | 20 ++- include/asm-generic/scatterlist.h | 34 ++++ include/configs/omap5_common.h | 1 + include/linux/usb/ch11.h | 13 ++ include/linux/usb/hcd.h | 10 +- include/linux/usb/linux-compat.h | 47 +++++ include/linux/usb/usb-compat.h | 4 +- include/usb.h | 34 +--- 18 files changed, 382 insertions(+), 432 deletions(-) delete mode 100644 drivers/usb/host/xhci-pci.c create mode 100644 include/asm-generic/scatterlist.h diff --git a/common/usb.c b/common/usb.c index 55fff5b..99aead8 100644 --- a/common/usb.c +++ b/common/usb.c @@ -53,6 +53,7 @@ #include #include +#include #ifdef CONFIG_4xx #include #endif diff --git a/common/usb_hub.c b/common/usb_hub.c index 774ba63..e18e34d 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -49,6 +49,7 @@ #include #include +#include /* usb structure information */ #ifdef CONFIG_4xx #include #endif diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 98f2a10..a483182 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -58,6 +58,12 @@ COBJS-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o COBJS-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o +COBJS-$(CONFIG_USB_XHCI) += xhci.o +COBJS-$(CONFIG_USB_XHCI) += xhci-hub.o +COBJS-$(CONFIG_USB_XHCI) += xhci-ring.o +COBJS-$(CONFIG_USB_XHCI) += xhci-mem.o +COBJS-$(CONFIG_USB_XHCI) += xhci-plat.o + COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) @@ -75,3 +81,4 @@ include $(SRCTREE)/rules.mk sinclude $(obj).depend ######################################################################### + diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index 377f424..f3cddb1 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -87,6 +87,8 @@ /* true: Controller Not Ready to accept doorbell or op reg writes after reset */ #define XHCI_STS_CNR (1 << 11) +#define __UBOOT__ +#ifndef __UBOOT__ #include /** @@ -153,3 +155,13 @@ static inline int xhci_find_ext_cap_by_id(void __iomem *base, int ext_offset, in return ext_offset; return 0; } +#else +static inline int xhci_find_next_cap_offset(void __iomem *base, int ext_offset) +{ + return 0; +} +static inline int xhci_find_ext_cap_by_id(void __iomem *base, int ext_offset, int id) +{ + return 0; +} +#endif diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 187a3ec..8f01cb3 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -19,10 +19,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#define __UBOOT__ +#ifndef __UBOOT__ #include #include - +#endif #include "xhci.h" #define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) @@ -632,8 +633,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, !DEV_SUPERSPEED(temp)) { if ((temp & PORT_RESET) || !(temp & PORT_PE)) goto error; +#ifndef __UBOOT__ if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) { +#else + /* TODO fix this to equate to time_after_eq API */ + if (bus_state->resume_done[wIndex]) { +#endif xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); bus_state->resume_done[wIndex] = 0; @@ -1009,10 +1015,19 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) retval = -ENODEV; break; } +#ifndef __UBOOT__ if ((temp & mask) != 0 || (bus_state->port_c_suspend & 1 << i) || (bus_state->resume_done[i] && time_after_eq( jiffies, bus_state->resume_done[i]))) { +#else + /* TODO Fix this for the time_after_eq api */ + if ((temp & mask) != 0 || + (bus_state->port_c_suspend & 1 << i) || + (bus_state->resume_done[i] && + (bus_state->resume_done[i]))) { + +#endif buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2cfc465..4b3f559 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -19,12 +19,20 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#define __UBOOT__ +#ifndef __UBOOT__ #include #include #include #include +#else +#include +#include /* for struct list_head */ +#include +#include +#endif + #include "xhci.h" /* @@ -44,13 +52,14 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, seg = kzalloc(sizeof *seg, flags); if (!seg) return NULL; - +#ifndef __UBOOT__ + /* DMA */ seg->trbs = dma_pool_alloc(xhci->segment_pool, flags, &dma); if (!seg->trbs) { kfree(seg); return NULL; } - +#endif memset(seg->trbs, 0, TRB_SEGMENT_SIZE); /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */ if (cycle_state == 0) { @@ -66,7 +75,10 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) { if (seg->trbs) { +#ifndef __UBOOT__ + /* DMA */ dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma); +#endif seg->trbs = NULL; } kfree(seg); @@ -367,8 +379,10 @@ static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024; if (type == XHCI_CTX_TYPE_INPUT) ctx->size += CTX_SIZE(xhci->hcc_params); - +#ifndef __UBOOT__ + /* DMA */ ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); +#endif memset(ctx->bytes, 0, ctx->size); return ctx; } @@ -378,7 +392,10 @@ static void xhci_free_container_ctx(struct xhci_hcd *xhci, { if (!ctx) return; +#ifndef __UBOOT__ + /* DMA */ dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma); +#endif kfree(ctx); } @@ -419,6 +436,8 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) { +#ifndef __UBOOT__ + /* PCI */ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) @@ -431,6 +450,9 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, else return dma_pool_free(xhci->medium_streams_pool, stream_ctx, dma); +#else + return; +#endif } /* @@ -447,6 +469,8 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, dma_addr_t *dma, gfp_t mem_flags) { +#ifndef __UBOOT__ + /* PCI */ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE) @@ -459,15 +483,21 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, else return dma_pool_alloc(xhci->medium_streams_pool, mem_flags, dma); +#else + return NULL; +#endif } struct xhci_ring *xhci_dma_to_transfer_ring( struct xhci_virt_ep *ep, u64 address) { +#ifndef __UBOOT__ + /* RADIX */ if (ep->ep_state & EP_HAS_STREAMS) return radix_tree_lookup(&ep->stream_info->trb_address_map, address >> TRB_SEGMENT_SHIFT); +#endif return ep->ring; } @@ -597,7 +627,10 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, struct xhci_stream_info *stream_info; u32 cur_stream; struct xhci_ring *cur_ring; +#ifndef __UBOOT__ + /* ilog2 */ unsigned long key; +#endif u64 addr; int ret; @@ -638,8 +671,10 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, xhci_alloc_command(xhci, true, true, mem_flags); if (!stream_info->free_streams_command) goto cleanup_ctx; - +#ifndef __UBOOT__ + /* RADIX */ INIT_RADIX_TREE(&stream_info->trb_address_map, GFP_ATOMIC); +#endif /* Allocate rings for all the streams that the driver will use, * and add their segment DMA addresses to the radix tree. @@ -660,11 +695,16 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, cpu_to_le64(addr); xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n", cur_stream, (unsigned long long) addr); - +#ifndef __UBOOT__ + /* ilog2 */ key = (unsigned long) (cur_ring->first_seg->dma >> TRB_SEGMENT_SHIFT); +#endif +#ifndef __UBOOT__ + /* RADIX */ ret = radix_tree_insert(&stream_info->trb_address_map, key, cur_ring); +#endif if (ret) { xhci_ring_free(xhci, cur_ring); stream_info->stream_rings[cur_stream] = NULL; @@ -692,8 +732,11 @@ cleanup_rings: cur_ring = stream_info->stream_rings[cur_stream]; if (cur_ring) { addr = cur_ring->first_seg->dma; +#ifndef __UBOOT__ + /* RADIX */ radix_tree_delete(&stream_info->trb_address_map, addr >> TRB_SEGMENT_SHIFT); +#endif xhci_ring_free(xhci, cur_ring); stream_info->stream_rings[cur_stream] = NULL; } @@ -763,8 +806,11 @@ void xhci_free_stream_info(struct xhci_hcd *xhci, cur_ring = stream_info->stream_rings[cur_stream]; if (cur_ring) { addr = cur_ring->first_seg->dma; +#ifndef __UBOOT__ + /* RADIX */ radix_tree_delete(&stream_info->trb_address_map, addr >> TRB_SEGMENT_SHIFT); +#endif xhci_ring_free(xhci, cur_ring); stream_info->stream_rings[cur_stream] = NULL; } @@ -788,9 +834,12 @@ void xhci_free_stream_info(struct xhci_hcd *xhci, static void xhci_init_endpoint_timer(struct xhci_hcd *xhci, struct xhci_virt_ep *ep) { +#ifndef __UBOOT__ + /* Timer */ init_timer(&ep->stop_cmd_timer); ep->stop_cmd_timer.data = (unsigned long) ep; ep->stop_cmd_timer.function = xhci_stop_endpoint_command_watchdog; +#endif ep->xhci = xhci; } @@ -973,8 +1022,9 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, if (!dev->ring_cache) goto fail; dev->num_rings_cached = 0; - +#ifndef __UBOOT__ init_completion(&dev->cmd_completion); +#endif INIT_LIST_HEAD(&dev->cmd_list); dev->udev = udev; @@ -1680,6 +1730,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) static void scratchpad_free(struct xhci_hcd *xhci) { +#ifndef __UBOOT__ + /* PCI */ int num_sp; int i; struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); @@ -1699,6 +1751,7 @@ static void scratchpad_free(struct xhci_hcd *xhci) dma_free_coherent(&pdev->dev, num_sp * sizeof(u64), xhci->scratchpad->sp_array, xhci->scratchpad->sp_dma); +#endif kfree(xhci->scratchpad); xhci->scratchpad = NULL; } @@ -1731,7 +1784,9 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, kfree(command); return NULL; } +#ifndef __UBOOT__ init_completion(command->completion); +#endif } command->status = 0; @@ -1758,7 +1813,12 @@ void xhci_free_command(struct xhci_hcd *xhci, void xhci_mem_cleanup(struct xhci_hcd *xhci) { +#ifndef __UBOOT__ + /* PCI */ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); +#else + struct pci_dev *pdev = NULL; +#endif struct dev_info *dev_info, *next; struct xhci_cd *cur_cd, *next_cd; unsigned long flags; @@ -1767,9 +1827,12 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); +#ifndef __UBOOT__ + /* DMA */ if (xhci->erst.entries) dma_free_coherent(&pdev->dev, size, xhci->erst.entries, xhci->erst.erst_dma_addr); +#endif xhci->erst.entries = NULL; xhci_dbg(xhci, "Freed ERST\n"); if (xhci->event_ring) @@ -1792,30 +1855,40 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); - +#ifndef __UBOOT__ + /* DMA */ if (xhci->segment_pool) dma_pool_destroy(xhci->segment_pool); +#endif xhci->segment_pool = NULL; xhci_dbg(xhci, "Freed segment pool\n"); - +#ifndef __UBOOT__ + /* DMA */ if (xhci->device_pool) dma_pool_destroy(xhci->device_pool); +#endif xhci->device_pool = NULL; xhci_dbg(xhci, "Freed device context pool\n"); - +#ifndef __UBOOT__ + /* DMA */ if (xhci->small_streams_pool) dma_pool_destroy(xhci->small_streams_pool); +#endif xhci->small_streams_pool = NULL; xhci_dbg(xhci, "Freed small stream array pool\n"); - +#ifndef __UBOOT__ + /* DMA */ if (xhci->medium_streams_pool) dma_pool_destroy(xhci->medium_streams_pool); +#endif xhci->medium_streams_pool = NULL; xhci_dbg(xhci, "Freed medium stream array pool\n"); - +#ifndef __UBOOT__ + /* DMA */ if (xhci->dcbaa) dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa), xhci->dcbaa, xhci->dcbaa->dma); +#endif xhci->dcbaa = NULL; scratchpad_free(xhci); @@ -2022,7 +2095,11 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, xhci->event_ring->dequeue); +#ifndef __UBOOT__ if (deq == 0 && !in_interrupt()) +#else + if (deq == 0) +#endif xhci_warn(xhci, "WARN something wrong with SW event ring " "dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ @@ -2305,24 +2382,32 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * however, the command ring segment needs 64-byte aligned segments, * so we pick the greater alignment need. */ +#ifndef __UBOOT__ + /* DMA */ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, TRB_SEGMENT_SIZE, 64, xhci->page_size); - +#endif /* See Table 46 and Note on Figure 55 */ +#ifndef __UBOOT__ + /* DMA */ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, 2112, 64, xhci->page_size); +#endif if (!xhci->segment_pool || !xhci->device_pool) goto fail; /* Linear stream context arrays don't have any boundary restrictions, * and only need to be 16-byte aligned. */ +#ifndef __UBOOT__ + /* DMA */ xhci->small_streams_pool = dma_pool_create("xHCI 256 byte stream ctx arrays", dev, SMALL_STREAM_ARRAY_SIZE, 16, 0); xhci->medium_streams_pool = dma_pool_create("xHCI 1KB stream ctx arrays", dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0); +#endif /* Any stream context array bigger than MEDIUM_STREAM_ARRAY_SIZE * will be allocated with dma_alloc_coherent() */ @@ -2432,7 +2517,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * something other than the default (~1ms minimum between interrupts). * See section 5.5.1.2. */ +#ifndef __UBOOT__ init_completion(&xhci->addr_dev); +#endif for (i = 0; i < MAX_HC_SLOTS; ++i) xhci->devs[i] = NULL; for (i = 0; i < USB_MAXCHILDREN; ++i) { diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c deleted file mode 100644 index 1a30c38..0000000 --- a/drivers/usb/host/xhci-pci.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * xHCI host controller driver PCI Bus Glue. - * - * Copyright (C) 2008 Intel Corp. - * - * Author: Sarah Sharp - * Some code borrowed from the Linux EHCI driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#include "xhci.h" - -/* Device for a quirk */ -#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 -#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 -#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400 - -#define PCI_VENDOR_ID_ETRON 0x1b6f -#define PCI_DEVICE_ID_ASROCK_P67 0x7023 - -static const char hcd_name[] = "xhci_hcd"; - -/* called after powerup, by probe or system-pm "wakeup" */ -static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) -{ - /* - * TODO: Implement finding debug ports later. - * TODO: see if there are any quirks that need to be added to handle - * new extended capabilities. - */ - - /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ - if (!pci_set_mwi(pdev)) - xhci_dbg(xhci, "MWI active\n"); - - xhci_dbg(xhci, "Finished xhci_pci_reinit\n"); - return 0; -} - -static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) -{ - struct pci_dev *pdev = to_pci_dev(dev); - - /* Look for vendor-specific quirks */ - if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { - if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && - pdev->revision == 0x0) { - xhci->quirks |= XHCI_RESET_EP_QUIRK; - xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" - " endpoint cmd after reset endpoint\n"); - } - /* Fresco Logic confirms: all revisions of this chip do not - * support MSI, even though some of them claim to in their PCI - * capabilities. - */ - xhci->quirks |= XHCI_BROKEN_MSI; - xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u " - "has broken MSI implementation\n", - pdev->revision); - xhci->quirks |= XHCI_TRUST_TX_LENGTH; - } - - if (pdev->vendor == PCI_VENDOR_ID_NEC) - xhci->quirks |= XHCI_NEC_HOST; - - if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96) - xhci->quirks |= XHCI_AMD_0x96_HOST; - - /* AMD PLL quirk */ - if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) - xhci->quirks |= XHCI_AMD_PLL_FIX; - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { - xhci->quirks |= XHCI_LPM_SUPPORT; - xhci->quirks |= XHCI_INTEL_HOST; - } - if (pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { - xhci->quirks |= XHCI_SPURIOUS_SUCCESS; - xhci->quirks |= XHCI_EP_LIMIT_QUIRK; - xhci->limit_active_eps = 64; - xhci->quirks |= XHCI_SW_BW_CHECKING; - /* - * PPT desktop boards DH77EB and DH77DF will power back on after - * a few seconds of being shutdown. The fix for this is to - * switch the ports from xHCI to EHCI on shutdown. We can't use - * DMI information to find those particular boards (since each - * vendor will change the board name), so we have to key off all - * PPT chipsets. - */ - xhci->quirks |= XHCI_SPURIOUS_REBOOT; - xhci->quirks |= XHCI_AVOID_BEI; - } - if (pdev->vendor == PCI_VENDOR_ID_ETRON && - pdev->device == PCI_DEVICE_ID_ASROCK_P67) { - xhci->quirks |= XHCI_RESET_ON_RESUME; - xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); - xhci->quirks |= XHCI_TRUST_TX_LENGTH; - } - if (pdev->vendor == PCI_VENDOR_ID_VIA) - xhci->quirks |= XHCI_RESET_ON_RESUME; -} - -/* called during probe() after chip reset completes */ -static int xhci_pci_setup(struct usb_hcd *hcd) -{ - struct xhci_hcd *xhci; - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - int retval; - - retval = xhci_gen_setup(hcd, xhci_pci_quirks); - if (retval) - return retval; - - xhci = hcd_to_xhci(hcd); - if (!usb_hcd_is_primary_hcd(hcd)) - return 0; - - pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); - xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn); - - /* Find any debug ports */ - retval = xhci_pci_reinit(xhci, pdev); - if (!retval) - return retval; - - kfree(xhci); - return retval; -} - -/* - * We need to register our own PCI probe function (instead of the USB core's - * function) in order to create a second roothub under xHCI. - */ -static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - struct xhci_hcd *xhci; - struct hc_driver *driver; - struct usb_hcd *hcd; - - driver = (struct hc_driver *)id->driver_data; - /* Register the USB 2.0 roothub. - * FIXME: USB core must know to register the USB 2.0 roothub first. - * This is sort of silly, because we could just set the HCD driver flags - * to say USB 2.0, but I'm not sure what the implications would be in - * the other parts of the HCD code. - */ - retval = usb_hcd_pci_probe(dev, id); - - if (retval) - return retval; - - /* USB 2.0 roothub is stored in the PCI device now. */ - hcd = dev_get_drvdata(&dev->dev); - xhci = hcd_to_xhci(hcd); - xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, - pci_name(dev), hcd); - if (!xhci->shared_hcd) { - retval = -ENOMEM; - goto dealloc_usb2_hcd; - } - - /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) - * is called by usb_add_hcd(). - */ - *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; - - retval = usb_add_hcd(xhci->shared_hcd, dev->irq, - IRQF_SHARED); - if (retval) - goto put_usb3_hcd; - /* Roothub already marked as USB 3.0 speed */ - - /* We know the LPM timeout algorithms for this host, let the USB core - * enable and disable LPM for devices under the USB 3.0 roothub. - */ - if (xhci->quirks & XHCI_LPM_SUPPORT) - hcd_to_bus(xhci->shared_hcd)->root_hub->lpm_capable = 1; - - return 0; - -put_usb3_hcd: - usb_put_hcd(xhci->shared_hcd); -dealloc_usb2_hcd: - usb_hcd_pci_remove(dev); - return retval; -} - -static void xhci_pci_remove(struct pci_dev *dev) -{ - struct xhci_hcd *xhci; - - xhci = hcd_to_xhci(pci_get_drvdata(dev)); - if (xhci->shared_hcd) { - usb_remove_hcd(xhci->shared_hcd); - usb_put_hcd(xhci->shared_hcd); - } - usb_hcd_pci_remove(dev); - kfree(xhci); -} - -#ifdef CONFIG_PM -static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - - return xhci_suspend(xhci); -} - -static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - int retval = 0; - - /* The BIOS on systems with the Intel Panther Point chipset may or may - * not support xHCI natively. That means that during system resume, it - * may switch the ports back to EHCI so that users can use their - * keyboard to select a kernel from GRUB after resume from hibernate. - * - * The BIOS is supposed to remember whether the OS had xHCI ports - * enabled before resume, and switch the ports back to xHCI when the - * BIOS/OS semaphore is written, but we all know we can't trust BIOS - * writers. - * - * Unconditionally switch the ports back to xHCI after a system resume. - * We can't tell whether the EHCI or xHCI controller will be resumed - * first, so we have to do the port switchover in both drivers. Writing - * a '1' to the port switchover registers should have no effect if the - * port was already switched over. - */ - if (usb_is_intel_switchable_xhci(pdev)) - usb_enable_xhci_ports(pdev); - - retval = xhci_resume(xhci, hibernated); - return retval; -} -#endif /* CONFIG_PM */ - -static const struct hc_driver xhci_pci_hc_driver = { - .description = hcd_name, - .product_desc = "xHCI Host Controller", - .hcd_priv_size = sizeof(struct xhci_hcd *), - - /* - * generic hardware linkage - */ - .irq = xhci_irq, - .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, - - /* - * basic lifecycle operations - */ - .reset = xhci_pci_setup, - .start = xhci_run, -#ifdef CONFIG_PM - .pci_suspend = xhci_pci_suspend, - .pci_resume = xhci_pci_resume, -#endif - .stop = xhci_stop, - .shutdown = xhci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = xhci_urb_enqueue, - .urb_dequeue = xhci_urb_dequeue, - .alloc_dev = xhci_alloc_dev, - .free_dev = xhci_free_dev, - .alloc_streams = xhci_alloc_streams, - .free_streams = xhci_free_streams, - .add_endpoint = xhci_add_endpoint, - .drop_endpoint = xhci_drop_endpoint, - .endpoint_reset = xhci_endpoint_reset, - .check_bandwidth = xhci_check_bandwidth, - .reset_bandwidth = xhci_reset_bandwidth, - .address_device = xhci_address_device, - .update_hub_device = xhci_update_hub_device, - .reset_device = xhci_discover_or_reset_device, - - /* - * scheduling support - */ - .get_frame_number = xhci_get_frame, - - /* Root hub support */ - .hub_control = xhci_hub_control, - .hub_status_data = xhci_hub_status_data, - .bus_suspend = xhci_bus_suspend, - .bus_resume = xhci_bus_resume, - /* - * call back when device connected and addressed - */ - .update_device = xhci_update_device, - .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, - .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, - .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, - .find_raw_port_number = xhci_find_raw_port_number, -}; - -/*-------------------------------------------------------------------------*/ - -/* PCI driver selection metadata; PCI hotplugging uses this */ -static const struct pci_device_id pci_ids[] = { { - /* handle any USB 3.0 xHCI controller */ - PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0), - .driver_data = (unsigned long) &xhci_pci_hc_driver, - }, - { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE(pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver xhci_pci_driver = { - .name = (char *) hcd_name, - .id_table = pci_ids, - - .probe = xhci_pci_probe, - .remove = xhci_pci_remove, - /* suspend and resume implemented later */ - - .shutdown = usb_hcd_pci_shutdown, -#ifdef CONFIG_PM_SLEEP - .driver = { - .pm = &usb_hcd_pci_pm_ops - }, -#endif -}; - -int __init xhci_register_pci(void) -{ - return pci_register_driver(&xhci_pci_driver); -} - -void xhci_unregister_pci(void) -{ - pci_unregister_driver(&xhci_pci_driver); -} diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index df90fe5..3472816 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -10,11 +10,12 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - +#define __UBOOT__ +#ifndef __UBOOT__ #include #include #include - +#endif #include "xhci.h" static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) @@ -81,7 +82,7 @@ static const struct hc_driver xhci_plat_xhci_driver = { .bus_suspend = xhci_bus_suspend, .bus_resume = xhci_bus_resume, }; - +#ifndef __UBOOT__ static int xhci_plat_probe(struct platform_device *pdev) { const struct hc_driver *driver; @@ -203,3 +204,4 @@ void xhci_unregister_plat(void) { platform_driver_unregister(&usb_xhci_driver); } +#endif diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1969c00..02fa41f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -64,8 +64,18 @@ * endpoint rings; it generates events on the event ring for these. */ +#define __UBOOT__ +#ifndef __UBOOT__ #include #include +#else + +#include +#include /* for struct list_head */ +#include +#include +#endif + #include "xhci.h" static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, @@ -699,7 +709,9 @@ static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci, * timer is running on another CPU, we don't decrement stop_cmds_pending * (since we didn't successfully stop the watchdog timer). */ +#ifndef __UBOOT__ if (del_timer(&ep->stop_cmd_timer)) +#endif ep->stop_cmds_pending--; } @@ -720,10 +732,12 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, if (urb_priv->td_cnt == urb_priv->length) { if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--; +#ifndef __UBOOT__ if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_quirk_pll_enable(); } +#endif } usb_hcd_unlink_urb_from_ep(hcd, urb); @@ -1178,8 +1192,10 @@ static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, command->status = status; list_del(&command->cmd_list); if (command->completion) +#ifndef __UBOOT__ complete(command->completion); else +#endif xhci_free_command(xhci, command); } @@ -1354,6 +1370,7 @@ static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { + int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; @@ -1399,7 +1416,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->slot_id = slot_id; else xhci->slot_id = 0; +#ifndef __UBOOT__ complete(&xhci->addr_dev); +#endif break; case TRB_TYPE(TRB_DISABLE_SLOT): if (xhci->devs[slot_id]) { @@ -1453,18 +1472,24 @@ bandwidth_change: xhci_dbg(xhci, "Completed config ep cmd\n"); xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); +#ifndef __UBOOT__ complete(&xhci->devs[slot_id]->cmd_completion); +#endif break; case TRB_TYPE(TRB_EVAL_CONTEXT): virt_dev = xhci->devs[slot_id]; if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) break; xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); +#ifndef __UBOOT__ complete(&xhci->devs[slot_id]->cmd_completion); +#endif break; case TRB_TYPE(TRB_ADDR_DEV): xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status)); +#ifndef __UBOOT__ complete(&xhci->addr_dev); +#endif break; case TRB_TYPE(TRB_STOP_RING): handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event); @@ -1677,11 +1702,17 @@ static void handle_port_status(struct xhci_hcd *xhci, goto cleanup; } else { xhci_dbg(xhci, "resume HS port %d\n", port_id); +#ifndef __UBOOT__ bus_state->resume_done[faked_port_index] = jiffies + msecs_to_jiffies(20); +#else + bus_state->resume_done[faked_port_index] = 20; +#endif set_bit(faked_port_index, &bus_state->resuming_ports); +#ifndef __UBOOT__ mod_timer(&hcd->rh_timer, bus_state->resume_done[faked_port_index]); +#endif /* Do the rest in GetPortStatus */ } } @@ -1960,11 +1991,13 @@ td_cleanup: ret = 1; if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--; +#ifndef __UBOOT__ if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_quirk_pll_enable(); } +#endif } } } @@ -2374,9 +2407,14 @@ static int handle_tx_event(struct xhci_hcd *xhci, break; if (xhci->quirks & XHCI_TRUST_TX_LENGTH) trb_comp_code = COMP_SHORT_TX; +#ifndef __UBOOT__ else xhci_warn_ratelimited(xhci, "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); +#else + else + printf("WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); +#endif case COMP_SHORT_TX: break; case COMP_STOP: @@ -2657,12 +2695,13 @@ static int xhci_handle_event(struct xhci_hcd *xhci) xhci->error_bitmask |= 1 << 2; return 0; } - +#ifndef __UBOOT__ /* * Barrier between reading the TRB_CYCLE (valid) flag above and any * speculative reads of the event's flags/data below. */ rmb(); +#endif /* FIXME: Handle more event types. */ switch ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK)) { case TRB_TYPE(TRB_COMPLETION): @@ -2977,6 +3016,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) temp = urb->transfer_buffer_length; num_trbs = 0; + /* sg_next is not defined yet need to define it */ for_each_sg(urb->sg, sg, num_sgs, i) { unsigned int len = sg_dma_len(sg); @@ -3056,7 +3096,9 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { +#ifndef __UBOOT__ if (printk_ratelimit()) +#endif dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", @@ -3258,9 +3300,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, --num_sgs; if (num_sgs == 0) break; +#ifndef __UBOOT__ + /* TODO fix the scatterlist code here */ sg = sg_next(sg); addr = (u64) sg_dma_address(sg); this_sg_len = sg_dma_len(sg); +#endif } else { addr += trb_buff_len; } @@ -3757,11 +3802,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, goto cleanup; } } - +#ifndef __UBOOT__ if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) { if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_quirk_pll_disable(); } +#endif xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs++; giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, @@ -3845,7 +3891,9 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { +#ifndef __UBOOT__ if (printk_ratelimit()) +#endif dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b4aa79d..14dcf69 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -20,6 +20,8 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define __UBOOT__ +#ifndef __UBOOT__ #include #include #include @@ -27,6 +29,16 @@ #include #include #include +#else + +#include +#include +#include +#include +#include +#include + +#endif #include "xhci.h" @@ -428,10 +440,12 @@ static void compliance_mode_recovery(unsigned long arg) usb_hcd_poll_rh_status(hcd); } } - +#ifndef __UBOOT__ +/* TODO needs implemenation */ if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) mod_timer(&xhci->comp_mode_recovery_timer, jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +#endif } /* @@ -447,6 +461,8 @@ static void compliance_mode_recovery(unsigned long arg) static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) { xhci->port_status_u0 = 0; +#ifndef __UBOOT__ +/* TODO needs timer implemenation */ init_timer(&xhci->comp_mode_recovery_timer); xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; @@ -457,6 +473,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) set_timer_slack(&xhci->comp_mode_recovery_timer, msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); add_timer(&xhci->comp_mode_recovery_timer); +#endif xhci_dbg(xhci, "Compliance mode recovery timer initialized\n"); } @@ -468,6 +485,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) */ static bool compliance_mode_recovery_timer_quirk_check(void) { +#ifndef __UBOOT__ const char *dmi_product_name, *dmi_sys_vendor; dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); @@ -483,7 +501,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void) strstr(dmi_product_name, "Z820") || strstr(dmi_product_name, "Z1 Workstation")) return true; - +#endif return false; } @@ -738,10 +756,10 @@ void xhci_stop(struct usb_hcd *hcd) xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n", __func__); } - +#ifndef __UBOOT__ if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); - +#endif xhci_dbg(xhci, "// Disabling event ring interrupts\n"); temp = xhci_readl(xhci, &xhci->op_regs->status); xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); @@ -768,10 +786,10 @@ void xhci_stop(struct usb_hcd *hcd) void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - +#ifndef __UBOOT__ if (xhci->quirks & XHCI_SPURIOUS_REBOOT) usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); - +#endif spin_lock_irq(&xhci->lock); xhci_halt(xhci); spin_unlock_irq(&xhci->lock); @@ -1269,8 +1287,10 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) ep_index = xhci_get_endpoint_index(&urb->ep->desc); if (!HCD_HW_ACCESSIBLE(hcd)) { +#ifndef __UBOOT__ if (!in_interrupt()) xhci_dbg(xhci, "urb submitted during PCI suspend\n"); +#endif ret = -ESHUTDOWN; goto exit; } @@ -1531,9 +1551,11 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) if (!(ep->ep_state & EP_HALT_PENDING)) { ep->ep_state |= EP_HALT_PENDING; ep->stop_cmds_pending++; +#ifndef __UBOOT__ ep->stop_cmd_timer.expires = jiffies + XHCI_STOP_EP_CMD_TIMEOUT * HZ; add_timer(&ep->stop_cmd_timer); +#endif xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0); xhci_ring_cmd_db(xhci); } @@ -2541,10 +2563,14 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, bool ctx_change, bool must_succeed) { int ret; +#ifndef __UBOOT__ int timeleft; +#endif unsigned long flags; struct xhci_container_ctx *in_ctx; +#ifndef __UBOOT__ struct completion *cmd_completion; +#endif u32 *cmd_status; struct xhci_virt_device *virt_dev; union xhci_trb *cmd_trb; @@ -2573,7 +2599,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, xhci_warn(xhci, "Not enough bandwidth\n"); return -ENOMEM; } - +#ifndef __UBOOT__ if (command) { cmd_completion = command->completion; cmd_status = &command->status; @@ -2593,6 +2619,11 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); +#endif +#ifndef __UBOOT__ + init_completion(cmd_completion); +#endif + cmd_trb = xhci->cmd_ring->dequeue; if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, @@ -2611,7 +2642,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); - +#ifndef __UBOOT__ /* Wait for the configure endpoint command to complete */ timeleft = wait_for_completion_interruptible_timeout( cmd_completion, @@ -2628,7 +2659,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, return ret; return -ETIME; } - +#endif if (!ctx_change) ret = xhci_configure_endpoint_result(xhci, udev, cmd_status); else @@ -2936,9 +2967,11 @@ static void xhci_calculate_streams_entries(struct xhci_hcd *xhci, unsigned int *num_streams, unsigned int *num_stream_ctxs) { unsigned int max_streams; - - /* The stream context array size must be a power of two */ +#ifndef __UBOOT__ +/* TODO redefine this + The stream context array size must be a power of two */ *num_stream_ctxs = roundup_pow_of_two(*num_streams); +#endif /* * Find out how many primary stream array entries the host controller * supports. Later we may use secondary stream arrays (similar to 2nd @@ -3321,7 +3354,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) unsigned int slot_id; struct xhci_virt_device *virt_dev; struct xhci_command *reset_device_cmd; +#ifndef __UBOOT__ int timeleft; +#endif int last_freed_endpoint; struct xhci_slot_ctx *slot_ctx; int old_active_eps = 0; @@ -3397,7 +3432,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); - +#ifndef __UBOOT__ +/* TODO */ /* Wait for the Reset Device command to finish */ timeleft = wait_for_completion_interruptible_timeout( reset_device_cmd->completion, @@ -3415,7 +3451,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) ret = -ETIME; goto command_cleanup; } - +#endif /* The Reset Device command can't fail, according to the 0.95/0.96 spec, * unless we tried to reset a slot ID that wasn't enabled, * or the device wasn't in the addressed or configured state. @@ -3572,7 +3608,9 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); unsigned long flags; +#ifndef __UBOOT__ int timeleft; +#endif int ret; union xhci_trb *cmd_trb; @@ -3586,7 +3624,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); - +#ifndef __UBOOT__ /* XXX: how much time for xHC slot assignment? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, XHCI_CMD_DEFAULT_TIMEOUT); @@ -3596,7 +3634,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) /* cancel the enable slot request */ return xhci_cancel_cmd(xhci, NULL, cmd_trb); } - +#endif if (!xhci->slot_id) { xhci_err(xhci, "Error while assigning device slot ID\n"); return 0; @@ -3648,7 +3686,10 @@ disable_slot: int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) { unsigned long flags; +#ifndef __UBOOT__ int timeleft; + +#endif struct xhci_virt_device *virt_dev; int ret = 0; struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -3663,8 +3704,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) } virt_dev = xhci->devs[udev->slot_id]; - +#ifndef __UBOOT__ if (WARN_ON(!virt_dev)) { +#else + if (!virt_dev) { +#endif /* * In plug/unplug torture test with an NEC controller, * a zero-dereference was observed once due to virt_dev = 0. @@ -3704,7 +3748,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); - +#ifndef __UBOOT__ /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, XHCI_CMD_DEFAULT_TIMEOUT); @@ -3721,7 +3765,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return ret; return -ETIME; } - +#endif switch (virt_dev->cmd_status) { case COMP_CTX_STATE: case COMP_EBADSLT: @@ -4723,6 +4767,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_LICENSE("GPL"); +#ifndef __UBOOT__ static int __init xhci_hcd_init(void) { int retval; @@ -4767,3 +4812,4 @@ static void __exit xhci_hcd_cleanup(void) xhci_unregister_plat(); } module_exit(xhci_hcd_cleanup); +#endif diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 29c978e..330562a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -23,14 +23,26 @@ #ifndef __LINUX_XHCI_HCD_H #define __LINUX_XHCI_HCD_H +#define __UBOOT__ +#ifndef __UBOOT__ #include #include #include #include +#else + +#include +#include +#include + +#endif /* Code sharing between pci-quirks and xhci hcd */ -#include "xhci-ext-caps.h" +#include "xhci-ext-caps.h" + +#ifndef __UBOOT__ #include "pci-quirks.h" +#endif /* xHCI PCI Configuration Registers */ #define XHCI_SBRN_OFFSET (0x60) @@ -749,8 +761,10 @@ struct xhci_stream_info { struct xhci_stream_ctx *stream_ctx_array; unsigned int num_stream_ctxs; dma_addr_t ctx_array_dma; +#ifndef __UBOOT__ /* For mapping physical TRB addresses to segments in stream rings */ struct radix_tree_root trb_address_map; +#endif struct xhci_command *free_streams_command; }; @@ -913,6 +927,7 @@ struct xhci_virt_device { #define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; struct completion cmd_completion; + /* Status of the last command issued for this device */ u32 cmd_status; struct list_head cmd_list; @@ -1447,9 +1462,10 @@ struct xhci_hcd { struct xhci_scratchpad *scratchpad; /* Store LPM test failed devices' information */ struct list_head lpm_failed_devs; - +#ifndef __UBOOT__ /* slot enabling and address device helpers */ struct completion addr_dev; +#endif int slot_id; /* For USB 3.0 LPM enable/disable. */ struct xhci_command *lpm_command; diff --git a/include/asm-generic/scatterlist.h b/include/asm-generic/scatterlist.h new file mode 100644 index 0000000..5de0735 --- /dev/null +++ b/include/asm-generic/scatterlist.h @@ -0,0 +1,34 @@ +#ifndef __ASM_GENERIC_SCATTERLIST_H +#define __ASM_GENERIC_SCATTERLIST_H + +#include + +struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; + unsigned int offset; + unsigned int length; + dma_addr_t dma_address; +#ifdef CONFIG_NEED_SG_DMA_LENGTH + unsigned int dma_length; +#endif +}; + +/* + * These macros should be used after a dma_map_sg call has been done + * to get bus addresses of each of the SG entries and their lengths. + * You should only work with the number of sg entries pci_map_sg + * returns, or alternatively stop on the first sg_dma_len(sg) which + * is 0. + */ +#define sg_dma_address(sg) ((sg)->dma_address) + +#ifdef CONFIG_NEED_SG_DMA_LENGTH +#define sg_dma_len(sg) ((sg)->dma_length) +#else +#define sg_dma_len(sg) ((sg)->length) +#endif + +#endif /* __ASM_GENERIC_SCATTERLIST_H */ diff --git a/include/configs/omap5_common.h b/include/configs/omap5_common.h index 1df553e..b7c3e9f 100644 --- a/include/configs/omap5_common.h +++ b/include/configs/omap5_common.h @@ -104,6 +104,7 @@ #define CONFIG_USB_DWC3_DUAL_ROLE #define CONFIG_USB_DWC3_OMAP #define CONFIG_USB_DWC3_HOST +#define CONFIG_USB_XHCI /* Flash */ #define CONFIG_SYS_NO_FLASH diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h index 7692dc6..2eac74c 100644 --- a/include/linux/usb/ch11.h +++ b/include/linux/usb/ch11.h @@ -11,6 +11,11 @@ #include /* __u8 etc */ +#define __UBOOT__ +#ifdef __UBOOT__ +#include +#endif + /* * Hub request types */ @@ -240,6 +245,14 @@ struct usb_hub_descriptor { __le16 DeviceRemovable; } __attribute__ ((packed)) ss; } u; +#ifdef __UBOOT__ + /* For uBoot backwards compatibility */ + unsigned char bLength; + unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; + unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; + /* DeviceRemovable and PortPwrCtrlMask want to be variable-length + bitmaps that hold max 255 entries. (bit0 is ignored) */ +#endif } __attribute__ ((packed)); /* port indicator status selectors, tables 11-7 and 11-25 */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index f5f5c7d..df68955 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -19,9 +19,14 @@ #ifndef __USB_CORE_HCD_H #define __USB_CORE_HCD_H +#define __UBOOT__ #ifdef __KERNEL__ +#ifndef __UBOOT__ #include +#else +#include +#endif #define MAX_TOPO_LEVEL 6 @@ -73,8 +78,9 @@ struct usb_hcd { * housekeeping */ struct usb_bus self; /* hcd is-a bus */ +#ifndef __UBOOT__ struct kref kref; /* reference counter */ - +#endif const char *product_desc; /* product/vendor string */ int speed; /* Speed for this roothub. * May be different from @@ -135,8 +141,10 @@ struct usb_hcd { unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ +#ifndef __UBOOT__ resource_size_t rsrc_start; /* memory/io resource start */ resource_size_t rsrc_len; /* memory/io resource length */ +#endif unsigned power_budget; /* in mA, 0 = no limit */ /* bandwidth_mutex should be taken before adding or removing diff --git a/include/linux/usb/linux-compat.h b/include/linux/usb/linux-compat.h index 9850f44..81a099b 100644 --- a/include/linux/usb/linux-compat.h +++ b/include/linux/usb/linux-compat.h @@ -27,6 +27,8 @@ #include #include #include +#include + #define __init #define __devinit @@ -44,6 +46,7 @@ struct work_struct {}; struct timer_list {}; struct notifier_block {}; +typedef int wait_queue_head_t; typedef unsigned long dmaaddr_t; #define BUS_ID_SIZE 20 @@ -59,6 +62,24 @@ struct device { }; /** + * clamp_val - return a value clamped to a given range using val's type + * @val: current value + * @min: minimum allowable value + * @max: maximum allowable value + * + * This macro does no typechecking and uses temporary variables of whatever + * type the input argument 'val' is. This is useful when val is an unsigned + * type and min and max are literals that will otherwise be assigned a signed + * integer type. + */ +#define clamp_val(val, min, max) ({ \ + typeof(val) __val = (val); \ + typeof(val) __min = (min); \ + typeof(val) __max = (max); \ + __val = __val < __min ? __min: __val; \ + __val > __max ? __max: __val; }) + +/** * struct device_driver - The basic device driver structure * @name: Name of the device driver. * @bus: The bus which the device of this driver belongs to. @@ -79,6 +100,26 @@ struct device_driver { }; + +/* + * struct completion - structure used to maintain state for a "completion" + * + * This is the opaque structure used to maintain the state for a "completion". + * Completions currently use a FIFO to queue threads that have to wait for + * the "completion" event. + * + * See also: complete(), wait_for_completion() (and friends _timeout, + * _interruptible, _interruptible_timeout, and _killable), init_completion(), + * and macros DECLARE_COMPLETION(), DECLARE_COMPLETION_ONSTACK(), and + * INIT_COMPLETION(). + */ +struct completion { + unsigned int done; +#ifndef __UBOOT__ + wait_queue_head_t wait; +#endif +}; + /* * Loop over each sg element, following the pointer to a new list if necessary */ @@ -103,6 +144,8 @@ struct device_driver { printf(fmt, ##args) #define dev_err(dev, fmt, args...) \ printf(fmt, ##args) +#define dev_warn(dev, fmt, args...) \ + printf(fmt, ##args) #define printk printf #define WARN(condition, fmt, args...) ({ \ @@ -123,6 +166,8 @@ struct device_driver { /* common */ #define spin_lock_init(...) #define spin_lock(...) +#define spin_lock_irq(...) +#define spin_unlock_irq(...) #define spin_lock_irqsave(lock, flags) do { debug("%lu\n", flags); } while (0) #define spin_unlock(...) #define spin_unlock_irqrestore(lock, flags) do {flags = 0; } while (0) @@ -134,6 +179,8 @@ struct device_driver { #define mutex_unlock(...) #define GFP_KERNEL 0 +#define GFP_ATOMIC 0x20u +#define GFP_NOIO 0x10u #define IRQ_HANDLED 1 diff --git a/include/linux/usb/usb-compat.h b/include/linux/usb/usb-compat.h index a46d1e6..e99f83b 100644 --- a/include/linux/usb/usb-compat.h +++ b/include/linux/usb/usb-compat.h @@ -1529,9 +1529,9 @@ struct urb { unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ -#ifndef __UBOOT__ + struct scatterlist *sg; /* (in) scatter gather buffer list */ -#endif + int num_mapped_sgs; /* (internal) mapped sg entries */ int num_sgs; /* (in) number of entries in the sg list */ u32 transfer_buffer_length; /* (in) data buffer length */ diff --git a/include/usb.h b/include/usb.h index 0598972..6a64c5a 100644 --- a/include/usb.h +++ b/include/usb.h @@ -28,6 +28,7 @@ #include #include +#include #include /* @@ -214,15 +215,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate); default_pipe(dev) | \ USB_DIR_IN) -/* The D0/D1 toggle bits */ -#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) -#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) -#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \ - ((dev)->toggle[out] & \ - ~(1 << ep)) | ((bit) << ep)) - /* Endpoint halt control/status */ -#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) #define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) #define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) #define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) @@ -244,31 +237,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate); /************************************************************************* * Hub Stuff */ -struct usb_port_status { - unsigned short wPortStatus; - unsigned short wPortChange; -} __attribute__ ((packed)); - -struct usb_hub_status { - unsigned short wHubStatus; - unsigned short wHubChange; -} __attribute__ ((packed)); - - -/* Hub descriptor */ -struct usb_hub_descriptor { - unsigned char bLength; - unsigned char bDescriptorType; - unsigned char bNbrPorts; - unsigned short wHubCharacteristics; - unsigned char bPwrOn2PwrGood; - unsigned char bHubContrCurrent; - unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; - unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; - /* DeviceRemovable and PortPwrCtrlMask want to be variable-length - bitmaps that hold max 255 entries. (bit0 is ignored) */ -} __attribute__ ((packed)); - struct usb_hub_device { struct usb_device *pusb_dev;