diff options
Diffstat (limited to 'qemu/roms/u-boot/drivers/usb/host')
40 files changed, 0 insertions, 18263 deletions
diff --git a/qemu/roms/u-boot/drivers/usb/host/Makefile b/qemu/roms/u-boot/drivers/usb/host/Makefile deleted file mode 100644 index b301e2825..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -# ohci -obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o -obj-$(CONFIG_USB_ATMEL) += ohci-at91.o -obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o -obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o -obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o -obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o -obj-$(CONFIG_USB_OHCI_S3C24XX) += ohci-s3c24xx.o - -# echi -obj-$(CONFIG_USB_EHCI) += ehci-hcd.o -obj-$(CONFIG_USB_EHCI_ARMADA100) += ehci-armada100.o utmi-armada100.o -obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o -ifdef CONFIG_MPC512X -obj-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o -else -obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o -endif -obj-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o -obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o -obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o -obj-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o -obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o -obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o -obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o -obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o -obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o -obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o -obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o -obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o -obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o -obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o - -# xhci -obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o -obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o -obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c b/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c deleted file mode 100644 index 012eb3a1a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-armada100.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * (C) Copyright 2012 - * eInfochips Ltd. <www.einfochips.com> - * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com> - * - * This driver is based on Kirkwood echi driver - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/cpu.h> -#include <asm/arch/armada100.h> -#include <asm/arch/utmi-armada100.h> - -/* - * EHCI host controller init - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - if (utmi_init() < 0) - return -1; - - *hccr = (struct ehci_hccr *)(ARMD1_USB_HOST_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("armada100-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * EHCI host controller stop - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c b/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c deleted file mode 100644 index 9ffe5010b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-atmel.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * (C) Copyright 2012 - * Atmel Semiconductor <www.atmel.com> - * Written-by: Bo Shen <voice.shen@atmel.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <watchdog.h> -#include <usb.h> -#include <asm/io.h> -#include <asm/arch/hardware.h> -#include <asm/arch/at91_pmc.h> -#include <asm/arch/clk.h> - -#include "ehci.h" - -/* Enable UTMI PLL time out 500us - * 10 times as datasheet specified - */ -#define EN_UPLL_TIMEOUT 500UL - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - ulong start_time, tmp_time; - - start_time = get_timer(0); - /* Enable UTMI PLL */ - writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) { - WATCHDOG_RESET(); - tmp_time = get_timer(0); - if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { - printf("ERROR: failed to enable UPLL\n"); - return -1; - } - } - - /* Enable USB Host clock */ - writel(1 << ATMEL_ID_UHPHS, &pmc->pcer); - - *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI; - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - ulong start_time, tmp_time; - - /* Disable USB Host Clock */ - writel(1 << ATMEL_ID_UHPHS, &pmc->pcdr); - - start_time = get_timer(0); - /* Disable UTMI PLL */ - writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) { - WATCHDOG_RESET(); - tmp_time = get_timer(0); - if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { - printf("ERROR: failed to stop UPLL\n"); - return -1; - } - } - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c b/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c deleted file mode 100644 index edd91a84a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-exynos.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * SAMSUNG EXYNOS USB HOST EHCI Controller - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Vivek Gautam <gautam.vivek@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <malloc.h> -#include <usb.h> -#include <asm/arch/cpu.h> -#include <asm/arch/ehci.h> -#include <asm/arch/system.h> -#include <asm/arch/power.h> -#include <asm/gpio.h> -#include <asm-generic/errno.h> -#include <linux/compat.h> -#include "ehci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -/** - * Contains pointers to register base addresses - * for the usb controller. - */ -struct exynos_ehci { - struct exynos_usb_phy *usb; - struct ehci_hccr *hcd; - struct fdt_gpio_state vbus_gpio; -}; - -static struct exynos_ehci exynos; - -#ifdef CONFIG_OF_CONTROL -static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) -{ - fdt_addr_t addr; - unsigned int node; - int depth; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_EHCI); - if (node <= 0) { - debug("EHCI: Can't get device node for ehci\n"); - return -ENODEV; - } - - /* - * Get the base address for EHCI controller from the device node - */ - addr = fdtdec_get_addr(blob, node, "reg"); - if (addr == FDT_ADDR_T_NONE) { - debug("Can't get the EHCI register address\n"); - return -ENXIO; - } - - exynos->hcd = (struct ehci_hccr *)addr; - - /* Vbus gpio */ - fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio); - - depth = 0; - node = fdtdec_next_compatible_subnode(blob, node, - COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth); - if (node <= 0) { - debug("EHCI: Can't get device node for usb-phy controller\n"); - return -ENODEV; - } - - /* - * Get the base address for usbphy from the device node - */ - exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr(blob, node, - "reg"); - if (exynos->usb == NULL) { - debug("Can't get the usbphy register address\n"); - return -ENXIO; - } - - return 0; -} -#endif - -/* Setup the EHCI host controller. */ -static void setup_usb_phy(struct exynos_usb_phy *usb) -{ - u32 hsic_ctrl; - - set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN); - - set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN); - - clrbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_FSEL_MASK | - HOST_CTRL0_COMMONON_N | - /* HOST Phy setting */ - HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - setbits_le32(&usb->usbphyctrl0, - /* Setting up the ref freq */ - (CLK_24MHZ << 16) | - /* HOST Phy setting */ - HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST); - udelay(10); - clrbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST); - - /* HSIC Phy Setting */ - hsic_ctrl = (HSIC_CTRL_FORCESUSPEND | - HSIC_CTRL_FORCESLEEP | - HSIC_CTRL_SIDDQ); - - clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK) - << HSIC_CTRL_REFCLKDIV_SHIFT) - | ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK) - << HSIC_CTRL_REFCLKSEL_SHIFT) - | HSIC_CTRL_UTMISWRST); - - setbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - setbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - udelay(10); - - clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST | - HSIC_CTRL_UTMISWRST); - - clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST | - HSIC_CTRL_UTMISWRST); - - udelay(20); - - /* EHCI Ctrl setting */ - setbits_le32(&usb->ehcictrl, - EHCICTRL_ENAINCRXALIGN | - EHCICTRL_ENAINCR4 | - EHCICTRL_ENAINCR8 | - EHCICTRL_ENAINCR16); -} - -/* Reset the EHCI host controller. */ -static void reset_usb_phy(struct exynos_usb_phy *usb) -{ - u32 hsic_ctrl; - - /* HOST_PHY reset */ - setbits_le32(&usb->usbphyctrl0, - HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - /* HSIC Phy reset */ - hsic_ctrl = (HSIC_CTRL_FORCESUSPEND | - HSIC_CTRL_FORCESLEEP | - HSIC_CTRL_SIDDQ | - HSIC_CTRL_PHYSWRST); - - setbits_le32(&usb->hsicphyctrl1, hsic_ctrl); - setbits_le32(&usb->hsicphyctrl2, hsic_ctrl); - - set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE); -} - -/* - * EHCI-initialization - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct exynos_ehci *ctx = &exynos; - -#ifdef CONFIG_OF_CONTROL - if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) { - debug("Unable to parse device tree for ehci-exynos\n"); - return -ENODEV; - } -#else - ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy(); - ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci(); -#endif - -#ifdef CONFIG_OF_CONTROL - /* setup the Vbus gpio here */ - if (fdt_gpio_isvalid(&ctx->vbus_gpio) && - !fdtdec_setup_gpio(&ctx->vbus_gpio)) - gpio_direction_output(ctx->vbus_gpio.gpio, 1); -#endif - - setup_usb_phy(ctx->usb); - - board_usb_init(index, init); - - *hccr = ctx->hcd; - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - struct exynos_ehci *ctx = &exynos; - - reset_usb_phy(ctx->usb); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c b/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c deleted file mode 100644 index 3b761bc32..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-faraday.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Faraday USB 2.0 EHCI Controller - * - * (C) Copyright 2010 Faraday Technology - * Dante Su <dantesu@faraday-tech.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <usb/fusbh200.h> -#include <usb/fotg210.h> - -#include "ehci.h" - -#ifndef CONFIG_USB_EHCI_BASE_LIST -#define CONFIG_USB_EHCI_BASE_LIST { CONFIG_USB_EHCI_BASE } -#endif - -union ehci_faraday_regs { - struct fusbh200_regs usb; - struct fotg210_regs otg; -}; - -static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs) -{ - return !readl(®s->usb.easstr); -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) -{ - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - union ehci_faraday_regs *regs; - uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST; - - if (index < 0 || index >= ARRAY_SIZE(base_list)) - return -1; - regs = (void __iomem *)base_list[index]; - hccr = (struct ehci_hccr *)®s->usb.hccr; - hcor = (struct ehci_hcor *)®s->usb.hcor; - - if (ehci_is_fotg2xx(regs)) { - /* A-device bus reset */ - /* ... Power off A-device */ - setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); - /* ... Drop vbus and bus traffic */ - clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); - mdelay(1); - /* ... Power on A-device */ - clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); - /* ... Drive vbus and bus traffic */ - setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); - mdelay(1); - /* Disable OTG & DEV interrupts, triggered at level-high */ - writel(IMR_IRQLH | IMR_OTG | IMR_DEV, ®s->otg.imr); - /* Clear all interrupt status */ - writel(ISR_HOST | ISR_OTG | ISR_DEV, ®s->otg.isr); - } else { - /* Interrupt=level-high */ - setbits_le32(®s->usb.bmcsr, BMCSR_IRQLH); - /* VBUS on */ - clrbits_le32(®s->usb.bmcsr, BMCSR_VBUS_OFF); - /* Disable all interrupts */ - writel(0x00, ®s->usb.bmier); - writel(0x1f, ®s->usb.bmisr); - } - - *ret_hccr = hccr; - *ret_hcor = hcor; - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} - -/* - * This ehci_set_usbmode() overrides the weak function - * in "ehci-hcd.c". - */ -void ehci_set_usbmode(int index) -{ - /* nothing needs to be done */ -} - -/* - * This ehci_get_port_speed() overrides the weak function - * in "ehci-hcd.c". - */ -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - int spd, ret = PORTSC_PSPD_HS; - union ehci_faraday_regs *regs = (void __iomem *)((ulong)hcor - 0x10); - - if (ehci_is_fotg2xx(regs)) - spd = OTGCSR_SPD(readl(®s->otg.otgcsr)); - else - spd = BMCSR_SPD(readl(®s->usb.bmcsr)); - - switch (spd) { - case 0: /* full speed */ - ret = PORTSC_PSPD_FS; - break; - case 1: /* low speed */ - ret = PORTSC_PSPD_LS; - break; - case 2: /* high speed */ - ret = PORTSC_PSPD_HS; - break; - default: - printf("ehci-faraday: invalid device speed\n"); - break; - } - - return ret; -} - -/* - * This ehci_get_portsc_register() overrides the weak function - * in "ehci-hcd.c". - */ -uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) -{ - /* Faraday EHCI has one and only one portsc register */ - if (port) { - /* Printing the message would cause a scan failure! */ - debug("The request port(%d) is not configured\n", port); - return NULL; - } - - /* Faraday EHCI PORTSC register offset is 0x20 from hcor */ - return (uint32_t *)((uint8_t *)hcor + 0x20); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c b/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c deleted file mode 100644 index 6cb4d9866..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-fsl.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc. - * - * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB - * - * Author: Tor Krill tor@excito.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> -#include <hwconfig.h> -#include <asm/fsl_errata.h> - -#include "ehci.h" - -static void set_txfifothresh(struct usb_ehci *, u32); - -/* Check USB PHY clock valid */ -static int usb_phy_clk_valid(struct usb_ehci *ehci) -{ - if (!((in_be32(&ehci->control) & PHY_CLK_VALID) || - in_be32(&ehci->prictrl))) { - printf("USB PHY clock invalid!\n"); - return 0; - } else { - return 1; - } -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - * - * Excerpts from linux ehci fsl driver. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci = NULL; - const char *phy_type = NULL; - size_t len; - char current_usb_controller[5]; -#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY - char usb_phy[5]; - - usb_phy[0] = '\0'; -#endif - if (has_erratum_a007075()) { - /* - * A 5ms delay is needed after applying soft-reset to the - * controller to let external ULPI phy come out of reset. - * This delay needs to be added before re-initializing - * the controller after soft-resetting completes - */ - mdelay(5); - } - memset(current_usb_controller, '\0', 5); - snprintf(current_usb_controller, 4, "usb%d", index+1); - - switch (index) { - case 0: - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - break; - case 1: - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR; - break; - default: - printf("ERROR: wrong controller index!!\n"); - break; - }; - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - /* Set to Host mode */ - setbits_le32(&ehci->usbmode, CM_HOST); - - out_be32(&ehci->snoop1, SNOOP_SIZE_2GB); - out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB); - - /* Init phy */ - if (hwconfig_sub(current_usb_controller, "phy_type")) - phy_type = hwconfig_subarg(current_usb_controller, - "phy_type", &len); - else - phy_type = getenv("usb_phy_type"); - - if (!phy_type) { -#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY - /* if none specified assume internal UTMI */ - strcpy(usb_phy, "utmi"); - phy_type = usb_phy; -#else - printf("WARNING: USB phy type not defined !!\n"); - return -1; -#endif - } - - if (!strncmp(phy_type, "utmi", 4)) { -#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY) - setbits_be32(&ehci->control, PHY_CLK_SEL_UTMI); - setbits_be32(&ehci->control, UTMI_PHY_EN); - udelay(1000); /* delay required for PHY Clk to appear */ -#endif - out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI); - setbits_be32(&ehci->control, USB_EN); - } else { - setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI); - clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN); - udelay(1000); /* delay required for PHY Clk to appear */ - if (!usb_phy_clk_valid(ehci)) - return -EINVAL; - out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI); - } - - out_be32(&ehci->prictrl, 0x0000000c); - out_be32(&ehci->age_cnt_limit, 0x00000040); - out_be32(&ehci->sictrl, 0x00000001); - - in_le32(&ehci->usbmode); - - if (SVR_SOC_VER(get_svr()) == SVR_T4240 && - IS_SVR_REV(get_svr(), 2, 0)) - set_txfifothresh(ehci, TXFIFOTHRESH); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} - -/* - * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register - * to counter DDR latencies in writing data into Tx buffer. - * This prevents Tx buffer from getting underrun - */ -static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh) -{ - u32 cmd; - cmd = ehci_readl(&ehci->txfilltuning); - cmd &= ~TXFIFO_THRESH_MASK; - cmd |= TXFIFO_THRESH(txfifo_thresh); - ehci_writel(&ehci->txfilltuning, cmd); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c b/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c deleted file mode 100644 index eaf59134c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-hcd.c +++ /dev/null @@ -1,1404 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * Copyright (c) 2008, Excito Elektronik i Skåne AB - * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> -#include <errno.h> -#include <asm/byteorder.h> -#include <asm/unaligned.h> -#include <usb.h> -#include <asm/io.h> -#include <malloc.h> -#include <watchdog.h> -#include <linux/compiler.h> - -#include "ehci.h" - -#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#endif - -/* - * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt. - * Let's time out after 8 to have a little safety margin on top of that. - */ -#define HCHALT_TIMEOUT (8 * 1000) - -static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; - -#define ALIGN_END_ADDR(type, ptr, size) \ - ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) - -static struct descriptor { - struct usb_hub_descriptor hub; - struct usb_device_descriptor device; - struct usb_linux_config_descriptor config; - struct usb_linux_interface_descriptor interface; - struct usb_endpoint_descriptor endpoint; -} __attribute__ ((packed)) descriptor = { - { - 0x8, /* bDescLength */ - 0x29, /* bDescriptorType: hub descriptor */ - 2, /* bNrPorts -- runtime modified */ - 0, /* wHubCharacteristics */ - 10, /* bPwrOn2PwrGood */ - 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ - }, - { - 0x12, /* bLength */ - 1, /* bDescriptorType: UDESC_DEVICE */ - cpu_to_le16(0x0200), /* bcdUSB: v2.0 */ - 9, /* bDeviceClass: UDCLASS_HUB */ - 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ - 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ - 64, /* bMaxPacketSize: 64 bytes */ - 0x0000, /* idVendor */ - 0x0000, /* idProduct */ - cpu_to_le16(0x0100), /* bcdDevice */ - 1, /* iManufacturer */ - 2, /* iProduct */ - 0, /* iSerialNumber */ - 1 /* bNumConfigurations: 1 */ - }, - { - 0x9, - 2, /* bDescriptorType: UDESC_CONFIG */ - cpu_to_le16(0x19), - 1, /* bNumInterface */ - 1, /* bConfigurationValue */ - 0, /* iConfiguration */ - 0x40, /* bmAttributes: UC_SELF_POWER */ - 0 /* bMaxPower */ - }, - { - 0x9, /* bLength */ - 4, /* bDescriptorType: UDESC_INTERFACE */ - 0, /* bInterfaceNumber */ - 0, /* bAlternateSetting */ - 1, /* bNumEndpoints */ - 9, /* bInterfaceClass: UICLASS_HUB */ - 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ - 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ - 0 /* iInterface */ - }, - { - 0x7, /* bLength */ - 5, /* bDescriptorType: UDESC_ENDPOINT */ - 0x81, /* bEndpointAddress: - * UE_DIR_IN | EHCI_INTR_ENDPT - */ - 3, /* bmAttributes: UE_INTERRUPT */ - 8, /* wMaxPacketSize */ - 255 /* bInterval */ - }, -}; - -#if defined(CONFIG_EHCI_IS_TDI) -#define ehci_is_TDI() (1) -#else -#define ehci_is_TDI() (0) -#endif - -int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - return PORTSC_PSPD(reg); -} - -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) - __attribute__((weak, alias("__ehci_get_port_speed"))); - -void __ehci_set_usbmode(int index) -{ - uint32_t tmp; - uint32_t *reg_ptr; - - reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE); - tmp = ehci_readl(reg_ptr); - tmp |= USBMODE_CM_HC; -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) - tmp |= USBMODE_BE; -#endif - ehci_writel(reg_ptr, tmp); -} - -void ehci_set_usbmode(int index) - __attribute__((weak, alias("__ehci_set_usbmode"))); - -void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) -{ - mdelay(50); -} - -void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) - __attribute__((weak, alias("__ehci_powerup_fixup"))); - -static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) -{ - uint32_t result; - do { - result = ehci_readl(ptr); - udelay(5); - if (result == ~(uint32_t)0) - return -1; - result &= mask; - if (result == done) - return 0; - usec--; - } while (usec > 0); - return -1; -} - -static int ehci_reset(int index) -{ - uint32_t cmd; - int ret = 0; - - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - cmd = (cmd & ~CMD_RUN) | CMD_RESET; - ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); - ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd, - CMD_RESET, 0, 250 * 1000); - if (ret < 0) { - printf("EHCI fail to reset\n"); - goto out; - } - - if (ehci_is_TDI()) - ehci_set_usbmode(index); - -#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH - cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); - cmd &= ~TXFIFO_THRESH_MASK; - cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH); - ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd); -#endif -out: - return ret; -} - -static int ehci_shutdown(struct ehci_ctrl *ctrl) -{ - int i, ret = 0; - uint32_t cmd, reg; - - if (!ctrl || !ctrl->hcor) - return -EINVAL; - - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd &= ~(CMD_PSE | CMD_ASE); - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0, - 100 * 1000); - - if (!ret) { - for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { - reg = ehci_readl(&ctrl->hcor->or_portsc[i]); - reg |= EHCI_PS_SUSP; - ehci_writel(&ctrl->hcor->or_portsc[i], reg); - } - - cmd &= ~CMD_RUN; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT, - HCHALT_TIMEOUT); - } - - if (ret) - puts("EHCI failed to shut down host controller.\n"); - - return ret; -} - -static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) -{ - uint32_t delta, next; - uint32_t addr = (uint32_t)buf; - int idx; - - if (addr != ALIGN(addr, ARCH_DMA_MINALIGN)) - debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf); - - flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN)); - - idx = 0; - while (idx < QT_BUFFER_CNT) { - td->qt_buffer[idx] = cpu_to_hc32(addr); - td->qt_buffer_hi[idx] = 0; - next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1); - delta = next - addr; - if (delta >= sz) - break; - sz -= delta; - addr = next; - idx++; - } - - if (idx == QT_BUFFER_CNT) { - printf("out of buffer pointers (%u bytes left)\n", sz); - return -1; - } - - return 0; -} - -static inline u8 ehci_encode_speed(enum usb_device_speed speed) -{ - #define QH_HIGH_SPEED 2 - #define QH_FULL_SPEED 0 - #define QH_LOW_SPEED 1 - if (speed == USB_SPEED_HIGH) - return QH_HIGH_SPEED; - if (speed == USB_SPEED_LOW) - return QH_LOW_SPEED; - return QH_FULL_SPEED; -} - -static int -ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *req) -{ - ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); - struct qTD *qtd; - int qtd_count = 0; - int qtd_counter = 0; - volatile struct qTD *vtd; - unsigned long ts; - uint32_t *tdp; - uint32_t endpt, maxpacket, token, usbsts; - uint32_t c, toggle; - uint32_t cmd; - int timeout; - int ret = 0; - struct ehci_ctrl *ctrl = dev->controller; - - debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, - buffer, length, req); - if (req != NULL) - debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->value), - le16_to_cpu(req->index)); - -#define PKT_ALIGN 512 - /* - * The USB transfer is split into qTD transfers. Eeach qTD transfer is - * described by a transfer descriptor (the qTD). The qTDs form a linked - * list with a queue head (QH). - * - * Each qTD transfer starts with a new USB packet, i.e. a packet cannot - * have its beginning in a qTD transfer and its end in the following - * one, so the qTD transfer lengths have to be chosen accordingly. - * - * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to - * single pages. The first data buffer can start at any offset within a - * page (not considering the cache-line alignment issues), while the - * following buffers must be page-aligned. There is no alignment - * constraint on the size of a qTD transfer. - */ - if (req != NULL) - /* 1 qTD will be needed for SETUP, and 1 for ACK. */ - qtd_count += 1 + 1; - if (length > 0 || req == NULL) { - /* - * Determine the qTD transfer size that will be used for the - * data payload (not considering the first qTD transfer, which - * may be longer or shorter, and the final one, which may be - * shorter). - * - * In order to keep each packet within a qTD transfer, the qTD - * transfer size is aligned to PKT_ALIGN, which is a multiple of - * wMaxPacketSize (except in some cases for interrupt transfers, - * see comment in submit_int_msg()). - * - * By default, i.e. if the input buffer is aligned to PKT_ALIGN, - * QT_BUFFER_CNT full pages will be used. - */ - int xfr_sz = QT_BUFFER_CNT; - /* - * However, if the input buffer is not aligned to PKT_ALIGN, the - * qTD transfer size will be one page shorter, and the first qTD - * data buffer of each transfer will be page-unaligned. - */ - if ((uint32_t)buffer & (PKT_ALIGN - 1)) - xfr_sz--; - /* Convert the qTD transfer size to bytes. */ - xfr_sz *= EHCI_PAGE_SIZE; - /* - * Approximate by excess the number of qTDs that will be - * required for the data payload. The exact formula is way more - * complicated and saves at most 2 qTDs, i.e. a total of 128 - * bytes. - */ - qtd_count += 2 + length / xfr_sz; - } -/* - * Threshold value based on the worst-case total size of the allocated qTDs for - * a mass-storage transfer of 65535 blocks of 512 bytes. - */ -#if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 -#warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI -#endif - qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); - if (qtd == NULL) { - printf("unable to allocate TDs\n"); - return -1; - } - - memset(qh, 0, sizeof(struct QH)); - memset(qtd, 0, qtd_count * sizeof(*qtd)); - - toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); - - /* - * Setup QH (3.6 in ehci-r10.pdf) - * - * qh_link ................. 03-00 H - * qh_endpt1 ............... 07-04 H - * qh_endpt2 ............... 0B-08 H - * - qh_curtd - * qh_overlay.qt_next ...... 13-10 H - * - qh_overlay.qt_altnext - */ - qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); - c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); - maxpacket = usb_maxpacket(dev, pipe); - endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | - QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | - QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | - QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | - QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | - QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); - qh->qh_endpt1 = cpu_to_hc32(endpt); - endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_PORTNUM(dev->portnr) | - QH_ENDPT2_HUBADDR(dev->parent->devnum) | - QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); - qh->qh_endpt2 = cpu_to_hc32(endpt); - qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - - tdp = &qh->qh_overlay.qt_next; - - if (req != NULL) { - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - * - * [ buffer, buffer_hi ] loaded with "req". - */ - qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | - QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | - QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { - printf("unable to construct SETUP TD\n"); - goto fail; - } - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - toggle = 1; - } - - if (length > 0 || req == NULL) { - uint8_t *buf_ptr = buffer; - int left_length = length; - - do { - /* - * Determine the size of this qTD transfer. By default, - * QT_BUFFER_CNT full pages can be used. - */ - int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; - /* - * However, if the input buffer is not page-aligned, the - * portion of the first page before the buffer start - * offset within that page is unusable. - */ - xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1); - /* - * In order to keep each packet within a qTD transfer, - * align the qTD transfer size to PKT_ALIGN. - */ - xfr_bytes &= ~(PKT_ALIGN - 1); - /* - * This transfer may be shorter than the available qTD - * transfer size that has just been computed. - */ - xfr_bytes = min(xfr_bytes, left_length); - - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - * - * [ buffer, buffer_hi ] loaded with "buffer". - */ - qtd[qtd_counter].qt_next = - cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = - cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(toggle) | - QT_TOKEN_TOTALBYTES(xfr_bytes) | - QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | - QT_TOKEN_CERR(3) | - QT_TOKEN_PID(usb_pipein(pipe) ? - QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, - xfr_bytes)) { - printf("unable to construct DATA TD\n"); - goto fail; - } - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - /* - * Data toggle has to be adjusted since the qTD transfer - * size is not always an even multiple of - * wMaxPacketSize. - */ - if ((xfr_bytes / maxpacket) & 1) - toggle ^= 1; - buf_ptr += xfr_bytes; - left_length -= xfr_bytes; - } while (left_length > 0); - } - - if (req != NULL) { - /* - * Setup request qTD (3.5 in ehci-r10.pdf) - * - * qt_next ................ 03-00 H - * qt_altnext ............. 07-04 H - * qt_token ............... 0B-08 H - */ - qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | - QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | - QT_TOKEN_PID(usb_pipein(pipe) ? - QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | - QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); - qtd[qtd_counter].qt_token = cpu_to_hc32(token); - /* Update previous qTD! */ - *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); - tdp = &qtd[qtd_counter++].qt_next; - } - - ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH); - - /* Flush dcache */ - flush_dcache_range((uint32_t)&ctrl->qh_list, - ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); - flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); - flush_dcache_range((uint32_t)qtd, - ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); - - /* Set async. queue head pointer. */ - ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list); - - usbsts = ehci_readl(&ctrl->hcor->or_usbsts); - ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); - - /* Enable async. schedule. */ - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd |= CMD_ASE; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STS_ASS set\n"); - goto fail; - } - - /* Wait for TDs to be processed. */ - ts = get_timer(0); - vtd = &qtd[qtd_counter - 1]; - timeout = USB_TIMEOUT_MS(pipe); - do { - /* Invalidate dcache */ - invalidate_dcache_range((uint32_t)&ctrl->qh_list, - ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); - invalidate_dcache_range((uint32_t)qh, - ALIGN_END_ADDR(struct QH, qh, 1)); - invalidate_dcache_range((uint32_t)qtd, - ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); - - token = hc32_to_cpu(vtd->qt_token); - if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) - break; - WATCHDOG_RESET(); - } while (get_timer(ts) < timeout); - - /* - * Invalidate the memory area occupied by buffer - * Don't try to fix the buffer alignment, if it isn't properly - * aligned it's upper layer's fault so let invalidate_dcache_range() - * vow about it. But we have to fix the length as it's actual - * transfer length and can be unaligned. This is potentially - * dangerous operation, it's responsibility of the calling - * code to make sure enough space is reserved. - */ - invalidate_dcache_range((uint32_t)buffer, - ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN)); - - /* Check that the TD processing happened */ - if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) - printf("EHCI timed out on TD - token=%#x\n", token); - - /* Disable async schedule. */ - cmd = ehci_readl(&ctrl->hcor->or_usbcmd); - cmd &= ~CMD_ASE; - ehci_writel(&ctrl->hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, - 100 * 1000); - if (ret < 0) { - printf("EHCI fail timeout STS_ASS reset\n"); - goto fail; - } - - token = hc32_to_cpu(qh->qh_overlay.qt_token); - if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { - debug("TOKEN=%#x\n", token); - switch (QT_TOKEN_GET_STATUS(token) & - ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { - case 0: - toggle = QT_TOKEN_GET_DT(token); - usb_settoggle(dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe), toggle); - dev->status = 0; - break; - case QT_TOKEN_STATUS_HALTED: - dev->status = USB_ST_STALLED; - break; - case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: - case QT_TOKEN_STATUS_DATBUFERR: - dev->status = USB_ST_BUF_ERR; - break; - case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: - case QT_TOKEN_STATUS_BABBLEDET: - dev->status = USB_ST_BABBLE_DET; - break; - default: - dev->status = USB_ST_CRC_ERR; - if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) - dev->status |= USB_ST_STALLED; - break; - } - dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); - } else { - dev->act_len = 0; -#ifndef CONFIG_USB_EHCI_FARADAY - debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", - dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), - ehci_readl(&ctrl->hcor->or_portsc[0]), - ehci_readl(&ctrl->hcor->or_portsc[1])); -#endif - } - - free(qtd); - return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; - -fail: - free(qtd); - return -1; -} - -__weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) -{ - if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - /* Printing the message would cause a scan failure! */ - debug("The request port(%u) is not configured\n", port); - return NULL; - } - - return (uint32_t *)&hcor->or_portsc[port]; -} - -int -ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *req) -{ - uint8_t tmpbuf[4]; - u16 typeReq; - void *srcptr = NULL; - int len, srclen; - uint32_t reg; - uint32_t *status_reg; - int port = le16_to_cpu(req->index) & 0xff; - struct ehci_ctrl *ctrl = dev->controller; - - srclen = 0; - - debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->index)); - - typeReq = req->request | req->requesttype << 8; - - switch (typeReq) { - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); - if (!status_reg) - return -1; - break; - default: - status_reg = NULL; - break; - } - - switch (typeReq) { - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_DEVICE: - debug("USB_DT_DEVICE request\n"); - srcptr = &descriptor.device; - srclen = descriptor.device.bLength; - break; - case USB_DT_CONFIG: - debug("USB_DT_CONFIG config\n"); - srcptr = &descriptor.config; - srclen = descriptor.config.bLength + - descriptor.interface.bLength + - descriptor.endpoint.bLength; - break; - case USB_DT_STRING: - debug("USB_DT_STRING config\n"); - switch (le16_to_cpu(req->value) & 0xff) { - case 0: /* Language */ - srcptr = "\4\3\1\0"; - srclen = 4; - break; - case 1: /* Vendor */ - srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; - srclen = 14; - break; - case 2: /* Product */ - srcptr = "\52\3E\0H\0C\0I\0 " - "\0H\0o\0s\0t\0 " - "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; - srclen = 42; - break; - default: - debug("unknown value DT_STRING %x\n", - le16_to_cpu(req->value)); - goto unknown; - } - break; - default: - debug("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_HUB: - debug("USB_DT_HUB config\n"); - srcptr = &descriptor.hub; - srclen = descriptor.hub.bLength; - break; - default: - debug("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): - debug("USB_REQ_SET_ADDRESS\n"); - ctrl->rootdev = le16_to_cpu(req->value); - break; - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - debug("USB_REQ_SET_CONFIGURATION\n"); - /* Nothing to do */ - break; - case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): - tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ - tmpbuf[1] = 0; - srcptr = tmpbuf; - srclen = 2; - break; - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - memset(tmpbuf, 0, 4); - reg = ehci_readl(status_reg); - if (reg & EHCI_PS_CS) - tmpbuf[0] |= USB_PORT_STAT_CONNECTION; - if (reg & EHCI_PS_PE) - tmpbuf[0] |= USB_PORT_STAT_ENABLE; - if (reg & EHCI_PS_SUSP) - tmpbuf[0] |= USB_PORT_STAT_SUSPEND; - if (reg & EHCI_PS_OCA) - tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; - if (reg & EHCI_PS_PR) - tmpbuf[0] |= USB_PORT_STAT_RESET; - if (reg & EHCI_PS_PP) - tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - - if (ehci_is_TDI()) { - switch (ehci_get_port_speed(ctrl->hcor, reg)) { - case PORTSC_PSPD_FS: - break; - case PORTSC_PSPD_LS: - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case PORTSC_PSPD_HS: - default: - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - } - } else { - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - } - - if (reg & EHCI_PS_CSC) - tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; - if (reg & EHCI_PS_PEC) - tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; - if (reg & EHCI_PS_OCC) - tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; - if (ctrl->portreset & (1 << port)) - tmpbuf[2] |= USB_PORT_STAT_C_RESET; - - srcptr = tmpbuf; - srclen = 4; - break; - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = ehci_readl(status_reg); - reg &= ~EHCI_PS_CLEAR; - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg |= EHCI_PS_PE; - ehci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { - reg |= EHCI_PS_PP; - ehci_writel(status_reg, reg); - } - break; - case USB_PORT_FEAT_RESET: - if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && - !ehci_is_TDI() && - EHCI_PS_IS_LOWSPEED(reg)) { - /* Low speed device, give up ownership. */ - debug("port %d low speed --> companion\n", - port - 1); - reg |= EHCI_PS_PO; - ehci_writel(status_reg, reg); - break; - } else { - int ret; - - reg |= EHCI_PS_PR; - reg &= ~EHCI_PS_PE; - ehci_writel(status_reg, reg); - /* - * caller must wait, then call GetPortStatus - * usb 2.0 specification say 50 ms resets on - * root - */ - ehci_powerup_fixup(status_reg, ®); - - ehci_writel(status_reg, reg & ~EHCI_PS_PR); - /* - * A host controller must terminate the reset - * and stabilize the state of the port within - * 2 milliseconds - */ - ret = handshake(status_reg, EHCI_PS_PR, 0, - 2 * 1000); - if (!ret) - ctrl->portreset |= 1 << port; - else - printf("port(%d) reset error\n", - port - 1); - } - break; - case USB_PORT_FEAT_TEST: - ehci_shutdown(ctrl); - reg &= ~(0xf << 16); - reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16; - ehci_writel(status_reg, reg); - break; - default: - debug("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - /* unblock posted writes */ - (void) ehci_readl(&ctrl->hcor->or_usbcmd); - break; - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = ehci_readl(status_reg); - reg &= ~EHCI_PS_CLEAR; - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg &= ~EHCI_PS_PE; - break; - case USB_PORT_FEAT_C_ENABLE: - reg |= EHCI_PS_PE; - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) - reg &= ~EHCI_PS_PP; - break; - case USB_PORT_FEAT_C_CONNECTION: - reg |= EHCI_PS_CSC; - break; - case USB_PORT_FEAT_OVER_CURRENT: - reg |= EHCI_PS_OCC; - break; - case USB_PORT_FEAT_C_RESET: - ctrl->portreset &= ~(1 << port); - break; - default: - debug("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - ehci_writel(status_reg, reg); - /* unblock posted write */ - (void) ehci_readl(&ctrl->hcor->or_usbcmd); - break; - default: - debug("Unknown request\n"); - goto unknown; - } - - mdelay(1); - len = min3(srclen, le16_to_cpu(req->length), length); - if (srcptr != NULL && len > 0) - memcpy(buffer, srcptr, len); - else - debug("Len is 0\n"); - - dev->act_len = len; - dev->status = 0; - return 0; - -unknown: - debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n", - req->requesttype, req->request, le16_to_cpu(req->value), - le16_to_cpu(req->index), le16_to_cpu(req->length)); - - dev->act_len = 0; - dev->status = USB_ST_STALLED; - return -1; -} - -int usb_lowlevel_stop(int index) -{ - ehci_shutdown(&ehcic[index]); - return ehci_hcd_stop(index); -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - uint32_t reg; - uint32_t cmd; - struct QH *qh_list; - struct QH *periodic; - int i; - int rc; - - rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); - if (rc) - return rc; - if (init == USB_INIT_DEVICE) - goto done; - - /* EHCI spec section 4.1 */ - if (ehci_reset(index)) - return -1; - -#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET) - rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); - if (rc) - return rc; -#endif - /* Set the high address word (aka segment) for 64-bit controller */ - if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1) - ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0); - - qh_list = &ehcic[index].qh_list; - - /* Set head of reclaim list */ - memset(qh_list, 0, sizeof(*qh_list)); - qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH); - qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) | - QH_ENDPT1_EPS(USB_SPEED_HIGH)); - qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - qh_list->qh_overlay.qt_token = - cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); - - flush_dcache_range((uint32_t)qh_list, - ALIGN_END_ADDR(struct QH, qh_list, 1)); - - /* Set async. queue head pointer. */ - ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); - - /* - * Set up periodic list - * Step 1: Parent QH for all periodic transfers. - */ - periodic = &ehcic[index].periodic_queue; - memset(periodic, 0, sizeof(*periodic)); - periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); - periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - - flush_dcache_range((uint32_t)periodic, - ALIGN_END_ADDR(struct QH, periodic, 1)); - - /* - * Step 2: Setup frame-list: Every microframe, USB tries the same list. - * In particular, device specifications on polling frequency - * are disregarded. Keyboards seem to send NAK/NYet reliably - * when polled with an empty buffer. - * - * Split Transactions will be spread across microframes using - * S-mask and C-mask. - */ - if (ehcic[index].periodic_list == NULL) - ehcic[index].periodic_list = memalign(4096, 1024 * 4); - - if (!ehcic[index].periodic_list) - return -ENOMEM; - for (i = 0; i < 1024; i++) { - ehcic[index].periodic_list[i] = cpu_to_hc32((uint32_t)periodic - | QH_LINK_TYPE_QH); - } - - flush_dcache_range((uint32_t)ehcic[index].periodic_list, - ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, - 1024)); - - /* Set periodic list base address */ - ehci_writel(&ehcic[index].hcor->or_periodiclistbase, - (uint32_t)ehcic[index].periodic_list); - - reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams); - descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); - debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); - /* Port Indicators */ - if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); - /* Port Power Control */ - if (HCS_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); - - /* Start the host controller. */ - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - /* - * Philips, Intel, and maybe others need CMD_RUN before the - * root hub will detect new devices (why?); NEC doesn't - */ - cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - cmd |= CMD_RUN; - ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); - -#ifndef CONFIG_USB_EHCI_FARADAY - /* take control over the ports */ - cmd = ehci_readl(&ehcic[index].hcor->or_configflag); - cmd |= FLAG_CF; - ehci_writel(&ehcic[index].hcor->or_configflag, cmd); -#endif - - /* unblock posted write */ - cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); - mdelay(5); - reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase)); - printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); - - ehcic[index].rootdev = 0; -done: - *controller = &ehcic[index]; - return 0; -} - -int -submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length) -{ - - if (usb_pipetype(pipe) != PIPE_BULK) { - debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); - return -1; - } - return ehci_submit_async(dev, pipe, buffer, length, NULL); -} - -int -submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) -{ - struct ehci_ctrl *ctrl = dev->controller; - - if (usb_pipetype(pipe) != PIPE_CONTROL) { - debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); - return -1; - } - - if (usb_pipedevice(pipe) == ctrl->rootdev) { - if (!ctrl->rootdev) - dev->speed = USB_SPEED_HIGH; - return ehci_submit_root(dev, pipe, buffer, length, setup); - } - return ehci_submit_async(dev, pipe, buffer, length, setup); -} - -struct int_queue { - struct QH *first; - struct QH *current; - struct QH *last; - struct qTD *tds; -}; - -#define NEXT_QH(qh) (struct QH *)(hc32_to_cpu((qh)->qh_link) & ~0x1f) - -static int -enable_periodic(struct ehci_ctrl *ctrl) -{ - uint32_t cmd; - struct ehci_hcor *hcor = ctrl->hcor; - int ret; - - cmd = ehci_readl(&hcor->or_usbcmd); - cmd |= CMD_PSE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, - STS_PSS, STS_PSS, 100 * 1000); - if (ret < 0) { - printf("EHCI failed: timeout when enabling periodic list\n"); - return -ETIMEDOUT; - } - udelay(1000); - return 0; -} - -static int -disable_periodic(struct ehci_ctrl *ctrl) -{ - uint32_t cmd; - struct ehci_hcor *hcor = ctrl->hcor; - int ret; - - cmd = ehci_readl(&hcor->or_usbcmd); - cmd &= ~CMD_PSE; - ehci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake((uint32_t *)&hcor->or_usbsts, - STS_PSS, 0, 100 * 1000); - if (ret < 0) { - printf("EHCI failed: timeout when disabling periodic list\n"); - return -ETIMEDOUT; - } - return 0; -} - -static int periodic_schedules; - -struct int_queue * -create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, - int elementsize, void *buffer) -{ - struct ehci_ctrl *ctrl = dev->controller; - struct int_queue *result = NULL; - int i; - - debug("Enter create_int_queue\n"); - if (usb_pipetype(pipe) != PIPE_INTERRUPT) { - debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); - return NULL; - } - - /* limit to 4 full pages worth of data - - * we can safely fit them in a single TD, - * no matter the alignment - */ - if (elementsize >= 16384) { - debug("too large elements for interrupt transfers\n"); - return NULL; - } - - result = malloc(sizeof(*result)); - if (!result) { - debug("ehci intr queue: out of memory\n"); - goto fail1; - } - result->first = memalign(USB_DMA_MINALIGN, - sizeof(struct QH) * queuesize); - if (!result->first) { - debug("ehci intr queue: out of memory\n"); - goto fail2; - } - result->current = result->first; - result->last = result->first + queuesize - 1; - result->tds = memalign(USB_DMA_MINALIGN, - sizeof(struct qTD) * queuesize); - if (!result->tds) { - debug("ehci intr queue: out of memory\n"); - goto fail3; - } - memset(result->first, 0, sizeof(struct QH) * queuesize); - memset(result->tds, 0, sizeof(struct qTD) * queuesize); - - for (i = 0; i < queuesize; i++) { - struct QH *qh = result->first + i; - struct qTD *td = result->tds + i; - void **buf = &qh->buffer; - - qh->qh_link = cpu_to_hc32((uint32_t)(qh+1) | QH_LINK_TYPE_QH); - if (i == queuesize - 1) - qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); - - qh->qh_overlay.qt_next = cpu_to_hc32((uint32_t)td); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_endpt1 = - cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */ - (usb_maxpacket(dev, pipe) << 16) | /* MPS */ - (1 << 14) | - QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | - (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */ - (usb_pipedevice(pipe) << 0)); - qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */ - (1 << 0)); /* S-mask: microframe 0 */ - if (dev->speed == USB_SPEED_LOW || - dev->speed == USB_SPEED_FULL) { - debug("TT: port: %d, hub address: %d\n", - dev->portnr, dev->parent->devnum); - qh->qh_endpt2 |= cpu_to_hc32((dev->portnr << 23) | - (dev->parent->devnum << 16) | - (0x1c << 8)); /* C-mask: microframes 2-4 */ - } - - td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - debug("communication direction is '%s'\n", - usb_pipein(pipe) ? "in" : "out"); - td->qt_token = cpu_to_hc32((elementsize << 16) | - ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ - 0x80); /* active */ - td->qt_buffer[0] = - cpu_to_hc32((uint32_t)buffer + i * elementsize); - td->qt_buffer[1] = - cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff); - td->qt_buffer[2] = - cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff); - td->qt_buffer[3] = - cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff); - td->qt_buffer[4] = - cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff); - - *buf = buffer + i * elementsize; - } - - flush_dcache_range((uint32_t)buffer, - ALIGN_END_ADDR(char, buffer, - queuesize * elementsize)); - flush_dcache_range((uint32_t)result->first, - ALIGN_END_ADDR(struct QH, result->first, - queuesize)); - flush_dcache_range((uint32_t)result->tds, - ALIGN_END_ADDR(struct qTD, result->tds, - queuesize)); - - if (disable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto fail3; - } - - /* hook up to periodic list */ - struct QH *list = &ctrl->periodic_queue; - result->last->qh_link = list->qh_link; - list->qh_link = cpu_to_hc32((uint32_t)result->first | QH_LINK_TYPE_QH); - - flush_dcache_range((uint32_t)result->last, - ALIGN_END_ADDR(struct QH, result->last, 1)); - flush_dcache_range((uint32_t)list, - ALIGN_END_ADDR(struct QH, list, 1)); - - if (enable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto fail3; - } - periodic_schedules++; - - debug("Exit create_int_queue\n"); - return result; -fail3: - if (result->tds) - free(result->tds); -fail2: - if (result->first) - free(result->first); - if (result) - free(result); -fail1: - return NULL; -} - -void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) -{ - struct QH *cur = queue->current; - - /* depleted queue */ - if (cur == NULL) { - debug("Exit poll_int_queue with completed queue\n"); - return NULL; - } - /* still active */ - invalidate_dcache_range((uint32_t)cur, - ALIGN_END_ADDR(struct QH, cur, 1)); - if (cur->qh_overlay.qt_token & cpu_to_hc32(0x80)) { - debug("Exit poll_int_queue with no completed intr transfer. " - "token is %x\n", cur->qh_overlay.qt_token); - return NULL; - } - if (!(cur->qh_link & QH_LINK_TERMINATE)) - queue->current++; - else - queue->current = NULL; - debug("Exit poll_int_queue with completed intr transfer. " - "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token, - &cur->qh_overlay.qt_token, queue->first); - return cur->buffer; -} - -/* Do not free buffers associated with QHs, they're owned by someone else */ -int -destroy_int_queue(struct usb_device *dev, struct int_queue *queue) -{ - struct ehci_ctrl *ctrl = dev->controller; - int result = -1; - unsigned long timeout; - - if (disable_periodic(ctrl) < 0) { - debug("FATAL: periodic should never fail, but did"); - goto out; - } - periodic_schedules--; - - struct QH *cur = &ctrl->periodic_queue; - timeout = get_timer(0) + 500; /* abort after 500ms */ - while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) { - debug("considering %p, with qh_link %x\n", cur, cur->qh_link); - if (NEXT_QH(cur) == queue->first) { - debug("found candidate. removing from chain\n"); - cur->qh_link = queue->last->qh_link; - result = 0; - break; - } - cur = NEXT_QH(cur); - if (get_timer(0) > timeout) { - printf("Timeout destroying interrupt endpoint queue\n"); - result = -1; - goto out; - } - } - - if (periodic_schedules > 0) { - result = enable_periodic(ctrl); - if (result < 0) - debug("FATAL: periodic should never fail, but did"); - } - -out: - free(queue->tds); - free(queue->first); - free(queue); - - return result; -} - -int -submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, int interval) -{ - void *backbuffer; - struct int_queue *queue; - unsigned long timeout; - int result = 0, ret; - - debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", - dev, pipe, buffer, length, interval); - - /* - * Interrupt transfers requiring several transactions are not supported - * because bInterval is ignored. - * - * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2 - * <= PKT_ALIGN if several qTDs are required, while the USB - * specification does not constrain this for interrupt transfers. That - * means that ehci_submit_async() would support interrupt transfers - * requiring several transactions only as long as the transfer size does - * not require more than a single qTD. - */ - if (length > usb_maxpacket(dev, pipe)) { - printf("%s: Interrupt transfers requiring several " - "transactions are not supported.\n", __func__); - return -1; - } - - queue = create_int_queue(dev, pipe, 1, length, buffer); - - timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); - while ((backbuffer = poll_int_queue(dev, queue)) == NULL) - if (get_timer(0) > timeout) { - printf("Timeout poll on interrupt endpoint\n"); - result = -ETIMEDOUT; - break; - } - - if (backbuffer != buffer) { - debug("got wrong buffer back (%x instead of %x)\n", - (uint32_t)backbuffer, (uint32_t)buffer); - return -EINVAL; - } - - invalidate_dcache_range((uint32_t)buffer, - ALIGN_END_ADDR(char, buffer, length)); - - ret = destroy_int_queue(dev, queue); - if (ret < 0) - return ret; - - /* everything worked out fine */ - return result; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c b/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c deleted file mode 100644 index 52c43fdc5..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-marvell.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/cpu.h> - -#if defined(CONFIG_KIRKWOOD) -#include <asm/arch/kirkwood.h> -#elif defined(CONFIG_ORION5X) -#include <asm/arch/orion5x.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -#define rdl(off) readl(MVUSB0_BASE + (off)) -#define wrl(off, val) writel((val), MVUSB0_BASE + (off)) - -#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4)) -#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4)) -#define USB_TARGET_DRAM 0x0 - -/* - * USB 2.0 Bridge Address Decoding registers setup - */ -static void usb_brg_adrdec_setup(void) -{ - int i; - u32 size, base, attrib; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - - /* Enable DRAM bank */ - switch (i) { - case 0: - attrib = MVUSB0_CPU_ATTR_DRAM_CS0; - break; - case 1: - attrib = MVUSB0_CPU_ATTR_DRAM_CS1; - break; - case 2: - attrib = MVUSB0_CPU_ATTR_DRAM_CS2; - break; - case 3: - attrib = MVUSB0_CPU_ATTR_DRAM_CS3; - break; - default: - /* invalide bank, disable access */ - attrib = 0; - break; - } - - size = gd->bd->bi_dram[i].size; - base = gd->bd->bi_dram[i].start; - if ((size) && (attrib)) - wrl(USB_WINDOW_CTRL(i), - MVCPU_WIN_CTRL_DATA(size, USB_TARGET_DRAM, - attrib, MVCPU_WIN_ENABLE)); - else - wrl(USB_WINDOW_CTRL(i), MVCPU_WIN_DISABLE); - - wrl(USB_WINDOW_BASE(i), base); - } -} - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - usb_brg_adrdec_setup(); - - *hccr = (struct ehci_hccr *)(MVUSB0_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c deleted file mode 100644 index b320c4a4e..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * (C) Copyright 2010, Damien Dusha, <d.dusha@gmail.com> - * - * (C) Copyright 2009, Value Team S.p.A. - * Francesco Rendine, <francesco.rendine@valueteam.com> - * - * (C) Copyright 2009 Freescale Semiconductor, Inc. - * - * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB - * - * Author: Tor Krill tor@excito.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci.h> -#include <usb.h> -#include <asm/io.h> -#include <usb/ehci-fsl.h> - -#include "ehci.h" - -static void fsl_setup_phy(volatile struct ehci_hcor *); -static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci); -static int reset_usb_controller(volatile struct usb_ehci *ehci); -static void usb_platform_dr_init(volatile struct usb_ehci *ehci); - -/* - * Initialize SOC FSL EHCI Controller - * - * This code is derived from EHCI FSL USB Linux driver for MPC5121 - * - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - volatile struct usb_ehci *ehci; - - /* Hook the memory mapped registers for EHCI-Controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - *hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength)); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - /* configure interface for UTMI_WIDE */ - usb_platform_dr_init(ehci); - - /* Init Phy USB0 to UTMI+ */ - fsl_setup_phy(*hcor); - - /* Set to host mode */ - fsl_platform_set_host_mode(ehci); - - /* - * Setting the burst size seems to be required to prevent the - * USB from hanging when communicating with certain USB Mass - * storage devices. This was determined by analysing the - * EHCI registers under Linux vs U-Boot and burstsize was the - * major non-interrupt related difference between the two - * implementations. - * - * Some USB sticks behave better than others. In particular, - * the following USB stick is especially problematic: - * 0930:6545 Toshiba Corp - * - * The burstsize is set here to match the Linux implementation. - */ - out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) | - FSL_EHCI_RXPBURST(8)); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - volatile struct usb_ehci *ehci; - int exit_status = 0; - - /* Reset the USB controller */ - ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; - exit_status = reset_usb_controller(ehci); - - return exit_status; -} - -static int reset_usb_controller(volatile struct usb_ehci *ehci) -{ - unsigned int i; - - /* Command a reset of the USB Controller */ - out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST); - - /* Wait for the reset process to finish */ - for (i = 65535 ; i > 0 ; i--) { - /* - * The host will set this bit to zero once the - * reset process is complete - */ - if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0) - return 0; - } - - /* Hub did not reset in time */ - return -1; -} - -static void fsl_setup_phy(volatile struct ehci_hcor *hcor) -{ - uint32_t portsc; - - portsc = ehci_readl(&hcor->or_portsc[0]); - portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); - - /* Enable the phy mode to UTMI Wide */ - portsc |= PORT_PTS_PTW; - portsc |= PORT_PTS_UTMI; - - ehci_writel(&hcor->or_portsc[0], portsc); -} - -static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci) -{ - uint32_t temp; - - temp = in_le32(&ehci->usbmode); - temp |= CM_HOST | ES_BE; - out_le32(&ehci->usbmode, temp); -} - -static void usb_platform_dr_init(volatile struct usb_ehci *ehci) -{ - /* Configure interface for UTMI_WIDE */ - out_be32(&ehci->isiphyctrl, PHYCTRL_PHYE | PHYCTRL_PXE); - out_be32(&ehci->usbgenctrl, GC_PPP | GC_PFP ); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c deleted file mode 100644 index 7566c6128..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mx5.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * Copyright (C) 2010 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <errno.h> -#include <linux/compiler.h> -#include <usb/ehci-fsl.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> - -#include "ehci.h" - -#define MX5_USBOTHER_REGS_OFFSET 0x800 - - -#define MXC_OTG_OFFSET 0 -#define MXC_H1_OFFSET 0x200 -#define MXC_H2_OFFSET 0x400 -#define MXC_H3_OFFSET 0x600 - -#define MXC_USBCTRL_OFFSET 0 -#define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8 -#define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc -#define MXC_USB_CTRL_1_OFFSET 0x10 -#define MXC_USBH2CTRL_OFFSET 0x14 -#define MXC_USBH3CTRL_OFFSET 0x18 - -/* USB_CTRL */ -/* OTG wakeup intr enable */ -#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) -/* OTG power mask */ -#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) -/* OTG power pin polarity */ -#define MXC_OTG_UCTRL_O_PWR_POL_BIT (1 << 24) -/* Host1 ULPI interrupt enable */ -#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) -/* HOST1 wakeup intr enable */ -#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) -/* HOST1 power mask */ -#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) -/* HOST1 power pin polarity */ -#define MXC_H1_UCTRL_H1_PWR_POL_BIT (1 << 8) - -/* USB_PHY_CTRL_FUNC */ -/* OTG Polarity of Overcurrent */ -#define MXC_OTG_PHYCTRL_OC_POL_BIT (1 << 9) -/* OTG Disable Overcurrent Event */ -#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) -/* UH1 Polarity of Overcurrent */ -#define MXC_H1_OC_POL_BIT (1 << 6) -/* UH1 Disable Overcurrent Event */ -#define MXC_H1_OC_DIS_BIT (1 << 5) -/* OTG Power Pin Polarity */ -#define MXC_OTG_PHYCTRL_PWR_POL_BIT (1 << 3) - -/* USBH2CTRL */ -#define MXC_H2_UCTRL_H2_OC_POL_BIT (1 << 31) -#define MXC_H2_UCTRL_H2_OC_DIS_BIT (1 << 30) -#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) -#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) -#define MXC_H2_UCTRL_H2PM_BIT (1 << 4) -#define MXC_H2_UCTRL_H2_PWR_POL_BIT (1 << 4) - -/* USBH3CTRL */ -#define MXC_H3_UCTRL_H3_OC_POL_BIT (1 << 31) -#define MXC_H3_UCTRL_H3_OC_DIS_BIT (1 << 30) -#define MXC_H3_UCTRL_H3UIE_BIT (1 << 8) -#define MXC_H3_UCTRL_H3WIE_BIT (1 << 7) -#define MXC_H3_UCTRL_H3_PWR_POL_BIT (1 << 4) - -/* USB_CTRL_1 */ -#define MXC_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -int mxc_set_usbcontrol(int port, unsigned int flags) -{ - unsigned int v; - void __iomem *usb_base = (void __iomem *)OTG_BASE_ADDR; - void __iomem *usbother_base; - int ret = 0; - - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - switch (port) { - case 0: /* OTG port */ - if (flags & MXC_EHCI_INTERNAL_PHY) { - v = __raw_readl(usbother_base + - MXC_USB_PHY_CTR_FUNC_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_OTG_PHYCTRL_OC_POL_BIT; - else - v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - /* OC/USBPWR is used */ - v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; - else - /* OC/USBPWR is not used */ - v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_OTG_PHYCTRL_PWR_POL_BIT; - else - v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + - MXC_USB_PHY_CTR_FUNC_OFFSET); - - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_OTG_UCTRL_OPM_BIT; - else - v |= MXC_OTG_UCTRL_OPM_BIT; -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_OTG_UCTRL_O_PWR_POL_BIT; - else - v &= ~MXC_OTG_UCTRL_O_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - } - break; - case 1: /* Host 1 ULPI */ -#ifdef CONFIG_MX51 - /* The clock for the USBH1 ULPI port will come externally - from the PHY. */ - v = __raw_readl(usbother_base + MXC_USB_CTRL_1_OFFSET); - __raw_writel(v | MXC_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + - MXC_USB_CTRL_1_OFFSET); -#endif - - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask unused */ - else - v |= MXC_H1_UCTRL_H1PM_BIT; /* H1 power mask used */ -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H1_UCTRL_H1_PWR_POL_BIT; - else - v &= ~MXC_H1_UCTRL_H1_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H1_OC_POL_BIT; - else - v &= ~MXC_H1_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - - break; - case 2: /* Host 2 ULPI */ - v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); -#ifdef CONFIG_MX51 - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask unused */ - else - v |= MXC_H2_UCTRL_H2PM_BIT; /* H2 power mask used */ -#endif -#ifdef CONFIG_MX53 - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H2_UCTRL_H2_OC_POL_BIT; - else - v &= ~MXC_H2_UCTRL_H2_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H2_UCTRL_H2_OC_DIS_BIT; /* OC is not used */ - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H2_UCTRL_H2_PWR_POL_BIT; - else - v &= ~MXC_H2_UCTRL_H2_PWR_POL_BIT; -#endif - __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); - break; -#ifdef CONFIG_MX53 - case 3: /* Host 3 ULPI */ - v = __raw_readl(usbother_base + MXC_USBH3CTRL_OFFSET); - if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) - v |= MXC_H3_UCTRL_H3_OC_POL_BIT; - else - v &= ~MXC_H3_UCTRL_H3_OC_POL_BIT; - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H3_UCTRL_H3_OC_DIS_BIT; /* OC is not used */ - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MXC_H3_UCTRL_H3_PWR_POL_BIT; - else - v &= ~MXC_H3_UCTRL_H3_PWR_POL_BIT; - __raw_writel(v, usbother_base + MXC_USBH3CTRL_OFFSET); - break; -#endif - } - - return ret; -} - -int __weak board_ehci_hcd_init(int port) -{ - return 0; -} - -void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) -{ -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci; - - set_usboh3_clk(); - enable_usboh3_clk(true); - set_usb_phy_clk(); - enable_usb_phy1_clk(true); - enable_usb_phy2_clk(true); - mdelay(1); - - /* Do board specific initialization */ - board_ehci_hcd_init(CONFIG_MXC_USB_PORT); - - ehci = (struct usb_ehci *)(OTG_BASE_ADDR + - (0x200 * CONFIG_MXC_USB_PORT)); - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - setbits_le32(&ehci->usbmode, CM_HOST); - - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - setbits_le32(&ehci->portsc, USB_EN); - - mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); - mdelay(10); - - /* Do board specific post-initialization */ - board_ehci_hcd_postinit(ehci, CONFIG_MXC_USB_PORT); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c deleted file mode 100644 index c0a557b2a..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mx6.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * Copyright (C) 2010 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <errno.h> -#include <linux/compiler.h> -#include <usb/ehci-fsl.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> -#include <asm/imx-common/iomux-v3.h> - -#include "ehci.h" - -#define USB_OTGREGS_OFFSET 0x000 -#define USB_H1REGS_OFFSET 0x200 -#define USB_H2REGS_OFFSET 0x400 -#define USB_H3REGS_OFFSET 0x600 -#define USB_OTHERREGS_OFFSET 0x800 - -#define USB_H1_CTRL_OFFSET 0x04 - -#define USBPHY_CTRL 0x00000030 -#define USBPHY_CTRL_SET 0x00000034 -#define USBPHY_CTRL_CLR 0x00000038 -#define USBPHY_CTRL_TOG 0x0000003c - -#define USBPHY_PWD 0x00000000 -#define USBPHY_CTRL_SFTRST 0x80000000 -#define USBPHY_CTRL_CLKGATE 0x40000000 -#define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 -#define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 -#define USBPHY_CTRL_OTG_ID 0x08000000 - -#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 -#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 - -#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 -#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 -#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 -#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 - - -#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ -#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ - -/* USBCMD */ -#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ -#define UCMD_RESET (1 << 1) /* controller reset */ - -static const unsigned phy_bases[] = { - USB_PHY0_BASE_ADDR, - USB_PHY1_BASE_ADDR, -}; - -static void usb_internal_phy_clock_gate(int index, int on) -{ - void __iomem *phy_reg; - - if (index >= ARRAY_SIZE(phy_bases)) - return; - - phy_reg = (void __iomem *)phy_bases[index]; - phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; - __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg); -} - -static void usb_power_config(int index) -{ - struct anatop_regs __iomem *anatop = - (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; - void __iomem *chrg_detect; - void __iomem *pll_480_ctrl_clr; - void __iomem *pll_480_ctrl_set; - - switch (index) { - case 0: - chrg_detect = &anatop->usb1_chrg_detect; - pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; - pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; - break; - case 1: - chrg_detect = &anatop->usb2_chrg_detect; - pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; - pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; - break; - default: - return; - } - /* - * Some phy and power's special controls - * 1. The external charger detector needs to be disabled - * or the signal at DP will be poor - * 2. The PLL's power and output to usb - * is totally controlled by IC, so the Software only needs - * to enable them at initializtion. - */ - __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | - ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, - chrg_detect); - - __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, - pll_480_ctrl_clr); - - __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | - ANADIG_USB2_PLL_480_CTRL_POWER | - ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, - pll_480_ctrl_set); -} - -/* Return 0 : host node, <>0 : device mode */ -static int usb_phy_enable(int index, struct usb_ehci *ehci) -{ - void __iomem *phy_reg; - void __iomem *phy_ctrl; - void __iomem *usb_cmd; - u32 val; - - if (index >= ARRAY_SIZE(phy_bases)) - return 0; - - phy_reg = (void __iomem *)phy_bases[index]; - phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); - usb_cmd = (void __iomem *)&ehci->usbcmd; - - /* Stop then Reset */ - val = __raw_readl(usb_cmd); - val &= ~UCMD_RUN_STOP; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) - ; - - val = __raw_readl(usb_cmd); - val |= UCMD_RESET; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RESET) - ; - - /* Reset USBPHY module */ - val = __raw_readl(phy_ctrl); - val |= USBPHY_CTRL_SFTRST; - __raw_writel(val, phy_ctrl); - udelay(10); - - /* Remove CLKGATE and SFTRST */ - val = __raw_readl(phy_ctrl); - val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); - __raw_writel(val, phy_ctrl); - udelay(10); - - /* Power up the PHY */ - __raw_writel(0, phy_reg + USBPHY_PWD); - /* enable FS/LS device */ - val = __raw_readl(phy_ctrl); - val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); - __raw_writel(val, phy_ctrl); - - return val & USBPHY_CTRL_OTG_ID; -} - -/* Base address for this IP block is 0x02184800 */ -struct usbnc_regs { - u32 ctrl[4]; /* otg/host1-3 */ - u32 uh2_hsic_ctrl; - u32 uh3_hsic_ctrl; - u32 otg_phy_ctrl_0; - u32 uh1_phy_ctrl_0; -}; - -static void usb_oc_config(int index) -{ - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USBOH3_USB_BASE_ADDR + - USB_OTHERREGS_OFFSET); - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); - u32 val; - - val = __raw_readl(ctrl); -#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 - /* mx6qarm2 seems to required a different setting*/ - val &= ~UCTRL_OVER_CUR_POL; -#else - val |= UCTRL_OVER_CUR_POL; -#endif - __raw_writel(val, ctrl); - - val = __raw_readl(ctrl); - val |= UCTRL_OVER_CUR_DIS; - __raw_writel(val, ctrl); -} - -int __weak board_ehci_hcd_init(int port) -{ - return 0; -} - -int __weak board_ehci_power(int port, int on) -{ - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - enum usb_init_type type; - struct usb_ehci *ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR + - (0x200 * index)); - - if (index > 3) - return -EINVAL; - enable_usboh3_clk(1); - mdelay(1); - - /* Do board specific initialization */ - board_ehci_hcd_init(index); - - usb_power_config(index); - usb_oc_config(index); - usb_internal_phy_clock_gate(index, 1); - type = usb_phy_enable(index, ehci) ? USB_INIT_DEVICE : USB_INIT_HOST; - - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - if ((type == init) || (type == USB_INIT_DEVICE)) - board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1); - if (type != init) - return -ENODEV; - if (type == USB_INIT_DEVICE) - return 0; - setbits_le32(&ehci->usbmode, CM_HOST); - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - setbits_le32(&ehci->portsc, USB_EN); - - mdelay(10); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c deleted file mode 100644 index f09c75a9b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mxc.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -#include <common.h> -#include <usb.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <usb/ehci-fsl.h> -#include <errno.h> - -#include "ehci.h" - -#define USBCTRL_OTGBASE_OFFSET 0x600 - -#define MX25_OTG_SIC_SHIFT 29 -#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) -#define MX25_OTG_PM_BIT (1 << 24) -#define MX25_OTG_PP_BIT (1 << 11) -#define MX25_OTG_OCPOL_BIT (1 << 3) - -#define MX25_H1_SIC_SHIFT 21 -#define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) -#define MX25_H1_PP_BIT (1 << 18) -#define MX25_H1_PM_BIT (1 << 16) -#define MX25_H1_IPPUE_UP_BIT (1 << 7) -#define MX25_H1_IPPUE_DOWN_BIT (1 << 6) -#define MX25_H1_TLL_BIT (1 << 5) -#define MX25_H1_USBTE_BIT (1 << 4) -#define MX25_H1_OCPOL_BIT (1 << 2) - -#define MX31_OTG_SIC_SHIFT 29 -#define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT) -#define MX31_OTG_PM_BIT (1 << 24) - -#define MX31_H2_SIC_SHIFT 21 -#define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT) -#define MX31_H2_PM_BIT (1 << 16) -#define MX31_H2_DT_BIT (1 << 5) - -#define MX31_H1_SIC_SHIFT 13 -#define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT) -#define MX31_H1_PM_BIT (1 << 8) -#define MX31_H1_DT_BIT (1 << 4) - -#define MX35_OTG_SIC_SHIFT 29 -#define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT) -#define MX35_OTG_PM_BIT (1 << 24) -#define MX35_OTG_PP_BIT (1 << 11) -#define MX35_OTG_OCPOL_BIT (1 << 3) - -#define MX35_H1_SIC_SHIFT 21 -#define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) -#define MX35_H1_PP_BIT (1 << 18) -#define MX35_H1_PM_BIT (1 << 16) -#define MX35_H1_IPPUE_UP_BIT (1 << 7) -#define MX35_H1_IPPUE_DOWN_BIT (1 << 6) -#define MX35_H1_TLL_BIT (1 << 5) -#define MX35_H1_USBTE_BIT (1 << 4) -#define MX35_H1_OCPOL_BIT (1 << 2) - -static int mxc_set_usbcontrol(int port, unsigned int flags) -{ - unsigned int v; - - v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); -#if defined(CONFIG_MX25) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT | - MX25_OTG_OCPOL_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX25_OTG_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX25_OTG_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX25_OTG_OCPOL_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT | - MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | - MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | - MX25_H1_IPPUE_UP_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX25_H1_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX25_H1_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX25_H1_OCPOL_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX25_H1_TLL_BIT; - - if (flags & MXC_EHCI_INTERNAL_PHY) - v |= MX25_H1_USBTE_BIT; - - if (flags & MXC_EHCI_IPPUE_DOWN) - v |= MX25_H1_IPPUE_DOWN_BIT; - - if (flags & MXC_EHCI_IPPUE_UP) - v |= MX25_H1_IPPUE_UP_BIT; - - break; - default: - return -EINVAL; - } -#elif defined(CONFIG_MX31) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_OTG_PM_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_H1_PM_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX31_H1_DT_BIT; - - break; - case 2: /* H2 port */ - v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX31_H2_PM_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX31_H2_DT_BIT; - - break; - default: - return -EINVAL; - } -#elif defined(CONFIG_MX35) - switch (port) { - case 0: /* OTG port */ - v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT | - MX35_OTG_OCPOL_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX35_OTG_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX35_OTG_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX35_OTG_OCPOL_BIT; - - break; - case 1: /* H1 port */ - v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT | - MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | - MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | - MX35_H1_IPPUE_UP_BIT); - v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT; - - if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) - v |= MX35_H1_PM_BIT; - - if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) - v |= MX35_H1_PP_BIT; - - if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) - v |= MX35_H1_OCPOL_BIT; - - if (!(flags & MXC_EHCI_TTL_ENABLED)) - v |= MX35_H1_TLL_BIT; - - if (flags & MXC_EHCI_INTERNAL_PHY) - v |= MX35_H1_USBTE_BIT; - - if (flags & MXC_EHCI_IPPUE_DOWN) - v |= MX35_H1_IPPUE_DOWN_BIT; - - if (flags & MXC_EHCI_IPPUE_UP) - v |= MX35_H1_IPPUE_UP_BIT; - - break; - default: - return -EINVAL; - } -#else -#error MXC EHCI USB driver not supported on this platform -#endif - writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct usb_ehci *ehci; -#ifdef CONFIG_MX31 - struct clock_control_regs *sc_regs = - (struct clock_control_regs *)CCM_BASE; - - __raw_readl(&sc_regs->ccmr); - __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; -#endif - - udelay(80); - - ehci = (struct usb_ehci *)(IMX_USB_BASE + - IMX_USB_PORT_OFFSET * CONFIG_MXC_USB_PORT); - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - setbits_le32(&ehci->usbmode, CM_HOST); - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); - mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); -#ifdef CONFIG_MX35 - /* Workaround for ENGcm11601 */ - __raw_writel(0, &ehci->sbuscfg); -#endif - - udelay(10000); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c deleted file mode 100644 index 4d652b32d..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-mxs.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Freescale i.MX28 USB Host driver - * - * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> - * on behalf of DENX Software Engineering GmbH - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <errno.h> - -#include "ehci.h" - -/* This DIGCTL register ungates clock to USB */ -#define HW_DIGCTL_CTRL 0x8001c000 -#define HW_DIGCTL_CTRL_USB0_CLKGATE (1 << 2) -#define HW_DIGCTL_CTRL_USB1_CLKGATE (1 << 16) - -struct ehci_mxs_port { - uint32_t usb_regs; - struct mxs_usbphy_regs *phy_regs; - - struct mxs_register_32 *pll; - uint32_t pll_en_bits; - uint32_t pll_dis_bits; - uint32_t gate_bits; -}; - -static const struct ehci_mxs_port mxs_port[] = { -#ifdef CONFIG_EHCI_MXS_PORT0 - { - MXS_USBCTRL0_BASE, - (struct mxs_usbphy_regs *)MXS_USBPHY0_BASE, - (struct mxs_register_32 *)(MXS_CLKCTRL_BASE + - offsetof(struct mxs_clkctrl_regs, - hw_clkctrl_pll0ctrl0_reg)), - CLKCTRL_PLL0CTRL0_EN_USB_CLKS | CLKCTRL_PLL0CTRL0_POWER, - CLKCTRL_PLL0CTRL0_EN_USB_CLKS, - HW_DIGCTL_CTRL_USB0_CLKGATE, - }, -#endif -#ifdef CONFIG_EHCI_MXS_PORT1 - { - MXS_USBCTRL1_BASE, - (struct mxs_usbphy_regs *)MXS_USBPHY1_BASE, - (struct mxs_register_32 *)(MXS_CLKCTRL_BASE + - offsetof(struct mxs_clkctrl_regs, - hw_clkctrl_pll1ctrl0_reg)), - CLKCTRL_PLL1CTRL0_EN_USB_CLKS | CLKCTRL_PLL1CTRL0_POWER, - CLKCTRL_PLL1CTRL0_EN_USB_CLKS, - HW_DIGCTL_CTRL_USB1_CLKGATE, - }, -#endif -}; - -static int ehci_mxs_toggle_clock(const struct ehci_mxs_port *port, int enable) -{ - struct mxs_register_32 *digctl_ctrl = - (struct mxs_register_32 *)HW_DIGCTL_CTRL; - int pll_offset, dig_offset; - - if (enable) { - pll_offset = offsetof(struct mxs_register_32, reg_set); - dig_offset = offsetof(struct mxs_register_32, reg_clr); - writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset); - writel(port->pll_en_bits, (u32)port->pll + pll_offset); - } else { - pll_offset = offsetof(struct mxs_register_32, reg_clr); - dig_offset = offsetof(struct mxs_register_32, reg_set); - writel(port->pll_dis_bits, (u32)port->pll + pll_offset); - writel(port->gate_bits, (u32)&digctl_ctrl->reg + dig_offset); - } - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - - int ret; - uint32_t usb_base, cap_base; - const struct ehci_mxs_port *port; - - if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { - printf("Invalid port index (index = %d)!\n", index); - return -EINVAL; - } - - port = &mxs_port[index]; - - /* Reset the PHY block */ - writel(USBPHY_CTRL_SFTRST, &port->phy_regs->hw_usbphy_ctrl_set); - udelay(10); - writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, - &port->phy_regs->hw_usbphy_ctrl_clr); - - /* Enable USB clock */ - ret = ehci_mxs_toggle_clock(port, 1); - if (ret) - return ret; - - /* Start USB PHY */ - writel(0, &port->phy_regs->hw_usbphy_pwd); - - /* Enable UTMI+ Level 2 and Level 3 compatibility */ - writel(USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2 | 1, - &port->phy_regs->hw_usbphy_ctrl_set); - - usb_base = port->usb_regs + 0x100; - *hccr = (struct ehci_hccr *)usb_base; - - cap_base = ehci_readl(&(*hccr)->cr_capbase); - *hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base)); - - return 0; -} - -int ehci_hcd_stop(int index) -{ - int ret; - uint32_t usb_base, cap_base, tmp; - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - const struct ehci_mxs_port *port; - - if ((index < 0) || (index >= ARRAY_SIZE(mxs_port))) { - printf("Invalid port index (index = %d)!\n", index); - return -EINVAL; - } - - port = &mxs_port[index]; - - /* Stop the USB port */ - usb_base = port->usb_regs + 0x100; - hccr = (struct ehci_hccr *)usb_base; - cap_base = ehci_readl(&hccr->cr_capbase); - hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base)); - - tmp = ehci_readl(&hcor->or_usbcmd); - tmp &= ~CMD_RUN; - ehci_writel(tmp, &hcor->or_usbcmd); - - /* Disable the PHY */ - tmp = USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | - USBPHY_PWD_RXPWD1PT1 | USBPHY_PWD_RXPWDENV | - USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS | - USBPHY_PWD_TXPWDFS; - writel(tmp, &port->phy_regs->hw_usbphy_pwd); - - /* Disable USB clock */ - ret = ehci_mxs_toggle_clock(port, 0); - - return ret; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c b/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c deleted file mode 100644 index 1b215c25f..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-omap.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * (C) Copyright 2011 Ilya Yanok, Emcraft Systems - * (C) Copyright 2004-2008 - * Texas Instruments, <www.ti.com> - * - * Derived from Beagle Board code by - * Sunil Kumar <sunilsaini05@gmail.com> - * Shashi Ranjan <shashiranjanmca05@gmail.com> - * - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <usb/ulpi.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/gpio.h> -#include <asm/arch/ehci.h> -#include <asm/ehci-omap.h> - -#include "ehci.h" - -static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE; -static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE; -static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE; - -static int omap_uhh_reset(void) -{ - int timeout = 0; - u32 rev; - - rev = readl(&uhh->rev); - - /* Soft RESET */ - writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc); - - switch (rev) { - case OMAP_USBHS_REV1: - /* Wait for soft RESET to complete */ - while (!(readl(&uhh->syss) & 0x1)) { - if (timeout > 100) { - printf("%s: RESET timeout\n", __func__); - return -1; - } - udelay(10); - timeout++; - } - - /* Set No-Idle, No-Standby */ - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - break; - - default: /* Rev. 2 onwards */ - - udelay(2); /* Need to wait before accessing SYSCONFIG back */ - - /* Wait for soft RESET to complete */ - while ((readl(&uhh->sysc) & 0x1)) { - if (timeout > 100) { - printf("%s: RESET timeout\n", __func__); - return -1; - } - udelay(10); - timeout++; - } - - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - break; - } - - return 0; -} - -static int omap_ehci_tll_reset(void) -{ - unsigned long init = get_timer(0); - - /* perform TLL soft reset, and wait until reset is complete */ - writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, &usbtll->sysc); - - /* Wait for TLL reset to complete */ - while (!(readl(&usbtll->syss) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) - if (get_timer(init) > CONFIG_SYS_HZ) { - debug("OMAP EHCI error: timeout resetting TLL\n"); - return -EL3RST; - } - - return 0; -} - -static void omap_usbhs_hsic_init(int port) -{ - unsigned int reg; - - /* Enable channels now */ - reg = readl(&usbtll->channel_conf + port); - - setbits_le32(®, (OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI - | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF - | OMAP_TLL_CHANNEL_CONF_DRVVBUS - | OMAP_TLL_CHANNEL_CONF_CHRGVBUS - | OMAP_TLL_CHANNEL_CONF_CHANEN)); - - writel(reg, &usbtll->channel_conf + port); -} - -#ifdef CONFIG_USB_ULPI -static void omap_ehci_soft_phy_reset(int port) -{ - struct ulpi_viewport ulpi_vp; - - ulpi_vp.viewport_addr = (u32)&ehci->insreg05_utmi_ulpi; - ulpi_vp.port_num = port; - - ulpi_reset(&ulpi_vp); -} -#else -static void omap_ehci_soft_phy_reset(int port) -{ - return; -} -#endif - -#if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \ - defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) || \ - defined(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO) -/* controls PHY(s) reset signal(s) */ -static inline void omap_ehci_phy_reset(int on, int delay) -{ - /* - * Refer ISSUE1: - * Hold the PHY in RESET for enough time till - * PHY is settled and ready - */ - if (delay && !on) - udelay(delay); -#ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on); -#endif -#ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on); -#endif -#ifdef CONFIG_OMAP_EHCI_PHY3_RESET_GPIO - gpio_request(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, "USB PHY3 reset"); - gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, !on); -#endif - - /* Hold the PHY in RESET for enough time till DIR is high */ - /* Refer: ISSUE1 */ - if (delay && on) - udelay(delay); -} -#else -#define omap_ehci_phy_reset(on, delay) do {} while (0) -#endif - -/* Reset is needed otherwise the kernel-driver will throw an error. */ -int omap_ehci_hcd_stop(void) -{ - debug("Resetting OMAP EHCI\n"); - omap_ehci_phy_reset(1, 0); - - if (omap_uhh_reset() < 0) - return -1; - - if (omap_ehci_tll_reset() < 0) - return -1; - - return 0; -} - -/* - * Initialize the OMAP EHCI controller and PHY. - * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1 - * See there for additional Copyrights. - */ -int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - int ret; - unsigned int i, reg = 0, rev = 0; - - debug("Initializing OMAP EHCI\n"); - - ret = board_usb_init(index, USB_INIT_HOST); - if (ret < 0) - return ret; - - /* Put the PHY in RESET */ - omap_ehci_phy_reset(1, 10); - - ret = omap_uhh_reset(); - if (ret < 0) - return ret; - - ret = omap_ehci_tll_reset(); - if (ret) - return ret; - - writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | - OMAP_USBTLL_SYSCONFIG_SIDLEMODE | - OMAP_USBTLL_SYSCONFIG_CACTIVITY, &usbtll->sysc); - - /* Put UHH in NoIdle/NoStandby mode */ - writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc); - - /* setup ULPI bypass and burst configurations */ - clrsetbits_le32(®, OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN, - (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | - OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | - OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN)); - - rev = readl(&uhh->rev); - if (rev == OMAP_USBHS_REV1) { - if (is_ehci_phy_mode(usbhs_pdata->port_mode[0])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS); - - if (is_ehci_phy_mode(usbhs_pdata->port_mode[1])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS); - - if (is_ehci_phy_mode(usbhs_pdata->port_mode[2])) - clrbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); - else - setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); - } else if (rev == OMAP_USBHS_REV2) { - - clrsetbits_le32(®, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR), - OMAP4_UHH_HOSTCONFIG_APP_START_CLK); - - /* Clear port mode fields for PHY mode */ - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) - setbits_le32(®, OMAP_P1_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) - setbits_le32(®, OMAP_P2_MODE_HSIC); - - } else if (rev == OMAP_USBHS_REV2_1) { - - clrsetbits_le32(®, - (OMAP_P1_MODE_CLEAR | - OMAP_P2_MODE_CLEAR | - OMAP_P3_MODE_CLEAR), - OMAP4_UHH_HOSTCONFIG_APP_START_CLK); - - /* Clear port mode fields for PHY mode */ - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) - setbits_le32(®, OMAP_P1_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) - setbits_le32(®, OMAP_P2_MODE_HSIC); - - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2])) - setbits_le32(®, OMAP_P3_MODE_HSIC); - } - - debug("OMAP UHH_REVISION 0x%x\n", rev); - writel(reg, &uhh->hostconfig); - - for (i = 0; i < OMAP_HS_USB_PORTS; i++) - if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i])) - omap_usbhs_hsic_init(i); - - omap_ehci_phy_reset(0, 10); - - /* - * An undocumented "feature" in the OMAP3 EHCI controller, - * causes suspended ports to be taken out of suspend when - * the USBCMD.Run/Stop bit is cleared (for example when - * we do ehci_bus_suspend). - * This breaks suspend-resume if the root-hub is allowed - * to suspend. Writing 1 to this undocumented register bit - * disables this feature and restores normal behavior. - */ - writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, &ehci->insreg04); - - for (i = 0; i < OMAP_HS_USB_PORTS; i++) - if (is_ehci_phy_mode(usbhs_pdata->port_mode[i])) - omap_ehci_soft_phy_reset(i); - - *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE); - *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10); - - debug("OMAP EHCI init done\n"); - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c b/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c deleted file mode 100644 index 991b19998..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-pci.c +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <errno.h> -#include <pci.h> -#include <usb.h> - -#include "ehci.h" - -#ifdef CONFIG_PCI_EHCI_DEVICE -static struct pci_device_id ehci_pci_ids[] = { - /* Please add supported PCI EHCI controller ids here */ - {0x1033, 0x00E0}, /* NEC */ - {0x10B9, 0x5239}, /* ULI1575 PCI EHCI module ids */ - {0x12D8, 0x400F}, /* Pericom */ - {0, 0} -}; -#else -static pci_dev_t ehci_find_class(int index) -{ - int bus; - int devnum; - pci_dev_t bdf; - uint32_t class; - - for (bus = 0; bus <= pci_last_busno(); bus++) { - for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) { - pci_read_config_dword(PCI_BDF(bus, devnum, 0), - PCI_CLASS_REVISION, &class); - if (class >> 16 == 0xffff) - continue; - - for (bdf = PCI_BDF(bus, devnum, 0); - bdf <= PCI_BDF(bus, devnum, - PCI_MAX_PCI_FUNCTIONS - 1); - bdf += PCI_BDF(0, 0, 1)) { - pci_read_config_dword(bdf, PCI_CLASS_REVISION, - &class); - class >>= 8; - /* - * Here be dragons! In case we have multiple - * PCI EHCI controllers, this function will - * be called multiple times as well. This - * function will scan the PCI busses, always - * starting from bus 0, device 0, function 0, - * until it finds an USB controller. The USB - * stack gives us an 'index' of a controller - * that is currently being registered, which - * is a number, starting from 0 and growing - * in ascending order as controllers are added. - * To avoid probing the same controller in tne - * subsequent runs of this function, we will - * skip 'index - 1' detected controllers and - * report the index'th controller. - */ - if (class != PCI_CLASS_SERIAL_USB_EHCI) - continue; - if (index) { - index--; - continue; - } - /* Return index'th controller. */ - return bdf; - } - } - } - - return -ENODEV; -} -#endif - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) -{ - pci_dev_t pdev; - uint32_t cmd; - struct ehci_hccr *hccr; - struct ehci_hcor *hcor; - -#ifdef CONFIG_PCI_EHCI_DEVICE - pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE); -#else - pdev = ehci_find_class(index); -#endif - if (pdev < 0) { - printf("EHCI host controller not found\n"); - return -1; - } - - hccr = (struct ehci_hccr *)pci_map_bar(pdev, - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - hcor = (struct ehci_hcor *)((uint32_t) hccr + - HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (uint32_t)hccr, (uint32_t)hcor, - (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - - *ret_hccr = hccr; - *ret_hcor = hcor; - - /* enable busmaster */ - pci_read_config_dword(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_dword(pdev, PCI_COMMAND, cmd); - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c b/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c deleted file mode 100644 index 9aee3ff78..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-ppc4xx.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * (C) Copyright 2010, Chris Zhang <chris@seamicro.com> - * - * Author: Chris Zhang <chris@seamicro.com> - * This code is based on ehci freescale driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include <common.h> -#include <usb.h> - -#include "ehci.h" - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - *hccr = (struct ehci_hccr *)(CONFIG_SYS_PPC4XX_USB_ADDR); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c b/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c deleted file mode 100644 index 049e4c4e6..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-rmobile.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2013,2014 Renesas Electronics Corporation - * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ehci-rmobile.h> -#include "ehci.h" - -#if defined(CONFIG_R8A7740) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xC6700000 -}; -#elif defined(CONFIG_R8A7790) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xEE080000, /* USB0 (EHCI) */ - 0xEE0A0000, /* USB1 */ - 0xEE0C0000, /* USB2 */ - 0xEE000000 /* USB3 (USB3.0 Host)*/ -}; -#elif defined(CONFIG_R8A7791) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { - 0xEE080000, /* USB0 (EHCI) */ - 0xEE0C0000, /* USB1 */ - 0xEE000000 /* USB3 (USB3.0 Host)*/ -}; -#else -#error rmobile EHCI USB driver not supported on this platform -#endif - -int ehci_hcd_stop(int index) -{ - int i; - u32 base; - struct ahbcom_pci_bridge *ahbcom_pci; - - base = usb_base_address[index]; - ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); - writel(0, &ahbcom_pci->ahb_bus_ctr); - - /* reset ehci */ - setbits_le32(base + EHCI_USBCMD, CMD_RESET); - for (i = 100; i > 0; i--) { - if (!(readl(base + EHCI_USBCMD) & CMD_RESET)) - break; - udelay(100); - } - - if (!i) - printf("error : ehci(%d) reset failed.\n", index); - - if (index == (CONFIG_USB_MAX_CONTROLLER_COUNT - 1)) - setbits_le32(SMSTPCR7, SMSTPCR703); - - return 0; -} - -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - u32 base; - u32 phys_base; - struct rmobile_ehci_reg *rehci; - struct ahbcom_pci_bridge *ahbcom_pci; - struct ahbconf_pci_bridge *ahbconf_pci; - struct ahb_pciconf *ahb_pciconf_ohci; - struct ahb_pciconf *ahb_pciconf_ehci; - uint32_t cap_base; - - base = usb_base_address[index]; - phys_base = base; - if (index == 0) - clrbits_le32(SMSTPCR7, SMSTPCR703); - - rehci = (struct rmobile_ehci_reg *)(base + EHCI_OFFSET); - ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); - ahbconf_pci = - (struct ahbconf_pci_bridge *)(base + PCI_CONF_AHBPCI_OFFSET); - ahb_pciconf_ohci = (struct ahb_pciconf *)(base + PCI_CONF_OHCI_OFFSET); - ahb_pciconf_ehci = (struct ahb_pciconf *)(base + PCI_CONF_EHCI_OFFSET); - - /* Clock & Reset & Direct Power Down */ - clrsetbits_le32(&ahbcom_pci->usbctr, - (DIRPD | PCICLK_MASK | USBH_RST), USBCTR_WIN_SIZE_1GB); - clrbits_le32(&ahbcom_pci->usbctr, PLL_RST); - - /* AHB-PCI Bridge Communication Registers */ - writel(AHB_BUS_CTR_INIT, &ahbcom_pci->ahb_bus_ctr); - writel((CONFIG_SYS_SDRAM_BASE & 0xf0000000) | PCIAHB_WIN_PREFETCH, - &ahbcom_pci->pciahb_win1_ctr); - writel(0xf0000000 | PCIAHB_WIN_PREFETCH, - &ahbcom_pci->pciahb_win2_ctr); - writel(phys_base | PCIWIN2_PCICMD, &ahbcom_pci->ahbpci_win2_ctr); - - setbits_le32(&ahbcom_pci->pci_arbiter_ctr, - PCIBP_MODE | PCIREQ1 | PCIREQ0); - - /* PCI Configuration Registers for AHBPCI */ - writel(PCIWIN1_PCICMD | AHB_CFG_AHBPCI, - &ahbcom_pci->ahbpci_win1_ctr); - writel(phys_base + AHBPCI_OFFSET, &ahbconf_pci->basead); - writel(CONFIG_SYS_SDRAM_BASE & 0xf0000000, &ahbconf_pci->win1_basead); - writel(0xf0000000, &ahbconf_pci->win2_basead); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahbconf_pci->cmnd_sts); - - /* PCI Configuration Registers for EHCI */ - writel(PCIWIN1_PCICMD | AHB_CFG_HOST, &ahbcom_pci->ahbpci_win1_ctr); - writel(phys_base + OHCI_OFFSET, &ahb_pciconf_ohci->basead); - writel(phys_base + EHCI_OFFSET, &ahb_pciconf_ehci->basead); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahb_pciconf_ohci->cmnd_sts); - writel(SERREN | PERREN | MASTEREN | MEMEN, - &ahb_pciconf_ehci->cmnd_sts); - - /* Enable PCI interrupt */ - setbits_le32(&ahbcom_pci->pci_int_enable, - USBH_PMEEN | USBH_INTBEN | USBH_INTAEN); - - *hccr = (struct ehci_hccr *)((uint32_t)&rehci->hciversion); - cap_base = ehci_readl(&(*hccr)->cr_capbase); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + HC_LENGTH(cap_base)); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c b/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c deleted file mode 100644 index 210ee9e88..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-spear.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * (C) Copyright 2010 - * Armando Visconti, ST Micoelectronics, <armando.visconti@st.com>. - * - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * Written-by: Prafulla Wadaskar <prafulla@marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include "ehci.h" -#include <asm/arch/hardware.h> - - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - *hccr = (struct ehci_hccr *)(CONFIG_SYS_UHC0_EHCI_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - debug("SPEAr-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c b/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c deleted file mode 100644 index 38db18e2c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-tegra.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (c) 2009-2013 NVIDIA Corporation - * Copyright (c) 2013 Lucas Stach - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <asm-generic/gpio.h> -#include <asm/arch/clock.h> -#include <asm/arch-tegra/usb.h> -#include <asm/arch-tegra/clk_rst.h> -#include <usb.h> -#include <usb/ulpi.h> -#include <libfdt.h> -#include <fdtdec.h> - -#include "ehci.h" - -#define USB1_ADDR_MASK 0xFFFF0000 - -#define HOSTPC1_DEVLC 0x84 -#define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) - -#ifdef CONFIG_USB_ULPI - #ifndef CONFIG_USB_ULPI_VIEWPORT - #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ - define CONFIG_USB_ULPI_VIEWPORT" - #endif -#endif - -enum { - USB_PORTS_MAX = 3, /* Maximum ports we allow */ -}; - -/* Parameters we need for USB */ -enum { - PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ - PARAM_DIVM, /* PLL INPUT DIVIDER */ - PARAM_DIVP, /* POST DIVIDER (2^N) */ - PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ - PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ - PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ - PARAM_STABLE_COUNT, /* PLL-U STABLE count */ - PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ - PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ - PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ - PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ - - PARAM_COUNT -}; - -/* Possible port types (dual role mode) */ -enum dr_mode { - DR_MODE_NONE = 0, - DR_MODE_HOST, /* supports host operation */ - DR_MODE_DEVICE, /* supports device operation */ - DR_MODE_OTG, /* supports both */ -}; - -/* Information about a USB port */ -struct fdt_usb { - struct usb_ctlr *reg; /* address of registers in physical memory */ - unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ - unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ - unsigned enabled:1; /* 1 to enable, 0 to disable */ - unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ - unsigned initialized:1; /* has this port already been initialized? */ - enum dr_mode dr_mode; /* dual role mode */ - enum periph_id periph_id;/* peripheral id */ - struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ - struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ -}; - -static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ -static unsigned port_count; /* Number of available ports */ -/* Port that needs to clear CSC after Port Reset */ -static u32 port_addr_clear_csc; - -/* - * This table has USB timing parameters for each Oscillator frequency we - * support. There are four sets of values: - * - * 1. PLLU configuration information (reference clock is osc/clk_m and - * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * ---------------------------------------------------------------------- - * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) - * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) - * Filter frequency (MHz) 1 4.8 6 2 - * CPCON 1100b 0011b 1100b 1100b - * LFCON0 0 0 0 0 - * - * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * --------------------------------------------------------------------------- - * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) - * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) - * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) - * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) - * - * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and - * SessEnd. Each of these signals have their own debouncer and for each of - * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or - * BIAS_DEBOUNCE_B). - * - * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: - * 0xffff -> No debouncing at all - * <n> ms = <n> *1000 / (1/19.2MHz) / 4 - * - * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: - * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 - * - * We need to use only DebounceA for BOOTROM. We don't need the DebounceB - * values, so we can keep those to default. - * - * 4. The 20 microsecond delay after bias cell operation. - */ -static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; - -static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 1, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 1, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; - -static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 2, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, - { 0x0C8, 0x04, 0x00, 0x3, 2, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, - { 0x3C0, 0x0C, 0x00, 0xC, 2, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } -}; - -/* UTMIP Idle Wait Delay */ -static const u8 utmip_idle_wait_delay = 17; - -/* UTMIP Elastic limit */ -static const u8 utmip_elastic_limit = 16; - -/* UTMIP High Speed Sync Start Delay */ -static const u8 utmip_hs_sync_start_delay = 9; - -struct fdt_usb_controller { - int compat; - /* flag to determine whether controller supports hostpc register */ - u32 has_hostpc:1; - const unsigned *pll_parameter; -}; - -static struct fdt_usb_controller fdt_usb_controllers[] = { - { - .compat = COMPAT_NVIDIA_TEGRA20_USB, - .has_hostpc = 0, - .pll_parameter = (const unsigned *)T20_usb_pll, - }, - { - .compat = COMPAT_NVIDIA_TEGRA30_USB, - .has_hostpc = 1, - .pll_parameter = (const unsigned *)T30_usb_pll, - }, - { - .compat = COMPAT_NVIDIA_TEGRA114_USB, - .has_hostpc = 1, - .pll_parameter = (const unsigned *)T114_usb_pll, - }, -}; - -static struct fdt_usb_controller *controller; - -/* - * A known hardware issue where Connect Status Change bit of PORTSC register - * of USB1 controller will be set after Port Reset. - * We have to clear it in order for later device enumeration to proceed. - * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup - * in "ehci-hcd.c". - */ -void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) -{ - mdelay(50); - /* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ - if (controller->has_hostpc) - *reg |= EHCI_PS_PE; - - if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc) - return; - /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ - if (ehci_readl(status_reg) & EHCI_PS_CSC) - *reg |= EHCI_PS_CSC; -} - -/* - * This ehci_set_usbmode overrides the weak function ehci_set_usbmode - * in "ehci-hcd.c". - */ -void ehci_set_usbmode(int index) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - uint32_t tmp; - - config = &port[index]; - usbctlr = config->reg; - - tmp = ehci_readl(&usbctlr->usb_mode); - tmp |= USBMODE_CM_HC; - ehci_writel(&usbctlr->usb_mode, tmp); -} - -/* - * This ehci_get_port_speed overrides the weak function ehci_get_port_speed - * in "ehci-hcd.c". - */ -int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) -{ - uint32_t tmp; - uint32_t *reg_ptr; - - if (controller->has_hostpc) { - reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); - tmp = ehci_readl(reg_ptr); - return HOSTPC1_PSPD(tmp); - } else - return PORTSC_PSPD(reg); -} - -/* Put the port into host mode */ -static void set_host_mode(struct fdt_usb *config) -{ - /* - * If we are an OTG port, check if remote host is driving VBus and - * bail out in this case. - */ - if (config->dr_mode == DR_MODE_OTG && - (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) - return; - - /* - * If not driving, we set the GPIO to enable VBUS. We assume - * that the pinmux is set up correctly for this. - */ - if (fdt_gpio_isvalid(&config->vbus_gpio)) { - fdtdec_setup_gpio(&config->vbus_gpio); - gpio_direction_output(config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - 0 : 1); - debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - "low" : "high"); - } -} - -void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) -{ - /* Reset the USB controller with 2us delay */ - reset_periph(config->periph_id, 2); - - /* - * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under - * base address - */ - if (config->has_legacy_mode) - setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); - - /* Put UTMIP1/3 in reset */ - setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Enable the UTMIP PHY */ - if (config->utmi) - setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); -} - -static const unsigned *get_pll_timing(void) -{ - const unsigned *timing; - - timing = controller->pll_parameter + - clock_get_osc_freq() * PARAM_COUNT; - - return timing; -} - -/* set up the UTMI USB controller with the parameters provided */ -static int init_utmi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - const unsigned *timing; - struct usb_ctlr *usbctlr = config->reg; - struct clk_rst_ctlr *clkrst; - struct usb_ctlr *usb1ctlr; - - clock_enable(config->periph_id); - - /* Reset the usb controller */ - usbf_reset_controller(config, usbctlr); - - /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ - clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - /* Follow the crystal clock disable by >100ns delay */ - udelay(1); - - /* - * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP - * mux must be switched to actually use a_sess_vld threshold. - */ - if (config->dr_mode == DR_MODE_OTG && - fdt_gpio_isvalid(&config->vbus_gpio)) - clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, - VBUS_SENSE_CTL_MASK, - VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); - - /* - * PLL Delay CONFIGURATION settings. The following parameters control - * the bring up of the plls. - */ - timing = get_pll_timing(); - - if (!controller->has_hostpc) { - val = readl(&usbctlr->utmip_misc_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << - UTMIP_PLLU_STABLE_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << - UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); - writel(val, &usbctlr->utmip_misc_cfg1); - - /* Set PLL enable delay count and crystal frequency count */ - val = readl(&usbctlr->utmip_pll_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << - UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << - UTMIP_XTAL_FREQ_COUNT_SHIFT); - writel(val, &usbctlr->utmip_pll_cfg1); - } else { - clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - - val = readl(&clkrst->crc_utmip_pll_cfg2); - clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << - UTMIP_PLLU_STABLE_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << - UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); - writel(val, &clkrst->crc_utmip_pll_cfg2); - - /* Set PLL enable delay count and crystal frequency count */ - val = readl(&clkrst->crc_utmip_pll_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << - UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << - UTMIP_XTAL_FREQ_COUNT_SHIFT); - writel(val, &clkrst->crc_utmip_pll_cfg1); - - /* Disable Power Down state for PLL */ - clrbits_le32(&clkrst->crc_utmip_pll_cfg1, - PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | - PLL_ACTIVE_POWERDOWN); - - /* Recommended PHY settings for EYE diagram */ - val = readl(&usbctlr->utmip_xcvr_cfg0); - clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, - 0x4 << UTMIP_XCVR_SETUP_SHIFT); - clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, - 0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); - clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, - 0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); - writel(val, &usbctlr->utmip_xcvr_cfg0); - clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, - UTMIP_XCVR_TERM_RANGE_ADJ_MASK, - 0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); - - /* Some registers can be controlled from USB1 only. */ - if (config->periph_id != PERIPH_ID_USBD) { - clock_enable(PERIPH_ID_USBD); - /* Disable Reset if in Reset state */ - reset_set_enable(PERIPH_ID_USBD, 0); - } - usb1ctlr = (struct usb_ctlr *) - ((u32)config->reg & USB1_ADDR_MASK); - val = readl(&usb1ctlr->utmip_bias_cfg0); - setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); - clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, - 0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); - clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, - 0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); - writel(val, &usb1ctlr->utmip_bias_cfg0); - - /* Miscellaneous setting mentioned in Programming Guide */ - clrbits_le32(&usbctlr->utmip_misc_cfg0, - UTMIP_SUSPEND_EXIT_ON_EDGE); - } - - /* Setting the tracking length time */ - clrsetbits_le32(&usbctlr->utmip_bias_cfg1, - UTMIP_BIAS_PDTRK_COUNT_MASK, - timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); - - /* Program debounce time for VBUS to become valid */ - clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, - UTMIP_DEBOUNCE_CFG0_MASK, - timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); - - setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); - - /* Disable battery charge enabling bit */ - setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); - - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); - setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); - - /* - * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT - * Setting these fields, together with default values of the - * other fields, results in programming the registers below as - * follows: - * UTMIP_HSRX_CFG0 = 0x9168c000 - * UTMIP_HSRX_CFG1 = 0x13 - */ - - /* Set PLL enable delay count and Crystal frequency count */ - val = readl(&usbctlr->utmip_hsrx_cfg0); - clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, - utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); - clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, - utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); - writel(val, &usbctlr->utmip_hsrx_cfg0); - - /* Configure the UTMIP_HS_SYNC_START_DLY */ - clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, - UTMIP_HS_SYNC_START_DLY_MASK, - utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); - - /* Preceed the crystal clock disable by >100ns delay. */ - udelay(1); - - /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ - setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - if (controller->has_hostpc) { - if (config->periph_id == PERIPH_ID_USBD) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_A_POWERDOWN); - if (config->periph_id == PERIPH_ID_USB2) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_B_POWERDOWN); - if (config->periph_id == PERIPH_ID_USB3) - clrbits_le32(&clkrst->crc_utmip_pll_cfg2, - UTMIP_FORCE_PD_SAMP_C_POWERDOWN); - } - /* Finished the per-controller init. */ - - /* De-assert UTMIP_RESET to bring out of reset. */ - clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Wait for the phy clock to become valid in 100 ms */ - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - - /* Disable ICUSB FS/LS transceiver */ - clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); - - /* Select UTMI parallel interface */ -#if defined(CONFIG_TEGRA20) - if (config->periph_id == PERIPH_ID_USBD) { - clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK, - PTS_UTMI << PTS1_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS1); - } else { - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS); - } -#else - clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->hostpc1_devlc, STS); -#endif - - /* Deassert power down state */ - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | - UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); - clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | - UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); - - if (controller->has_hostpc) { - /* - * BIAS Pad Power Down is common among all 3 USB - * controllers and can be controlled from USB1 only. - */ - usb1ctlr = (struct usb_ctlr *) - ((u32)config->reg & USB1_ADDR_MASK); - clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); - udelay(25); - clrbits_le32(&usb1ctlr->utmip_bias_cfg1, - UTMIP_FORCE_PDTRK_POWERDOWN); - } - return 0; -} - -#ifdef CONFIG_USB_ULPI -/* if board file does not set a ULPI reference frequency we default to 24MHz */ -#ifndef CONFIG_ULPI_REF_CLK -#define CONFIG_ULPI_REF_CLK 24000000 -#endif - -/* set up the ULPI USB controller with the parameters provided */ -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - struct ulpi_viewport ulpi_vp; - struct usb_ctlr *usbctlr = config->reg; - - /* set up ULPI reference clock on pllp_out4 */ - clock_enable(PERIPH_ID_DEV2_OUT); - clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); - - /* reset ULPI phy */ - if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { - fdtdec_setup_gpio(&config->phy_reset_gpio); - gpio_direction_output(config->phy_reset_gpio.gpio, 0); - mdelay(5); - gpio_set_value(config->phy_reset_gpio.gpio, 1); - } - - /* Reset the usb controller */ - clock_enable(config->periph_id); - usbf_reset_controller(config, usbctlr); - - /* enable pinmux bypass */ - setbits_le32(&usbctlr->ulpi_timing_ctrl_0, - ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); - - /* Select ULPI parallel interface */ -#if defined(CONFIG_TEGRA20) - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_ULPI << PTS_SHIFT); -#else - clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, - PTS_ULPI << PTS_SHIFT); -#endif - - /* enable ULPI transceiver */ - setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); - - /* configure ULPI transceiver timings */ - val = 0; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - val |= ULPI_DATA_TRIMMER_SEL(4); - val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); - val |= ULPI_DIR_TRIMMER_SEL(4); - writel(val, &usbctlr->ulpi_timing_ctrl_1); - udelay(10); - - val |= ULPI_DATA_TRIMMER_LOAD; - val |= ULPI_STPDIRNXT_TRIMMER_LOAD; - val |= ULPI_DIR_TRIMMER_LOAD; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - /* set up phy for host operation with external vbus supply */ - ulpi_vp.port_num = 0; - ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; - - if (ulpi_init(&ulpi_vp)) { - printf("Tegra ULPI viewport init failed\n"); - return -1; - } - - ulpi_set_vbus(&ulpi_vp, 1, 1); - ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); - - /* enable wakeup events */ - setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); - - /* Enable and wait for the phy clock to become valid in 100 ms */ - setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - - return 0; -} -#else -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - printf("No code to set up ULPI controller, please enable" - "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); - return -1; -} -#endif - -static void config_clock(const u32 timing[]) -{ - clock_start_pll(CLOCK_ID_USB, - timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], - timing[PARAM_CPCON], timing[PARAM_LFCON]); -} - -static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) -{ - const char *phy, *mode; - - config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); - mode = fdt_getprop(blob, node, "dr_mode", NULL); - if (mode) { - if (0 == strcmp(mode, "host")) - config->dr_mode = DR_MODE_HOST; - else if (0 == strcmp(mode, "peripheral")) - config->dr_mode = DR_MODE_DEVICE; - else if (0 == strcmp(mode, "otg")) - config->dr_mode = DR_MODE_OTG; - else { - debug("%s: Cannot decode dr_mode '%s'\n", __func__, - mode); - return -FDT_ERR_NOTFOUND; - } - } else { - config->dr_mode = DR_MODE_HOST; - } - - phy = fdt_getprop(blob, node, "phy_type", NULL); - config->utmi = phy && 0 == strcmp("utmi", phy); - config->ulpi = phy && 0 == strcmp("ulpi", phy); - config->enabled = fdtdec_get_is_enabled(blob, node); - config->has_legacy_mode = fdtdec_get_bool(blob, node, - "nvidia,has-legacy-mode"); - if (config->has_legacy_mode) - port_addr_clear_csc = (u32) config->reg; - config->periph_id = clock_decode_periph_id(blob, node); - if (config->periph_id == PERIPH_ID_NONE) { - debug("%s: Missing/invalid peripheral ID\n", __func__); - return -FDT_ERR_NOTFOUND; - } - fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); - fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", - &config->phy_reset_gpio); - debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " - "vbus=%d, phy_reset=%d, dr_mode=%d\n", - config->enabled, config->has_legacy_mode, config->utmi, - config->ulpi, config->periph_id, config->vbus_gpio.gpio, - config->phy_reset_gpio.gpio, config->dr_mode); - - return 0; -} - -/* - * process_usb_nodes() - Process a list of USB nodes, adding them to our list - * of USB ports. - * @blob: fdt blob - * @node_list: list of nodes to process (any <=0 are ignored) - * @count: number of nodes to process - * - * Return: 0 - ok, -1 - error - */ -static int process_usb_nodes(const void *blob, int node_list[], int count) -{ - struct fdt_usb config; - int node, i; - int clk_done = 0; - - port_count = 0; - for (i = 0; i < count; i++) { - if (port_count == USB_PORTS_MAX) { - printf("tegrausb: Cannot register more than %d ports\n", - USB_PORTS_MAX); - return -1; - } - - debug("USB %d: ", i); - node = node_list[i]; - if (!node) - continue; - if (fdt_decode_usb(blob, node, &config)) { - debug("Cannot decode USB node %s\n", - fdt_get_name(blob, node, NULL)); - return -1; - } - if (!clk_done) { - config_clock(get_pll_timing()); - clk_done = 1; - } - config.initialized = 0; - - /* add new USB port to the list of available ports */ - port[port_count++] = config; - } - - return 0; -} - -int usb_process_devicetree(const void *blob) -{ - int node_list[USB_PORTS_MAX]; - int count, err = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(fdt_usb_controllers); i++) { - controller = &fdt_usb_controllers[i]; - - count = fdtdec_find_aliases_for_id(blob, "usb", - controller->compat, node_list, USB_PORTS_MAX); - if (count) { - err = process_usb_nodes(blob, node_list, count); - if (err) - printf("%s: Error processing USB node!\n", - __func__); - return err; - } - } - if (i == ARRAY_SIZE(fdt_usb_controllers)) - controller = NULL; - - return err; -} - -/** - * Start up the given port number (ports are numbered from 0 on each board). - * This returns values for the appropriate hccr and hcor addresses to use for - * USB EHCI operations. - * - * @param index port number to start - * @param hccr returns start address of EHCI HCCR registers - * @param hcor returns start address of EHCI HCOR registers - * @return 0 if ok, -1 on error (generally invalid port number) - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - - if (index >= port_count) - return -1; - - config = &port[index]; - - /* skip init, if the port is already initialized */ - if (config->initialized) - goto success; - - if (config->utmi && init_utmi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", index); - return -1; - } - - if (config->ulpi && init_ulpi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", index); - return -1; - } - - set_host_mode(config); - - config->initialized = 1; - -success: - usbctlr = config->reg; - *hccr = (struct ehci_hccr *)&usbctlr->cap_length; - *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; - - if (controller->has_hostpc) { - /* Set to Host mode after Controller Reset was done */ - clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, - USBMODE_CM_HC); - /* Select UTMI parallel interface after setting host mode */ - if (config->utmi) { - clrsetbits_le32((char *)&usbctlr->usb_cmd + - HOSTPC1_DEVLC, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32((char *)&usbctlr->usb_cmd + - HOSTPC1_DEVLC, STS); - } - } - return 0; -} - -/* - * Bring down the specified USB controller - */ -int ehci_hcd_stop(int index) -{ - struct usb_ctlr *usbctlr; - - usbctlr = port[index].reg; - - /* Stop controller */ - writel(0, &usbctlr->usb_cmd); - udelay(1000); - - /* Initiate controller reset */ - writel(2, &usbctlr->usb_cmd); - udelay(1000); - - port[index].initialized = 0; - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c b/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c deleted file mode 100644 index 512ad3fb7..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci-vct.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> - -#include "ehci.h" - -int vct_ehci_hcd_init(u32 *hccr, u32 *hcor); - -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor) -{ - int ret; - u32 vct_hccr; - u32 vct_hcor; - - /* - * Init VCT specific stuff - */ - ret = vct_ehci_hcd_init(&vct_hccr, &vct_hcor); - if (ret) - return ret; - - *hccr = (struct ehci_hccr *)vct_hccr; - *hcor = (struct ehci_hcor *)vct_hcor; - - return 0; -} - -/* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. - */ -int ehci_hcd_stop(int index) -{ - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci.h b/qemu/roms/u-boot/drivers/usb/host/ehci.h deleted file mode 100644 index 093eb4b83..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ehci.h +++ /dev/null @@ -1,257 +0,0 @@ -/*- - * Copyright (c) 2007-2008, Juniper Networks, Inc. - * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * 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., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef USB_EHCI_H -#define USB_EHCI_H - -#include <usb.h> - -#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 -#endif - -/* - * Register Space. - */ -struct ehci_hccr { - uint32_t cr_capbase; -#define HC_LENGTH(p) (((p) >> 0) & 0x00ff) -#define HC_VERSION(p) (((p) >> 16) & 0xffff) - uint32_t cr_hcsparams; -#define HCS_PPC(p) ((p) & (1 << 4)) -#define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */ -#define HCS_N_PORTS(p) (((p) >> 0) & 0xf) - uint32_t cr_hccparams; - uint8_t cr_hcsp_portrt[8]; -} __attribute__ ((packed, aligned(4))); - -struct ehci_hcor { - uint32_t or_usbcmd; -#define CMD_PARK (1 << 11) /* enable "park" */ -#define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */ -#define CMD_ASE (1 << 5) /* async schedule enable */ -#define CMD_LRESET (1 << 7) /* partial reset */ -#define CMD_IAAD (1 << 5) /* "doorbell" interrupt */ -#define CMD_PSE (1 << 4) /* periodic schedule enable */ -#define CMD_RESET (1 << 1) /* reset HC not bus */ -#define CMD_RUN (1 << 0) /* start/stop HC */ - uint32_t or_usbsts; -#define STS_ASS (1 << 15) -#define STS_PSS (1 << 14) -#define STS_HALT (1 << 12) - uint32_t or_usbintr; -#define INTR_UE (1 << 0) /* USB interrupt enable */ -#define INTR_UEE (1 << 1) /* USB error interrupt enable */ -#define INTR_PCE (1 << 2) /* Port change detect enable */ -#define INTR_SEE (1 << 4) /* system error enable */ -#define INTR_AAE (1 << 5) /* Interrupt on async adavance enable */ - uint32_t or_frindex; - uint32_t or_ctrldssegment; - uint32_t or_periodiclistbase; - uint32_t or_asynclistaddr; - uint32_t _reserved_0_; - uint32_t or_burstsize; - uint32_t or_txfilltuning; -#define TXFIFO_THRESH_MASK (0x3f << 16) -#define TXFIFO_THRESH(p) ((p & 0x3f) << 16) - uint32_t _reserved_1_[6]; - uint32_t or_configflag; -#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ - uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; -#define PORTSC_PSPD(x) (((x) >> 26) & 0x3) -#define PORTSC_PSPD_FS 0x0 -#define PORTSC_PSPD_LS 0x1 -#define PORTSC_PSPD_HS 0x2 - uint32_t or_systune; -} __attribute__ ((packed, aligned(4))); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1 << 3) /* Stream disable */ -#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ -#define USBMODE_CM_HC (3 << 0) /* host controller mode */ -#define USBMODE_CM_IDLE (0 << 0) /* idle state */ - -/* Interface descriptor */ -struct usb_linux_interface_descriptor { - unsigned char bLength; - unsigned char bDescriptorType; - unsigned char bInterfaceNumber; - unsigned char bAlternateSetting; - unsigned char bNumEndpoints; - unsigned char bInterfaceClass; - unsigned char bInterfaceSubClass; - unsigned char bInterfaceProtocol; - unsigned char iInterface; -} __attribute__ ((packed)); - -/* Configuration descriptor information.. */ -struct usb_linux_config_descriptor { - unsigned char bLength; - unsigned char bDescriptorType; - unsigned short wTotalLength; - unsigned char bNumInterfaces; - unsigned char bConfigurationValue; - unsigned char iConfiguration; - unsigned char bmAttributes; - unsigned char MaxPower; -} __attribute__ ((packed)); - -#if defined CONFIG_EHCI_DESC_BIG_ENDIAN -#define ehci_readl(x) (*((volatile u32 *)(x))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = ((volatile u32)b)) -#else -#define ehci_readl(x) cpu_to_le32((*((volatile u32 *)(x)))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = \ - cpu_to_le32(((volatile u32)b))) -#endif - -#if defined CONFIG_EHCI_MMIO_BIG_ENDIAN -#define hc32_to_cpu(x) be32_to_cpu((x)) -#define cpu_to_hc32(x) cpu_to_be32((x)) -#else -#define hc32_to_cpu(x) le32_to_cpu((x)) -#define cpu_to_hc32(x) cpu_to_le32((x)) -#endif - -#define EHCI_PS_WKOC_E (1 << 22) /* RW wake on over current */ -#define EHCI_PS_WKDSCNNT_E (1 << 21) /* RW wake on disconnect */ -#define EHCI_PS_WKCNNT_E (1 << 20) /* RW wake on connect */ -#define EHCI_PS_PO (1 << 13) /* RW port owner */ -#define EHCI_PS_PP (1 << 12) /* RW,RO port power */ -#define EHCI_PS_LS (3 << 10) /* RO line status */ -#define EHCI_PS_PR (1 << 8) /* RW port reset */ -#define EHCI_PS_SUSP (1 << 7) /* RW suspend */ -#define EHCI_PS_FPR (1 << 6) /* RW force port resume */ -#define EHCI_PS_OCC (1 << 5) /* RWC over current change */ -#define EHCI_PS_OCA (1 << 4) /* RO over current active */ -#define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ -#define EHCI_PS_PE (1 << 2) /* RW port enable */ -#define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ -#define EHCI_PS_CS (1 << 0) /* RO connect status */ -#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) - -#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10)) - -/* - * Schedule Interface Space. - * - * IMPORTANT: Software must ensure that no interface data structure - * reachable by the EHCI host controller spans a 4K page boundary! - * - * Periodic transfers (i.e. isochronous and interrupt transfers) are - * not supported. - */ - -/* Queue Element Transfer Descriptor (qTD). */ -struct qTD { - /* this part defined by EHCI spec */ - uint32_t qt_next; /* see EHCI 3.5.1 */ -#define QT_NEXT_TERMINATE 1 - uint32_t qt_altnext; /* see EHCI 3.5.2 */ - uint32_t qt_token; /* see EHCI 3.5.3 */ -#define QT_TOKEN_DT(x) (((x) & 0x1) << 31) /* Data Toggle */ -#define QT_TOKEN_GET_DT(x) (((x) >> 31) & 0x1) -#define QT_TOKEN_TOTALBYTES(x) (((x) & 0x7fff) << 16) /* Total Bytes to Transfer */ -#define QT_TOKEN_GET_TOTALBYTES(x) (((x) >> 16) & 0x7fff) -#define QT_TOKEN_IOC(x) (((x) & 0x1) << 15) /* Interrupt On Complete */ -#define QT_TOKEN_CPAGE(x) (((x) & 0x7) << 12) /* Current Page */ -#define QT_TOKEN_CERR(x) (((x) & 0x3) << 10) /* Error Counter */ -#define QT_TOKEN_PID(x) (((x) & 0x3) << 8) /* PID Code */ -#define QT_TOKEN_PID_OUT 0x0 -#define QT_TOKEN_PID_IN 0x1 -#define QT_TOKEN_PID_SETUP 0x2 -#define QT_TOKEN_STATUS(x) (((x) & 0xff) << 0) /* Status */ -#define QT_TOKEN_GET_STATUS(x) (((x) >> 0) & 0xff) -#define QT_TOKEN_STATUS_ACTIVE 0x80 -#define QT_TOKEN_STATUS_HALTED 0x40 -#define QT_TOKEN_STATUS_DATBUFERR 0x20 -#define QT_TOKEN_STATUS_BABBLEDET 0x10 -#define QT_TOKEN_STATUS_XACTERR 0x08 -#define QT_TOKEN_STATUS_MISSEDUFRAME 0x04 -#define QT_TOKEN_STATUS_SPLITXSTATE 0x02 -#define QT_TOKEN_STATUS_PERR 0x01 -#define QT_BUFFER_CNT 5 - uint32_t qt_buffer[QT_BUFFER_CNT]; /* see EHCI 3.5.4 */ - uint32_t qt_buffer_hi[QT_BUFFER_CNT]; /* Appendix B */ - /* pad struct for 32 byte alignment */ - uint32_t unused[3]; -}; - -#define EHCI_PAGE_SIZE 4096 - -/* Queue Head (QH). */ -struct QH { - uint32_t qh_link; -#define QH_LINK_TERMINATE 1 -#define QH_LINK_TYPE_ITD 0 -#define QH_LINK_TYPE_QH 2 -#define QH_LINK_TYPE_SITD 4 -#define QH_LINK_TYPE_FSTN 6 - uint32_t qh_endpt1; -#define QH_ENDPT1_RL(x) (((x) & 0xf) << 28) /* NAK Count Reload */ -#define QH_ENDPT1_C(x) (((x) & 0x1) << 27) /* Control Endpoint Flag */ -#define QH_ENDPT1_MAXPKTLEN(x) (((x) & 0x7ff) << 16) /* Maximum Packet Length */ -#define QH_ENDPT1_H(x) (((x) & 0x1) << 15) /* Head of Reclamation List Flag */ -#define QH_ENDPT1_DTC(x) (((x) & 0x1) << 14) /* Data Toggle Control */ -#define QH_ENDPT1_DTC_IGNORE_QTD_TD 0x0 -#define QH_ENDPT1_DTC_DT_FROM_QTD 0x1 -#define QH_ENDPT1_EPS(x) (((x) & 0x3) << 12) /* Endpoint Speed */ -#define QH_ENDPT1_EPS_FS 0x0 -#define QH_ENDPT1_EPS_LS 0x1 -#define QH_ENDPT1_EPS_HS 0x2 -#define QH_ENDPT1_ENDPT(x) (((x) & 0xf) << 8) /* Endpoint Number */ -#define QH_ENDPT1_I(x) (((x) & 0x1) << 7) /* Inactivate on Next Transaction */ -#define QH_ENDPT1_DEVADDR(x) (((x) & 0x7f) << 0) /* Device Address */ - uint32_t qh_endpt2; -#define QH_ENDPT2_MULT(x) (((x) & 0x3) << 30) /* High-Bandwidth Pipe Multiplier */ -#define QH_ENDPT2_PORTNUM(x) (((x) & 0x7f) << 23) /* Port Number */ -#define QH_ENDPT2_HUBADDR(x) (((x) & 0x7f) << 16) /* Hub Address */ -#define QH_ENDPT2_UFCMASK(x) (((x) & 0xff) << 8) /* Split Completion Mask */ -#define QH_ENDPT2_UFSMASK(x) (((x) & 0xff) << 0) /* Interrupt Schedule Mask */ - uint32_t qh_curtd; - struct qTD qh_overlay; - /* - * Add dummy fill value to make the size of this struct - * aligned to 32 bytes - */ - union { - uint32_t fill[4]; - void *buffer; - }; -}; - -struct ehci_ctrl { - struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ - struct ehci_hcor *hcor; - int rootdev; - uint16_t portreset; - struct QH qh_list __aligned(USB_DMA_MINALIGN); - struct QH periodic_queue __aligned(USB_DMA_MINALIGN); - uint32_t *periodic_list; - int ntds; -}; - -/* Low level init functions */ -int ehci_hcd_init(int index, enum usb_init_type init, - struct ehci_hccr **hccr, struct ehci_hcor **hcor); -int ehci_hcd_stop(int index); - -#endif /* USB_EHCI_H */ diff --git a/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c b/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c deleted file mode 100644 index 46e4cee1d..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/isp116x-hcd.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * ISP116x HCD (Host Controller Driver) for u-boot. - * - * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it> - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c" - * (original copyright message follows): - * - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * This code is based on linux driver for sl811hs chip, source at - * drivers/usb/host/sl811.c: - * - * SL811 Host Controller Interface driver for USB. - * - * Copyright (c) 2003/06, Courage Co., Ltd. - * - * Based on: - * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, - * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, - * Adam Richter, Gregory P. Smith; - * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> - * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> - * - * [[GNU/GPL disclaimer]] - * - * and in part from AU1x00 OHCI HCD driver "u-boot/arch/mips/cpu/au1x00_usb_ohci.c" - * (original copyright message follows): - * - * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * [[GNU/GPL disclaimer]] - * - * Note: Part of this code has been derived from linux - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <malloc.h> -#include <linux/list.h> - -/* - * ISP116x chips require certain delays between accesses to its - * registers. The following timing options exist. - * - * 1. Configure your memory controller (the best) - * 2. Use ndelay (easiest, poorest). For that, enable the following macro. - * - * Value is in microseconds. - */ -#ifdef ISP116X_HCD_USE_UDELAY -#define UDELAY 1 -#endif - -/* - * On some (slowly?) machines an extra delay after data packing into - * controller's FIFOs is required, * otherwise you may get the following - * error: - * - * uboot> usb start - * (Re)start USB... - * USB: scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT - * isp116x: isp116x_submit_job: ****** FIFO not ready! ****** - * - * USB device not responding, giving up (status=4) - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * 3 USB Device(s) found - * scanning bus for storage devices... 0 Storage Device(s) found - * - * Value is in milliseconds. - */ -#ifdef ISP116X_HCD_USE_EXTRA_DELAY -#define EXTRA_DELAY 2 -#endif - -/* - * Enable the following defines if you wish enable debugging messages. - */ -#undef DEBUG /* enable debugging messages */ -#undef TRACE /* enable tracing code */ -#undef VERBOSE /* verbose debugging messages */ - -#include "isp116x.h" - -#define DRIVER_VERSION "08 Jan 2007" -static const char hcd_name[] = "isp116x-hcd"; - -struct isp116x isp116x_dev; -struct isp116x_platform_data isp116x_board; -static int got_rhsc; /* root hub status change */ -struct usb_device *devgone; /* device which was disconnected */ -static int rh_devnum; /* address of Root Hub endpoint */ - -/* ------------------------------------------------------------------------- */ - -#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) -#define min_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) - -/* ------------------------------------------------------------------------- */ - -static int isp116x_reset(struct isp116x *isp116x); - -/* --- Debugging functions ------------------------------------------------- */ - -#define isp116x_show_reg(d, r) { \ - if ((r) < 0x20) { \ - DBG("%-12s[%02x]: %08x", #r, \ - r, isp116x_read_reg32(d, r)); \ - } else { \ - DBG("%-12s[%02x]: %04x", #r, \ - r, isp116x_read_reg16(d, r)); \ - } \ -} - -#define isp116x_show_regs(d) { \ - isp116x_show_reg(d, HCREVISION); \ - isp116x_show_reg(d, HCCONTROL); \ - isp116x_show_reg(d, HCCMDSTAT); \ - isp116x_show_reg(d, HCINTSTAT); \ - isp116x_show_reg(d, HCINTENB); \ - isp116x_show_reg(d, HCFMINTVL); \ - isp116x_show_reg(d, HCFMREM); \ - isp116x_show_reg(d, HCFMNUM); \ - isp116x_show_reg(d, HCLSTHRESH); \ - isp116x_show_reg(d, HCRHDESCA); \ - isp116x_show_reg(d, HCRHDESCB); \ - isp116x_show_reg(d, HCRHSTATUS); \ - isp116x_show_reg(d, HCRHPORT1); \ - isp116x_show_reg(d, HCRHPORT2); \ - isp116x_show_reg(d, HCHWCFG); \ - isp116x_show_reg(d, HCDMACFG); \ - isp116x_show_reg(d, HCXFERCTR); \ - isp116x_show_reg(d, HCuPINT); \ - isp116x_show_reg(d, HCuPINTENB); \ - isp116x_show_reg(d, HCCHIPID); \ - isp116x_show_reg(d, HCSCRATCH); \ - isp116x_show_reg(d, HCITLBUFLEN); \ - isp116x_show_reg(d, HCATLBUFLEN); \ - isp116x_show_reg(d, HCBUFSTAT); \ - isp116x_show_reg(d, HCRDITL0LEN); \ - isp116x_show_reg(d, HCRDITL1LEN); \ -} - -#if defined(TRACE) - -static int isp116x_get_current_frame_number(struct usb_device *usb_dev) -{ - struct isp116x *isp116x = &isp116x_dev; - - return isp116x_read_reg32(isp116x, HCFMNUM); -} - -static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, char *str) -{ -#if defined(VERBOSE) - int i; -#endif - - DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", - str, - isp116x_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? - (usb_pipeint(pipe) ? - "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); -#if defined(VERBOSE) - if (len > 0 && buffer) { - printf(__FILE__ ": data(%d):", len); - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); - } -#endif -} - -#define PTD_DIR_STR(ptd) ({char __c; \ - switch(PTD_GET_DIR(ptd)){ \ - case 0: __c = 's'; break; \ - case 1: __c = 'o'; break; \ - default: __c = 'i'; break; \ - }; __c;}) - -/* - Dump PTD info. The code documents the format - perfectly, right :) -*/ -static inline void dump_ptd(struct ptd *ptd) -{ -#if defined(VERBOSE) - int k; -#endif - - DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x", - PTD_GET_CC(ptd), - PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), - PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), - PTD_GET_TOGGLE(ptd), - PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); -#if defined(VERBOSE) - printf("isp116x: %s: PTD(byte): ", __FUNCTION__); - for (k = 0; k < sizeof(struct ptd); ++k) - printf("%02x ", ((u8 *) ptd)[k]); - printf("\n"); -#endif -} - -static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type) -{ -#if defined(VERBOSE) - int k; - - if (type == 0 /* 0ut data */ ) { - printf("isp116x: %s: out data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_LEN(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - if (type == 1 /* 1n data */ ) { - printf("isp116x: %s: in data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_COUNT(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - - if (PTD_GET_LAST(ptd)) - DBG("--- last PTD ---"); -#endif -} - -#else - -#define dump_msg(dev, pipe, buffer, len, str) do { } while (0) -#define dump_pkt(dev, pipe, buffer, len, setup, str, small) do {} while (0) - -#define dump_ptd(ptd) do {} while (0) -#define dump_ptd_data(ptd, buf, type) do {} while (0) - -#endif - -/* --- Virtual Root Hub ---------------------------------------------------- */ - -#include <usbroothubdes.h> - -/* - * Hub class-specific descriptor is constructed dynamically - */ - -/* --- Virtual root hub management functions ------------------------------- */ - -static int rh_check_port_status(struct isp116x *isp116x) -{ - u32 temp, ndp, i; - int res; - - res = -1; - temp = isp116x_read_reg32(isp116x, HCRHSTATUS); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -/* --- HC management functions --------------------------------------------- */ - -/* Write len bytes to fifo, pad till 32-bit boundary - */ -static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = *dp++; - w |= *dp++ << 8; - isp116x_raw_write_data16(isp116x, w); - } - if (len) - isp116x_write_data16(isp116x, (u16) * dp); - } else { - /* aligned */ - for (; len > 1; len -= 2) - isp116x_raw_write_data16(isp116x, *dp2++); - if (len) - isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); - } - if (quot == 1 || quot == 2) - isp116x_raw_write_data16(isp116x, 0); -} - -/* Read len bytes from fifo and then read till 32-bit boundary - */ -static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = isp116x_raw_read_data16(isp116x); - *dp++ = w & 0xff; - *dp++ = (w >> 8) & 0xff; - } - if (len) - *dp = 0xff & isp116x_read_data16(isp116x); - } else { - /* aligned */ - for (; len > 1; len -= 2) - *dp2++ = isp116x_raw_read_data16(isp116x); - if (len) - *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); - } - if (quot == 1 || quot == 2) - isp116x_raw_read_data16(isp116x); -} - -/* Write PTD's and data for scheduled transfers into the fifo ram. - * Fifo must be empty and ready */ -static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done; - - DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); - - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - dump_ptd(&ptd[i]); - isp116x_write_data16(isp116x, ptd[i].count); - isp116x_write_data16(isp116x, ptd[i].mps); - isp116x_write_data16(isp116x, ptd[i].len); - isp116x_write_data16(isp116x, ptd[i].faddr); - - dump_ptd_data(&ptd[i], (__u8 *) data + done, 0); - write_ptddata_to_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - - done += PTD_GET_LEN(&ptd[i]); - } -} - -/* Read the processed PTD's and data from fifo ram back to URBs' buffers. - * Fifo must be full and done */ -static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done, cc, ret; - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT); - - ret = TD_CC_NOERROR; - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - ptd[i].count = isp116x_read_data16(isp116x); - ptd[i].mps = isp116x_read_data16(isp116x); - ptd[i].len = isp116x_read_data16(isp116x); - ptd[i].faddr = isp116x_read_data16(isp116x); - dump_ptd(&ptd[i]); - - read_ptddata_from_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - dump_ptd_data(&ptd[i], (__u8 *) data + done, 1); - - done += PTD_GET_LEN(&ptd[i]); - - cc = PTD_GET_CC(&ptd[i]); - - /* Data underrun means basically that we had more buffer space than - * the function had data. It is perfectly normal but upper levels have - * to know how much we actually transferred. - */ - if (cc == TD_NOTACCESSED || - (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN))) - ret = cc; - } - - DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - return ret; -} - -/* Interrupt handling - */ -static int isp116x_interrupt(struct isp116x *isp116x) -{ - u16 irqstat; - u32 intstat; - int ret = 0; - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - irqstat = isp116x_read_reg16(isp116x, HCuPINT); - isp116x_write_reg16(isp116x, HCuPINT, irqstat); - DBG(">>>>>> irqstat %x <<<<<<", irqstat); - - if (irqstat & HCuPINT_ATL) { - DBG(">>>>>> HCuPINT_ATL <<<<<<"); - udelay(500); - ret = 1; - } - - if (irqstat & HCuPINT_OPR) { - intstat = isp116x_read_reg32(isp116x, HCINTSTAT); - isp116x_write_reg32(isp116x, HCINTSTAT, intstat); - DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat); - - if (intstat & HCINT_UE) { - ERR("unrecoverable error, controller disabled"); - - /* FIXME: be optimistic, hope that bug won't repeat - * often. Make some non-interrupt context restart the - * controller. Count and limit the retries though; - * either hardware or software errors can go forever... - */ - isp116x_reset(isp116x); - ret = -1; - return -1; - } - - if (intstat & HCINT_RHSC) { - got_rhsc = 1; - ret = 1; - /* When root hub or any of its ports is going - to come out of suspend, it may take more - than 10ms for status bits to stabilize. */ - mdelay(20); - } - - if (intstat & HCINT_SO) { - ERR("schedule overrun"); - ret = -1; - } - - irqstat &= ~HCuPINT_OPR; - } - - return ret; -} - -/* With one PTD we can transfer almost 1K in one go; - * HC does the splitting into endpoint digestible transactions - */ -struct ptd ptd[1]; - -static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe) -{ - unsigned mpck = usb_maxpacket(dev, pipe); - - /* One PTD can transfer 1023 bytes but try to always - * transfer multiples of endpoint buffer size - */ - return 1023 / mpck * mpck; -} - -/* Do an USB transfer - */ -static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe, - int dir, void *buffer, int len) -{ - struct isp116x *isp116x = &isp116x_dev; - int type = usb_pipetype(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int dir_out = usb_pipeout(pipe); - int speed_low = (dev->speed == USB_SPEED_LOW); - int i, done = 0, stat, timeout, cc; - - /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */ - int retries = 500; - - DBG("------------------------------------------------"); - dump_msg(dev, pipe, buffer, len, "SUBMIT"); - DBG("------------------------------------------------"); - - if (len >= 1024) { - ERR("Too big job"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (isp116x->disabled) { - ERR("EPIPE"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - ERR("ENODEV"); - dev->status = USB_ST_CRC_ERR; - return USB_ST_CRC_ERR; - } - - if (!max) { - ERR("pipesize for pipe %lx is zero", pipe); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (type == PIPE_ISOCHRONOUS) { - ERR("isochronous transfers not supported"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* FIFO not empty? */ - if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) { - ERR("****** FIFO not empty! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - retry: - isp116x_write_reg32(isp116x, HCINTSTAT, 0xff); - - /* Prepare the PTD data */ - ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | - PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out)); - ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK; - ptd->len = PTD_LEN(len) | PTD_DIR(dir); - ptd->faddr = PTD_FA(usb_pipedevice(pipe)); - -retry_same: - /* Pack data into FIFO ram */ - pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); -#ifdef EXTRA_DELAY - mdelay(EXTRA_DELAY); -#endif - - /* Start the data transfer */ - - /* Allow more time for a BULK device to react - some are slow */ - if (usb_pipebulk(pipe)) - timeout = 5000; - else - timeout = 100; - - /* Wait for it to complete */ - for (;;) { - /* Check whether the controller is done */ - stat = isp116x_interrupt(isp116x); - - if (stat < 0) { - dev->status = USB_ST_CRC_ERR; - break; - } - if (stat > 0) - break; - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - ERR("CTL:TIMEOUT "); - stat = USB_ST_CRC_ERR; - break; - } - } - - /* We got an Root Hub Status Change interrupt */ - if (got_rhsc) { - isp116x_show_regs(isp116x); - - got_rhsc = 0; - - /* Abuse timeout */ - timeout = rh_check_port_status(isp116x); - if (timeout >= 0) { - /* - * FIXME! NOTE! AAAARGH! - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } - - /* Ok, now we can read transfer status */ - - /* FIFO not ready? */ - if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) { - ERR("****** FIFO not ready! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - /* Unpack data from FIFO ram */ - cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); - - i = PTD_GET_COUNT(ptd); - done += i; - buffer += i; - len -= i; - - /* There was some kind of real problem; Prepare the PTD again - * and retry from the failed transaction on - */ - if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) { - if (retries >= 100) { - retries -= 100; - /* The chip will have toggled the toggle bit for the failed - * transaction too. We have to toggle it back. - */ - usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed - * the transactions from the first on for the whole frame. It may be busy and we retry - * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the - * PTD didn't make it because the function was busy or the frame ended before the PTD - * finished. We prepare the rest of the data and try again. - */ - else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) { - if (retries) { - --retries; - if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same; - usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - - if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) { - DBG("****** completition code error %x ******", cc); - switch (cc) { - case TD_CC_BITSTUFFING: - dev->status = USB_ST_BIT_ERR; - break; - case TD_CC_STALL: - dev->status = USB_ST_STALLED; - break; - case TD_BUFFEROVERRUN: - case TD_BUFFERUNDERRUN: - dev->status = USB_ST_BUF_ERR; - break; - default: - dev->status = USB_ST_CRC_ERR; - } - return -cc; - } - else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - - dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)"); - - dev->status = 0; - return done; -} - -/* Adapted from au1x00_usb_ohci.c - */ -static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - struct isp116x *isp116x = &isp116x_dev; - u32 tmp = 0; - - int leni = transfer_len; - int len = 0; - int stat = 0; - u32 datab[4]; - u8 *data_buf = (u8 *) datab; - u16 bmRType_bReq; - u16 wValue; - u16 wIndex; - u16 wLength; - - if (usb_pipeint(pipe)) { - INFO("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = swap_16(cmd->value); - wIndex = swap_16(cmd->index); - wLength = swap_16(cmd->length); - - DBG("--- HUB ----------------------------------------"); - DBG("submit rh urb, req=%x val=%#x index=%#x len=%d", - bmRType_bReq, wValue, wIndex, wLength); - dump_msg(dev, pipe, buffer, transfer_len, "RH"); - DBG("------------------------------------------------"); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - DBG("RH_GET_STATUS"); - - *(__u16 *) data_buf = swap_16(1); - len = 2; - break; - - case RH_GET_STATUS | RH_INTERFACE: - DBG("RH_GET_STATUS | RH_INTERFACE"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_ENDPOINT: - DBG("RH_GET_STATUS | RH_ENDPOINT"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_CLASS: - DBG("RH_GET_STATUS | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHSTATUS); - - *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE)); - len = 4; - break; - - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1); - *(__u32 *) data_buf = swap_32(tmp); - isp116x_show_regs(isp116x); - len = 4; - break; - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - DBG("RH_CLEAR_FEATURE | RH_ENDPOINT"); - - switch (wValue) { - case RH_ENDPOINT_STALL: - DBG("C_HUB_ENDPOINT_STALL"); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_CLASS"); - - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - DBG("C_HUB_LOCAL_POWER"); - len = 0; - break; - - case RH_C_HUB_OVER_CURRENT: - DBG("C_HUB_OVER_CURRENT"); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CCS); - len = 0; - break; - - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_LSDA); - len = 0; - break; - - case RH_C_PORT_CONNECTION: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CSC); - len = 0; - break; - - case RH_C_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PESC); - len = 0; - break; - - case RH_C_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSSC); - len = 0; - break; - - case RH_C_PORT_OVER_CURRENT: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_C_PORT_RESET: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRSC); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSS); - len = 0; - break; - - case RH_PORT_RESET: - /* Spin until any current reset finishes */ - while (1) { - tmp = - isp116x_read_reg32(isp116x, - HCRHPORT1 + wIndex - 1); - if (!(tmp & RH_PS_PRS)) - break; - mdelay(1); - } - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRS); - mdelay(10); - - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PPS); - len = 0; - break; - - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PES); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_ADDRESS: - DBG("RH_SET_ADDRESS"); - - rh_devnum = wValue; - len = 0; - break; - - case RH_GET_DESCRIPTOR: - DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength); - - switch (wValue) { - case (USB_DT_DEVICE << 8): /* device descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; - break; - - case (USB_DT_CONFIG << 8): /* configuration descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - break; - - case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - break; - - case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - DBG("RH_GET_DESCRIPTOR | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHDESCA); - - data_buf[0] = 0x09; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = tmp & RH_A_NDP; - data_buf[3] = 0; - if (tmp & RH_A_PSM) /* per-port power switching? */ - data_buf[3] |= 0x01; - if (tmp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (tmp & RH_A_OCPM) /* per-port overcurrent rep? */ - data_buf[3] |= 0x08; - - /* Corresponds to data_buf[4-7] */ - datab[1] = 0; - data_buf[5] = (tmp & RH_A_POTPGT) >> 24; - - tmp = isp116x_read_reg32(isp116x, HCRHDESCB); - - data_buf[7] = tmp & RH_B_DR; - if (data_buf[2] < 7) - data_buf[8] = 0xff; - else { - data_buf[0] += 2; - data_buf[8] = (tmp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - break; - - case RH_GET_CONFIGURATION: - DBG("RH_GET_CONFIGURATION"); - - *(__u8 *) data_buf = 0x01; - len = 1; - break; - - case RH_SET_CONFIGURATION: - DBG("RH_SET_CONFIGURATION"); - - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC); - len = 0; - break; - - default: - ERR("*** *** *** unsupported root hub command *** *** ***"); - stat = USB_ST_STALLED; - } - - len = min_t(int, len, leni); - if (buffer != data_buf) - memcpy(buffer, data_buf, len); - - dev->act_len = len; - dev->status = stat; - DBG("dev act_len %d, status %d", dev->act_len, dev->status); - - dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)"); - - return stat; -} - -/* --- Transfer functions -------------------------------------------------- */ - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) -{ - DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d", - dev, pipe, buffer, len, interval); - - return -1; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, struct devrequest *setup) -{ - int devnum = usb_pipedevice(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = max_transfer_len(dev, pipe); - int dir_in = usb_pipein(pipe); - int done, ret; - - /* Control message is for the HUB? */ - if (devnum == rh_devnum) - return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup); - - /* Ok, no HUB message so send the message to the device */ - - /* Setup phase */ - DBG("--- SETUP PHASE --------------------------------"); - usb_settoggle(dev, epnum, 1, 0); - ret = isp116x_submit_job(dev, pipe, - PTD_DIR_SETUP, - setup, sizeof(struct devrequest)); - if (ret < 0) { - DBG("control setup phase error (ret = %d", ret); - return -1; - } - - /* Data phase */ - DBG("--- DATA PHASE ---------------------------------"); - done = 0; - usb_settoggle(dev, epnum, !dir_in, 1); - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - dir_in ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("control data phase error (ret = %d)", ret); - return -1; - } - done += ret; - - if (dir_in && ret < max) /* short packet */ - break; - } - - /* Status phase */ - DBG("--- STATUS PHASE -------------------------------"); - usb_settoggle(dev, epnum, !dir_in, 1); - ret = isp116x_submit_job(dev, pipe, - !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0); - if (ret < 0) { - DBG("control status phase error (ret = %d", ret); - return -1; - } - - dev->act_len = done; - - dump_msg(dev, pipe, buffer, len, "DEV(ret)"); - - return done; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len) -{ - int dir_out = usb_pipeout(pipe); - int max = max_transfer_len(dev, pipe); - int done, ret; - - DBG("--- BULK ---------------------------------------"); - DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d", - usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); - - done = 0; - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - !dir_out ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("error on bulk message (ret = %d)", ret); - return -1; - } - - done += ret; - - if (!dir_out && ret < max) /* short packet */ - break; - } - - dev->act_len = done; - - return 0; -} - -/* --- Basic functions ----------------------------------------------------- */ - -static int isp116x_sw_reset(struct isp116x *isp116x) -{ - int retries = 15; - int ret = 0; - - DBG(""); - - isp116x->disabled = 1; - - isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); - isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); - while (--retries) { - /* It usually resets within 1 ms */ - mdelay(1); - if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) - break; - } - if (!retries) { - ERR("software reset timeout"); - ret = -1; - } - return ret; -} - -static int isp116x_reset(struct isp116x *isp116x) -{ - unsigned long t; - u16 clkrdy = 0; - int ret, timeout = 15 /* ms */ ; - - DBG(""); - - ret = isp116x_sw_reset(isp116x); - if (ret) - return ret; - - for (t = 0; t < timeout; t++) { - clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; - if (clkrdy) - break; - mdelay(1); - } - if (!clkrdy) { - ERR("clock not ready after %dms", timeout); - /* After sw_reset the clock won't report to be ready, if - H_WAKEUP pin is high. */ - ERR("please make sure that the H_WAKEUP pin is pulled low!"); - ret = -1; - } - return ret; -} - -static void isp116x_stop(struct isp116x *isp116x) -{ - u32 val; - - DBG(""); - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - /* Switch off ports' power, some devices don't come up - after next 'start' without this */ - val = isp116x_read_reg32(isp116x, HCRHDESCA); - val &= ~(RH_A_NPS | RH_A_PSM); - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); - - isp116x_sw_reset(isp116x); -} - -/* - * Configure the chip. The chip must be successfully reset by now. - */ -static int isp116x_start(struct isp116x *isp116x) -{ - struct isp116x_platform_data *board = isp116x->board; - u32 val; - - DBG(""); - - /* Clear interrupt status and disable all interrupt sources */ - isp116x_write_reg16(isp116x, HCuPINT, 0xff); - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); - isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); - - /* Hardware configuration */ - val = HCHWCFG_DBWIDTH(1); - if (board->sel15Kres) - val |= HCHWCFG_15KRSEL; - /* Remote wakeup won't work without working clock */ - if (board->remote_wakeup_enable) - val |= HCHWCFG_CLKNOTSTOP; - if (board->oc_enable) - val |= HCHWCFG_ANALOG_OC; - isp116x_write_reg16(isp116x, HCHWCFG, val); - - /* --- Root hub configuration */ - val = (25 << 24) & RH_A_POTPGT; - /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to - be always set. Yet, instead, we request individual port - power switching. */ - val |= RH_A_PSM; - /* Report overcurrent per port */ - val |= RH_A_OCPM; - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); - - val = RH_B_PPCM; - isp116x_write_reg32(isp116x, HCRHDESCB, val); - isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); - - val = 0; - if (board->remote_wakeup_enable) - val |= RH_HS_DRWE; - isp116x_write_reg32(isp116x, HCRHSTATUS, val); - isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); - - isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); - - /* Go operational */ - val = HCCONTROL_USB_OPER; - if (board->remote_wakeup_enable) - val |= HCCONTROL_RWE; - isp116x_write_reg32(isp116x, HCCONTROL, val); - - /* Disable ports to avoid race in device enumeration */ - isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); - isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); - - isp116x_show_regs(isp116x); - - isp116x->disabled = 0; - - return 0; -} - -/* --- Init functions ------------------------------------------------------ */ - -int isp116x_check_id(struct isp116x *isp116x) -{ - int val; - - val = isp116x_read_reg16(isp116x, HCCHIPID); - if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { - ERR("invalid chip ID %04x", val); - return -1; - } - - return 0; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - got_rhsc = rh_devnum = 0; - - /* Init device registers addr */ - isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR; - isp116x->data_reg = (u16 *) ISP116X_HCD_DATA; - - /* Setup specific board settings */ -#ifdef ISP116X_HCD_SEL15kRES - isp116x_board.sel15Kres = 1; -#endif -#ifdef ISP116X_HCD_OC_ENABLE - isp116x_board.oc_enable = 1; -#endif -#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE - isp116x_board.remote_wakeup_enable = 1; -#endif - isp116x->board = &isp116x_board; - - /* Try to get ISP116x silicon chip ID */ - if (isp116x_check_id(isp116x) < 0) - return -1; - - isp116x->disabled = 1; - isp116x->sleeping = 0; - - isp116x_reset(isp116x); - isp116x_start(isp116x); - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - if (!isp116x->disabled) - isp116x_stop(isp116x); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/isp116x.h b/qemu/roms/u-boot/drivers/usb/host/isp116x.h deleted file mode 100644 index 5b7afaf42..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/isp116x.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * ISP116x register declarations and HCD data structures - * - * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> - * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> - * Portions: - * Copyright (C) 2004 Lothar Wassmann - * Copyright (C) 2004 Psion Teklogix - * Copyright (C) 2004 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef DEBUG -#define DBG(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#else -#define DBG(fmt, args...) do {} while (0) -#endif - -#ifdef VERBOSE -# define VDBG DBG -#else -# define VDBG(fmt, args...) do {} while (0) -#endif - -#define ERR(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define WARN(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define INFO(fmt, args...) \ - printf("isp116x: " fmt "\n" , ## args) - -/* ------------------------------------------------------------------------- */ - -/* us of 1ms frame */ -#define MAX_LOAD_LIMIT 850 - -/* Full speed: max # of bytes to transfer for a single urb - at a time must be < 1024 && must be multiple of 64. - 832 allows transfering 4kiB within 5 frames. */ -#define MAX_TRANSFER_SIZE_FULLSPEED 832 - -/* Low speed: there is no reason to schedule in very big - chunks; often the requested long transfers are for - string descriptors containing short strings. */ -#define MAX_TRANSFER_SIZE_LOWSPEED 64 - -/* Bytetime (us), a rough indication of how much time it - would take to transfer a byte of useful data over USB */ -#define BYTE_TIME_FULLSPEED 1 -#define BYTE_TIME_LOWSPEED 20 - -/* Buffer sizes */ -#define ISP116x_BUF_SIZE 4096 -#define ISP116x_ITL_BUFSIZE 0 -#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) - -#define ISP116x_WRITE_OFFSET 0x80 - -/* --- ISP116x registers/bits ---------------------------------------------- */ - -#define HCREVISION 0x00 -#define HCCONTROL 0x01 -#define HCCONTROL_HCFS (3 << 6) /* host controller - functional state */ -#define HCCONTROL_USB_RESET (0 << 6) -#define HCCONTROL_USB_RESUME (1 << 6) -#define HCCONTROL_USB_OPER (2 << 6) -#define HCCONTROL_USB_SUSPEND (3 << 6) -#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */ -#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */ -#define HCCMDSTAT 0x02 -#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */ -#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */ -#define HCINTSTAT 0x03 -#define HCINT_SO (1 << 0) /* scheduling overrun */ -#define HCINT_WDH (1 << 1) /* writeback of done_head */ -#define HCINT_SF (1 << 2) /* start frame */ -#define HCINT_RD (1 << 3) /* resume detect */ -#define HCINT_UE (1 << 4) /* unrecoverable error */ -#define HCINT_FNO (1 << 5) /* frame number overflow */ -#define HCINT_RHSC (1 << 6) /* root hub status change */ -#define HCINT_OC (1 << 30) /* ownership change */ -#define HCINT_MIE (1 << 31) /* master interrupt enable */ -#define HCINTENB 0x04 -#define HCINTDIS 0x05 -#define HCFMINTVL 0x0d -#define HCFMREM 0x0e -#define HCFMNUM 0x0f -#define HCLSTHRESH 0x11 -#define HCRHDESCA 0x12 -#define RH_A_NDP (0x3 << 0) /* # downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* overcurrent protection - mode */ -#define RH_A_NOCP (1 << 12) /* no overcurrent protection */ -#define RH_A_POTPGT (0xff << 24) /* power on -> power good - time */ -#define HCRHDESCB 0x13 -#define RH_B_DR (0xffff << 0) /* device removable flags */ -#define RH_B_PPCM (0xffff << 16) /* port power control mask */ -#define HCRHSTATUS 0x14 -#define RH_HS_LPS (1 << 0) /* local power status */ -#define RH_HS_OCI (1 << 1) /* over current indicator */ -#define RH_HS_DRWE (1 << 15) /* device remote wakeup - enable */ -#define RH_HS_LPSC (1 << 16) /* local power status change */ -#define RH_HS_OCIC (1 << 17) /* over current indicator - change */ -#define RH_HS_CRWE (1 << 31) /* clear remote wakeup - enable */ -#define HCRHPORT1 0x15 -#define RH_PS_CCS (1 << 0) /* current connect status */ -#define RH_PS_PES (1 << 1) /* port enable status */ -#define RH_PS_PSS (1 << 2) /* port suspend status */ -#define RH_PS_POCI (1 << 3) /* port over current - indicator */ -#define RH_PS_PRS (1 << 4) /* port reset status */ -#define RH_PS_PPS (1 << 8) /* port power status */ -#define RH_PS_LSDA (1 << 9) /* low speed device attached */ -#define RH_PS_CSC (1 << 16) /* connect status change */ -#define RH_PS_PESC (1 << 17) /* port enable status change */ -#define RH_PS_PSSC (1 << 18) /* port suspend status - change */ -#define RH_PS_OCIC (1 << 19) /* over current indicator - change */ -#define RH_PS_PRSC (1 << 20) /* port reset status change */ -#define HCRHPORT_CLRMASK (0x1f << 16) -#define HCRHPORT2 0x16 -#define HCHWCFG 0x20 -#define HCHWCFG_15KRSEL (1 << 12) -#define HCHWCFG_CLKNOTSTOP (1 << 11) -#define HCHWCFG_ANALOG_OC (1 << 10) -#define HCHWCFG_DACK_MODE (1 << 8) -#define HCHWCFG_EOT_POL (1 << 7) -#define HCHWCFG_DACK_POL (1 << 6) -#define HCHWCFG_DREQ_POL (1 << 5) -#define HCHWCFG_DBWIDTH_MASK (0x03 << 3) -#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) -#define HCHWCFG_INT_POL (1 << 2) -#define HCHWCFG_INT_TRIGGER (1 << 1) -#define HCHWCFG_INT_ENABLE (1 << 0) -#define HCDMACFG 0x21 -#define HCDMACFG_BURST_LEN_MASK (0x03 << 5) -#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) -#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) -#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) -#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) -#define HCDMACFG_DMA_ENABLE (1 << 4) -#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) -#define HCDMACFG_CTR_SEL (1 << 2) -#define HCDMACFG_ITLATL_SEL (1 << 1) -#define HCDMACFG_DMA_RW_SELECT (1 << 0) -#define HCXFERCTR 0x22 -#define HCuPINT 0x24 -#define HCuPINT_SOF (1 << 0) -#define HCuPINT_ATL (1 << 1) -#define HCuPINT_AIIEOT (1 << 2) -#define HCuPINT_OPR (1 << 4) -#define HCuPINT_SUSP (1 << 5) -#define HCuPINT_CLKRDY (1 << 6) -#define HCuPINTENB 0x25 -#define HCCHIPID 0x27 -#define HCCHIPID_MASK 0xff00 -#define HCCHIPID_MAGIC 0x6100 -#define HCSCRATCH 0x28 -#define HCSWRES 0x29 -#define HCSWRES_MAGIC 0x00f6 -#define HCITLBUFLEN 0x2a -#define HCATLBUFLEN 0x2b -#define HCBUFSTAT 0x2c -#define HCBUFSTAT_ITL0_FULL (1 << 0) -#define HCBUFSTAT_ITL1_FULL (1 << 1) -#define HCBUFSTAT_ATL_FULL (1 << 2) -#define HCBUFSTAT_ITL0_DONE (1 << 3) -#define HCBUFSTAT_ITL1_DONE (1 << 4) -#define HCBUFSTAT_ATL_DONE (1 << 5) -#define HCRDITL0LEN 0x2d -#define HCRDITL1LEN 0x2e -#define HCITLPORT 0x40 -#define HCATLPORT 0x41 - -/* PTD accessor macros. */ -#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) -#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) -#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) -#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) -#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) -#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) -#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) -#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) -#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) -#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) -#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) -#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) -#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) -#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) -#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) -#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) -#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) -#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) -#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) -#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) -#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13) -#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK) -#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) -#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) -#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7) -#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK) - -/* Hardware transfer status codes -- CC from ptd->count */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define TD_NOTACCESSED 0x0F - -/* ------------------------------------------------------------------------- */ - -#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ -#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) - -/* Philips transfer descriptor */ -struct ptd { - u16 count; -#define PTD_COUNT_MSK (0x3ff << 0) -#define PTD_TOGGLE_MSK (1 << 10) -#define PTD_ACTIVE_MSK (1 << 11) -#define PTD_CC_MSK (0xf << 12) - u16 mps; -#define PTD_MPS_MSK (0x3ff << 0) -#define PTD_SPD_MSK (1 << 10) -#define PTD_LAST_MSK (1 << 11) -#define PTD_EP_MSK (0xf << 12) - u16 len; -#define PTD_LEN_MSK (0x3ff << 0) -#define PTD_DIR_MSK (3 << 10) -#define PTD_DIR_SETUP (0) -#define PTD_DIR_OUT (1) -#define PTD_DIR_IN (2) -#define PTD_B5_5_MSK (1 << 13) - u16 faddr; -#define PTD_FA_MSK (0x7f << 0) -#define PTD_FMT_MSK (1 << 7) -} __attribute__ ((packed, aligned(2))); - -struct isp116x_ep { - struct usb_device *udev; - struct ptd ptd; - - u8 maxpacket; - u8 epnum; - u8 nextpid; - - u16 length; /* of current packet */ - unsigned char *data; /* to databuf */ - - u16 error_count; -}; - -/* URB struct */ -#define N_URB_TD 48 -#define URB_DEL 1 -typedef struct { - struct isp116x_ep *ed; - void *transfer_buffer; /* (in) associated data buffer */ - int actual_length; /* (return) actual transfer length */ - unsigned long pipe; /* (in) pipe information */ -#if 0 - int state; -#endif -} urb_priv_t; - -struct isp116x_platform_data { - /* Enable internal resistors on downstream ports */ - unsigned sel15Kres:1; - /* On-chip overcurrent detection */ - unsigned oc_enable:1; - /* Enable wakeup by devices on usb bus (e.g. wakeup - by attachment/detachment or by device activity - such as moving a mouse). When chosen, this option - prevents stopping internal clock, increasing - thereby power consumption in suspended state. */ - unsigned remote_wakeup_enable:1; -}; - -struct isp116x { - u16 *addr_reg; - u16 *data_reg; - - struct isp116x_platform_data *board; - - struct dentry *dentry; - unsigned long stat1, stat2, stat4, stat8, stat16; - - /* Status flags */ - unsigned disabled:1; - unsigned sleeping:1; - - /* Root hub registers */ - u32 rhdesca; - u32 rhdescb; - u32 rhstatus; - u32 rhport[2]; - - /* Schedule for the current frame */ - struct isp116x_ep *atl_active; - int atl_buflen; - int atl_bufshrt; - int atl_last_dir; - int atl_finishing; -}; - -/* ------------------------------------------------- */ - -/* Inter-io delay (ns). The chip is picky about access timings; it - * expects at least: - * 150ns delay between consecutive accesses to DATA_REG, - * 300ns delay between access to ADDR_REG and DATA_REG - * OE, WE MUST NOT be changed during these intervals - */ -#if defined(UDELAY) -#define isp116x_delay(h,d) udelay(d) -#else -#define isp116x_delay(h,d) do {} while (0) -#endif - -static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) -{ - writew(reg & 0xff, isp116x->addr_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) -{ - writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) -{ - __raw_writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u16 isp116x_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = __raw_readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) -{ - writew(val & 0xffff, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - writew(val >> 16, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u32 isp116x_read_data32(struct isp116x *isp116x) -{ - u32 val; - - val = (u32) readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - val |= ((u32) readw(isp116x->data_reg)) << 16; - isp116x_delay(isp116x, UDELAY); - return val; -} - -/* Let's keep register access functions out of line. Hint: - we wait at least 150 ns at every access. -*/ -static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data16(isp116x); -} - -static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data32(isp116x); -} - -static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data16(isp116x, (u16) (val & 0xffff)); -} - -static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data32(isp116x, (u32) val); -} - -/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c b/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c deleted file mode 100644 index c24505e78..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-at91.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * (C) Copyright 2006 - * DENX Software Engineering <mk@denx.de> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) - -#include <asm/io.h> -#include <asm/arch/hardware.h> -#include <asm/arch/at91_pmc.h> -#include <asm/arch/clk.h> - -int usb_cpu_init(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - -#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB - /* Enable PLLB */ - writel(get_pllb_init(), &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) - ; -#ifdef CONFIG_AT91SAM9N12 - writel(AT91_PMC_USBS_USB_PLLB | AT91_PMC_USB_DIV_2, &pmc->usb); -#endif -#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL) - /* Enable UPLL */ - writel(readl(&pmc->uckr) | AT91_PMC_UPLLEN | AT91_PMC_BIASEN, - &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) - ; - - /* Select PLLA as input clock of OHCI */ - writel(AT91_PMC_USBS_USB_UPLL | AT91_PMC_USBDIV_10, &pmc->usb); -#endif - - /* Enable USB host clock. */ -#ifdef CONFIG_SAMA5D3 - writel(1 << (ATMEL_ID_UHP - 32), &pmc->pcer1); -#else - writel(1 << ATMEL_ID_UHP, &pmc->pcer); -#endif - -#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10) - writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scer); -#else - writel(ATMEL_PMC_UHP, &pmc->scer); -#endif - - return 0; -} - -int usb_cpu_stop(void) -{ - at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; - - /* Disable USB host clock. */ -#ifdef CONFIG_SAMA5D3 - writel(1 << (ATMEL_ID_UHP - 32), &pmc->pcdr1); -#else - writel(1 << ATMEL_ID_UHP, &pmc->pcdr); -#endif - -#if defined(CONFIG_AT91SAM9261) || defined(CONFIG_AT91SAM9G10) - writel(ATMEL_PMC_UHP | AT91_PMC_HCK0, &pmc->scdr); -#else - writel(ATMEL_PMC_UHP, &pmc->scdr); -#endif - -#ifdef CONFIG_USB_ATMEL_CLK_SEL_PLLB -#ifdef CONFIG_AT91SAM9N12 - writel(0, &pmc->usb); -#endif - /* Disable PLLB */ - writel(0, &pmc->pllbr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) - ; -#elif defined(CONFIG_USB_ATMEL_CLK_SEL_UPLL) - /* Disable UPLL */ - writel(readl(&pmc->uckr) & (~AT91_PMC_UPLLEN), &pmc->uckr); - while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) - ; -#endif - - return 0; -} - -int usb_cpu_init_fail(void) -{ - return usb_cpu_stop(); -} - -#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c b/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c deleted file mode 100644 index 981662806..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-da8xx.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 Sughosh Ganu <urwithsughosh@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#include <asm/arch/da8xx-usb.h> - -int usb_cpu_init(void) -{ - /* enable psc for usb2.0 */ - lpsc_on(DAVINCI_LPSC_USB20); - - /* enable psc for usb1.0 */ - lpsc_on(DAVINCI_LPSC_USB11); - - /* start the on-chip usb phy and its pll */ - if (usb_phy_on()) - return 0; - - return 1; -} - -int usb_cpu_stop(void) -{ - usb_phy_off(); - - /* turn off the usb clock and assert the module reset */ - lpsc_disable(DAVINCI_LPSC_USB11); - lpsc_disable(DAVINCI_LPSC_USB20); - - return 0; -} - -int usb_cpu_init_fail(void) -{ - return usb_cpu_stop(); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c b/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c deleted file mode 100644 index dc0a4e317..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-hcd.c +++ /dev/null @@ -1,1885 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. - * - * Interrupt support is added. Now, it has been tested - * on ULI1575 chip and works well with USB keyboard. - * - * (C) Copyright 2007 - * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com> - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * Note: Much of this code has been derived from Linux 2.4 - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell - * - * Modified for the MP2USB by (C) Copyright 2005 Eric Benard - * ebenard@eukrea.com - based on s3c24x0's driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ -/* - * IMPORTANT NOTES - * 1 - Read doc/README.generic_usb_ohci - * 2 - this driver is intended for use with USB Mass Storage Devices - * (BBB) and USB keyboard. There is NO support for Isochronous pipes! - * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG - * to activate workaround for bug #41 or this driver will NOT work! - */ - -#include <common.h> -#include <asm/byteorder.h> - -#if defined(CONFIG_PCI_OHCI) -# include <pci.h> -#if !defined(CONFIG_PCI_OHCI_DEVNO) -#define CONFIG_PCI_OHCI_DEVNO 0 -#endif -#endif - -#include <malloc.h> -#include <usb.h> - -#include "ohci.h" - -#ifdef CONFIG_AT91RM9200 -#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */ -#endif - -#if defined(CONFIG_ARM920T) || \ - defined(CONFIG_S3C24X0) || \ - defined(CONFIG_440EP) || \ - defined(CONFIG_PCI_OHCI) || \ - defined(CONFIG_MPC5200) || \ - defined(CONFIG_SYS_OHCI_USE_NPS) -# define OHCI_USE_NPS /* force NoPowerSwitching mode */ -#endif - -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ -#undef DEBUG -#undef SHOW_INFO -#undef OHCI_FILL_TRACE - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) - -#ifdef CONFIG_PCI_OHCI -static struct pci_device_id ohci_pci_ids[] = { - {0x10b9, 0x5237}, /* ULI1575 PCI OHCI module ids */ - {0x1033, 0x0035}, /* NEC PCI OHCI module ids */ - {0x1131, 0x1561}, /* Philips 1561 PCI OHCI module ids */ - /* Please add supported PCI OHCI controller ids here */ - {0, 0} -}; -#endif - -#ifdef CONFIG_PCI_EHCI_DEVNO -static struct pci_device_id ehci_pci_ids[] = { - {0x1131, 0x1562}, /* Philips 1562 PCI EHCI module ids */ - /* Please add supported PCI EHCI controller ids here */ - {0, 0} -}; -#endif - -#ifdef DEBUG -#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#endif /* DEBUG */ -#define err(format, arg...) printf("ERROR: " format "\n", ## arg) -#ifdef SHOW_INFO -#define info(format, arg...) printf("INFO: " format "\n", ## arg) -#else -#define info(format, arg...) do {} while (0) -#endif - -#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER -# define m16_swap(x) cpu_to_be16(x) -# define m32_swap(x) cpu_to_be32(x) -#else -# define m16_swap(x) cpu_to_le16(x) -# define m32_swap(x) cpu_to_le32(x) -#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */ - -/* global ohci_t */ -static ohci_t gohci; -/* this must be aligned to a 256 byte boundary */ -struct ohci_hcca ghcca[1]; -/* a pointer to the aligned storage */ -struct ohci_hcca *phcca; -/* this allocates EDs for all possible endpoints */ -struct ohci_device ohci_dev; -/* device which was disconnected */ -struct usb_device *devgone; - -static inline u32 roothub_a(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.a); } -static inline u32 roothub_b(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.b); } -static inline u32 roothub_status(struct ohci *hc) - { return ohci_readl(&hc->regs->roothub.status); } -static inline u32 roothub_portstatus(struct ohci *hc, int i) - { return ohci_readl(&hc->regs->roothub.portstatus[i]); } - -/* forward declaration */ -static int hc_interrupt(void); -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, urb_priv_t *urb, - int interval); - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv(urb_priv_t *urb) -{ - int i; - int last; - struct td *td; - - last = urb->length - 1; - if (last >= 0) { - for (i = 0; i <= last; i++) { - td = urb->td[i]; - if (td) { - td->usb_dev = NULL; - urb->td[i] = NULL; - } - } - } - free(urb); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number(struct usb_device *dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void pkt_print(urb_priv_t *purb, struct usb_device *dev, - unsigned long pipe, void *buffer, int transfer_len, - struct devrequest *setup, char *str, int small) -{ - dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe)? 'O': 'I', - usb_pipetype(pipe) < 2 ? \ - (usb_pipeint(pipe)? "INTR": "ISOC"): \ - (usb_pipecontrol(pipe)? "CTRL": "BULK"), - (purb ? purb->actual_length : 0), - transfer_len, dev->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol(pipe)) { - printf(__FILE__ ": cmd(8):"); - for (i = 0; i < 8 ; i++) - printf(" %02x", ((__u8 *) setup) [i]); - printf("\n"); - } - if (transfer_len > 0 && buffer) { - printf(__FILE__ ": data(%d/%d):", - (purb ? purb->actual_length : 0), - transfer_len); - len = usb_pipeout(pipe)? transfer_len: - (purb ? purb->actual_length : 0); - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer) [i]); - printf("%s\n", i < len? "...": ""); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the int ed tree - * inclusive iso eds */ -void ep_print_int_eds(ohci_t *ohci, char *str) -{ - int i, j; - __u32 *ed_p; - for (i = 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - ed_t *ed = (ed_t *)m32_swap(ed_p); - printf(" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printf("\n"); - } -} - -static void ohci_dump_intr_mask(char *label, __u32 mask) -{ - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} - -static void maybe_print_eds(char *label, __u32 value) -{ - ed_t *edp = (ed_t *)value; - - if (value) { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); - } -} - -static char *hcfs2string(int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} - -/* dump control and status registers */ -static void ohci_dump_status(ohci_t *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = ohci_readl(®s->revision) & 0xff; - if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = ohci_readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string(temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = ohci_readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask("intrstatus", ohci_readl(®s->intrstatus)); - ohci_dump_intr_mask("intrenable", ohci_readl(®s->intrenable)); - - maybe_print_eds("ed_periodcurrent", - ohci_readl(®s->ed_periodcurrent)); - - maybe_print_eds("ed_controlhead", ohci_readl(®s->ed_controlhead)); - maybe_print_eds("ed_controlcurrent", - ohci_readl(®s->ed_controlcurrent)); - - maybe_print_eds("ed_bulkhead", ohci_readl(®s->ed_bulkhead)); - maybe_print_eds("ed_bulkcurrent", ohci_readl(®s->ed_bulkcurrent)); - - maybe_print_eds("donehead", ohci_readl(®s->donehead)); -} - -static void ohci_dump_roothub(ohci_t *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1:0; -#endif - if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : "" - ); - } -} - -static void ohci_dump(ohci_t *controller, int verbose) -{ - dbg("OHCI controller usb-%s state", controller->slot_name); - - /* dumps some of the state we know about */ - ohci_dump_status(controller); - if (verbose) - ep_print_int_eds(controller, "hcca"); - dbg("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub(controller, 1); -} -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup) -{ - ohci_t *ohci; - ed_t *ed; - urb_priv_t *purb_priv = urb; - int i, size = 0; - struct usb_device *dev = urb->dev; - unsigned long pipe = urb->pipe; - void *buffer = urb->transfer_buffer; - int transfer_len = urb->transfer_buffer_length; - int interval = urb->interval; - - ohci = &gohci; - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - err("sohci_submit_job: EPIPE"); - return -1; - } - - /* we're about to begin a new transaction here so mark the - * URB unfinished */ - urb->finished = 0; - - /* every endpoint has a ed, locate and fill it */ - ed = ep_add_ed(dev, pipe, interval, 1); - if (!ed) { - err("sohci_submit_job: ENOMEM"); - return -1; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype(pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL:/* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0)? 2: - (transfer_len - 1) / 4096 + 3; - break; - case PIPE_INTERRUPT: /* 1 TD */ - size = 1; - break; - } - - ed->purb = urb; - - if (size >= (N_URB_TD - 1)) { - err("need %d TDs, only have %d", size, N_URB_TD); - return -1; - } - purb_priv->pipe = pipe; - - /* fill the private part of the URB */ - purb_priv->length = size; - purb_priv->ed = ed; - purb_priv->actual_length = 0; - - /* allocate the TDs */ - /* note that td[0] was allocated in ep_add_ed */ - for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc(dev); - if (!purb_priv->td[i]) { - purb_priv->length = i; - urb_free_priv(purb_priv); - err("sohci_submit_job: ENOMEM"); - return -1; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv(purb_priv); - err("sohci_submit_job: EINVAL"); - return -1; - } - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link(ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, - setup, purb_priv, interval); - - return 0; -} - -static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) -{ - struct ohci_regs *regs = hc->regs; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - /* implicitly requeued */ - if (urb->dev->irq_handle && - (urb->dev->irq_act_len = urb->actual_length)) { - ohci_writel(OHCI_INTR_WDH, ®s->intrenable); - ohci_readl(®s->intrenable); /* PCI posting flush */ - urb->dev->irq_handle(urb->dev); - ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); - ohci_readl(®s->intrdisable); /* PCI posting flush */ - } - urb->actual_length = 0; - td_submit_job( - urb->dev, - urb->pipe, - urb->transfer_buffer, - urb->transfer_buffer_length, - NULL, - urb, - urb->interval); - break; - case PIPE_CONTROL: - case PIPE_BULK: - break; - default: - return 0; - } - return 1; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number(struct usb_device *usb_dev) -{ - ohci_t *ohci = &gohci; - - return m16_swap(ohci->hcca->frame_no); -} -#endif - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* search for the right branch to insert an interrupt ed into the int tree - * do some load ballancing; - * returns the branch and - * sets the interval to interval = 2^integer (ld (interval)) */ - -static int ep_int_ballance(ohci_t *ohci, int interval, int load) -{ - int i, branch = 0; - - /* search for the least loaded interrupt endpoint - * branch of all 32 branches - */ - for (i = 0; i < 32; i++) - if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) - branch = i; - - branch = branch % interval; - for (i = branch; i < 32; i += interval) - ohci->ohci_int_load [i] += load; - - return branch; -} - -/*-------------------------------------------------------------------------*/ - -/* 2^int( ld (inter)) */ - -static int ep_2_n_interval(int inter) -{ - int i; - for (i = 0; ((inter >> i) > 1) && (i < 5); i++); - return 1 << i; -} - -/*-------------------------------------------------------------------------*/ - -/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to - * be mapped the mapping reverses the bits of a word of num_bits length */ -static int ep_rev(int num_bits, int word) -{ - int i, wout = 0; - - for (i = 0; i < num_bits; i++) - wout |= (((word >> i) & 1) << (num_bits - i - 1)); - return wout; -} - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link(ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - int int_branch; - int i; - int inter; - int interval; - int load; - __u32 *ed_p; - - ed->state = ED_OPER; - ed->int_interval = 0; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) - ohci_writel(ed, &ohci->regs->ed_controlhead); - else - ohci->ed_controltail->hwNextED = - m32_swap((unsigned long)ed); - - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - ohci_writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) - ohci_writel(ed, &ohci->regs->ed_bulkhead); - else - ohci->ed_bulktail->hwNextED = - m32_swap((unsigned long)ed); - - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - ohci_writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - - case PIPE_INTERRUPT: - load = ed->int_load; - interval = ep_2_n_interval(ed->int_period); - ed->int_interval = interval; - int_branch = ep_int_ballance(ohci, interval, load); - ed->int_branch = int_branch; - - for (i = 0; i < ep_rev(6, interval); i += inter) { - inter = 1; - for (ed_p = &(ohci->hcca->int_table[\ - ep_rev(5, i) + int_branch]); - (*ed_p != 0) && - (((ed_t *)ed_p)->int_interval >= interval); - ed_p = &(((ed_t *)ed_p)->hwNextED)) - inter = ep_rev(6, - ((ed_t *)ed_p)->int_interval); - ed->hwNextED = *ed_p; - *ed_p = m32_swap((unsigned long)ed); - } - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, - unsigned index, unsigned period) -{ - for (; index < NUM_INTS; index += period) { - __u32 *ed_p = &ohci->hcca->int_table [index]; - - /* ED might have been unlinked through another path */ - while (*ed_p != 0) { - if (((struct ed *) - m32_swap((unsigned long)ed_p)) == ed) { - *ed_p = ed->hwNextED; - break; - } - ed_p = &(((struct ed *) - m32_swap((unsigned long)ed_p))->hwNextED); - } - } -} - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink(ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - int i; - - ed->hwINFO |= m32_swap(OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - ohci_writel(ohci->hc_control, - &ohci->regs->control); - } - ohci_writel(m32_swap(*((__u32 *)&ed->hwNextED)), - &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - ((ed_t *)m32_swap( - *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - ohci_writel(ohci->hc_control, - &ohci->regs->control); - } - ohci_writel(m32_swap(*((__u32 *)&ed->hwNextED)), - &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - ((ed_t *)m32_swap( - *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_INTERRUPT: - periodic_unlink(ohci, ed, 0, 1); - for (i = ed->int_branch; i < 32; i += ed->int_interval) - ohci->ohci_int_load[i] -= ed->int_load; - break; - } - ed->state = ED_UNLINK; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the - * usb_set_configuration command, but the USB stack is a little bit - * stateless so we do it at every transaction if the state of the ed - * is ED_NEW then a dummy td is added and the state is changed to - * ED_UNLINK in all other cases the state is left unchanged the ed - * info fields are setted anyway even though most of them should not - * change - */ -static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, - int interval, int load) -{ - td_t *td; - ed_t *ed_ret; - volatile ed_t *ed; - - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | - (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))]; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - err("ep_add_ed: pending delete"); - /* pending delete request */ - return NULL; - } - - if (ed->state == ED_NEW) { - /* dummy td; end of td list for ed */ - td = td_alloc(usb_dev); - ed->hwTailP = m32_swap((unsigned long)td); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype(pipe); - ohci_dev.ed_cnt++; - } - - ed->hwINFO = m32_swap(usb_pipedevice(pipe) - | usb_pipeendpoint(pipe) << 7 - | (usb_pipeisoc(pipe)? 0x8000: 0) - | (usb_pipecontrol(pipe)? 0: \ - (usb_pipeout(pipe)? 0x800: 0x1000)) - | (usb_dev->speed == USB_SPEED_LOW) << 13 - | usb_maxpacket(usb_dev, pipe) << 16); - - if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { - ed->int_period = interval; - ed->int_load = load; - } - - return ed_ret; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void td_fill(ohci_t *ohci, unsigned int info, - void *data, int len, - struct usb_device *dev, int index, urb_priv_t *urb_priv) -{ - volatile td_t *td, *td_pt; -#ifdef OHCI_FILL_TRACE - int i; -#endif - - if (index > urb_priv->length) { - err("index > length"); - return; - } - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = - (td_t *)(m32_swap(urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->data = (__u32)data; -#ifdef OHCI_FILL_TRACE - if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { - for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); - printf("\n"); - } -#endif - if (!len) - data = 0; - - td->hwINFO = m32_swap(info); - td->hwCBP = m32_swap((unsigned long)data); - if (data) - td->hwBE = m32_swap((unsigned long)(data + len - 1)); - else - td->hwBE = 0; - - td->hwNextTD = m32_swap((unsigned long)td_pt); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, urb_priv_t *urb, - int interval) -{ - ohci_t *ohci = &gohci; - int data_len = transfer_len; - void *data; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle - * bits for reseting */ - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe), 1); - } - urb->td_cnt = 0; - if (data_len) - data = buffer; - else - data = 0; - - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - info = usb_pipeout(pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while (data_len > 4096) { - td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), - data, 4096, dev, cnt, urb); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout(pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill(ohci, info | (cnt? TD_T_TOGGLE:toggle), data, - data_len, dev, cnt, urb); - cnt++; - - if (!ohci->sleeping) { - /* start bulk list */ - ohci_writel(OHCI_BLF, &ohci->regs->cmdstatus); - } - break; - - case PIPE_CONTROL: - /* Setup phase */ - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill(ohci, info, setup, 8, dev, cnt++, urb); - - /* Optional Data phase */ - if (data_len > 0) { - info = usb_pipeout(pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : - TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - } - - /* Status phase */ - info = usb_pipeout(pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: - TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill(ohci, info, data, 0, dev, cnt++, urb); - - if (!ohci->sleeping) { - /* start Control list */ - ohci_writel(OHCI_CLF, &ohci->regs->cmdstatus); - } - break; - - case PIPE_INTERRUPT: - info = usb_pipeout(urb->pipe)? - TD_CC | TD_DP_OUT | toggle: - TD_CC | TD_R | TD_DP_IN | toggle; - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - break; - } - if (urb->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(td_t *td) -{ - __u32 tdBE, tdCBP; - urb_priv_t *lurb_priv = td->ed->purb; - - tdBE = m32_swap(td->hwBE); - tdCBP = m32_swap(td->hwCBP); - - if (!(usb_pipecontrol(lurb_priv->pipe) && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - lurb_priv->actual_length += tdBE - td->data + 1; - else - lurb_priv->actual_length += tdCBP - td->data; - } - } -} - -/*-------------------------------------------------------------------------*/ -static void check_status(td_t *td_list) -{ - urb_priv_t *lurb_priv = td_list->ed->purb; - int urb_len = lurb_priv->length; - __u32 *phwHeadP = &td_list->ed->hwHeadP; - int cc; - - cc = TD_CC_GET(m32_swap(td_list->hwINFO)); - if (cc) { - err(" USB-error: %s (%x)", cc_to_string[cc], cc); - - if (*phwHeadP & m32_swap(0x1)) { - if (lurb_priv && - ((td_list->index + 1) < urb_len)) { - *phwHeadP = - (lurb_priv->td[urb_len - 1]->hwNextTD &\ - m32_swap(0xfffffff0)) | - (*phwHeadP & m32_swap(0x2)); - - lurb_priv->td_cnt += urb_len - - td_list->index - 1; - } else - *phwHeadP &= m32_swap(0xfffffff2); - } -#ifdef CONFIG_MPC5200 - td_list->hwNextTD = 0; -#endif - } -} - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ -static td_t *dl_reverse_done_list(ohci_t *ohci) -{ - __u32 td_list_hc; - td_t *td_rev = NULL; - td_t *td_list = NULL; - - td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = (td_t *)td_list_hc; - check_status(td_list); - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; - } - return td_list; -} - -/*-------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------*/ - -static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) -{ - if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) - urb->finished = sohci_return_job(ohci, urb); - else - dbg("finish_urb: strange.., ED state %x, \n", status); -} - -/* - * Used to take back a TD from the host controller. This would normally be - * called from within dl_done_list, however it may be called directly if the - * HC no longer sees the TD and it has not appeared on the donelist (after - * two frames). This bug has been observed on ZF Micro systems. - */ -static int takeback_td(ohci_t *ohci, td_t *td_list) -{ - ed_t *ed; - int cc; - int stat = 0; - /* urb_t *urb; */ - urb_priv_t *lurb_priv; - __u32 tdINFO, edHeadP, edTailP; - - tdINFO = m32_swap(td_list->hwINFO); - - ed = td_list->ed; - lurb_priv = ed->purb; - - dl_transfer_length(td_list); - - lurb_priv->td_cnt++; - - /* error code of transfer */ - cc = TD_CC_GET(tdINFO); - if (cc) { - err("USB-error: %s (%x)", cc_to_string[cc], cc); - stat = cc_to_error[cc]; - } - - /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (lurb_priv->td_cnt == lurb_priv->length) - finish_urb(ohci, lurb_priv, ed->state); - - dbg("dl_done_list: processing TD %x, len %x\n", - lurb_priv->td_cnt, lurb_priv->length); - - if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) { - edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap(ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink(ohci, ed); - } - return stat; -} - -static int dl_done_list(ohci_t *ohci) -{ - int stat = 0; - td_t *td_list = dl_reverse_done_list(ohci); - - while (td_list) { - td_t *td_next = td_list->next_dl_td; - stat = takeback_td(ohci, td_list); - td_list = td_next; - } - return stat; -} - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -/* Hub class-specific descriptor is constructed dynamically */ - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#ifdef DEBUG -#define WR_RH_STAT(x) {info("WR:status %#8x", (x)); ohci_writel((x), \ - &gohci.regs->roothub.status); } -#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, \ - (x)); ohci_writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); } -#else -#define WR_RH_STAT(x) ohci_writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x) ohci_writel((x), \ - &gohci.regs->roothub.portstatus[wIndex-1]) -#endif -#define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1) - -/* request to virtual root hub */ - -int rh_check_port_status(ohci_t *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1:0; -#endif - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && - ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *cmd) -{ - void *data = buffer; - int leni = transfer_len; - int len = 0; - int stat = 0; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - ALLOC_ALIGN_BUFFER(__u8, databuf, 16, sizeof(u32)); - -#ifdef DEBUG -pkt_print(NULL, dev, pipe, buffer, transfer_len, - cmd, "SUB(rh)", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (usb_pipeint(pipe)) { - info("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = le16_to_cpu(cmd->value); - wIndex = le16_to_cpu(cmd->index); - wLength = le16_to_cpu(cmd->length); - - info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(u16 *)databuf = cpu_to_le16(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - *(u16 *)databuf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - *(u16 *)databuf = cpu_to_le16(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - *(u32 *)databuf = cpu_to_le32( - RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(u32 *)databuf = cpu_to_le32(RD_RH_PORTSTAT); - OK(4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_CCS); OK(0); - case (RH_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_POCI); OK(0); - case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_LSDA); OK(0); - case (RH_C_PORT_CONNECTION): WR_RH_PORTSTAT(RH_PS_CSC); OK(0); - case (RH_C_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_PESC); OK(0); - case (RH_C_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_PSSC); OK(0); - case (RH_C_PORT_OVER_CURRENT):WR_RH_PORTSTAT(RH_PS_OCIC); OK(0); - case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSS); OK(0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PRS); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_PPS); - mdelay(100); - OK(0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PES); - OK(0); - } - break; - - case RH_SET_ADDRESS: - gohci.rh.devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - databuf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - databuf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - databuf = root_hub_str_index0; - OK(len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - databuf = root_hub_str_index1; - OK(len); - } - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a(&gohci); - - databuf[0] = 9; /* min length; */ - databuf[1] = 0x29; - databuf[2] = temp & RH_A_NDP; -#ifdef CONFIG_AT91C_PQFP_UHPBUG - databuf[2] = (databuf[2] == 2) ? 1 : 0; -#endif - databuf[3] = 0; - if (temp & RH_A_PSM) /* per-port power switching? */ - databuf[3] |= 0x1; - if (temp & RH_A_NOCP) /* no overcurrent reporting? */ - databuf[3] |= 0x10; - else if (temp & RH_A_OCPM)/* per-port overcurrent reporting? */ - databuf[3] |= 0x8; - - databuf[4] = 0; - databuf[5] = (temp & RH_A_POTPGT) >> 24; - databuf[6] = 0; - temp = roothub_b(&gohci); - databuf[7] = temp & RH_B_DR; - if (databuf[2] < 7) { - databuf[8] = 0xff; - } else { - databuf[0] += 2; - databuf[8] = (temp & RH_B_DR) >> 8; - databuf[10] = databuf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, databuf[0], wLength)); - OK(len); - } - - case RH_GET_CONFIGURATION: - databuf[0] = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - WR_RH_STAT(0x10000); - OK(0); - - default: - dbg("unsupported root hub command"); - stat = USB_ST_STALLED; - } - -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#else - mdelay(1); -#endif - - len = min_t(int, len, leni); - if (data != databuf) - memcpy(data, databuf, len); - dev->act_len = len; - dev->status = stat; - -#ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, - transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); -#else - mdelay(1); -#endif - - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/* common code for handling submit messages - used for all but root hub */ -/* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - int stat = 0; - int maxsize = usb_maxpacket(dev, pipe); - int timeout; - urb_priv_t *urb; - - urb = malloc(sizeof(urb_priv_t)); - memset(urb, 0, sizeof(urb_priv_t)); - - urb->dev = dev; - urb->pipe = pipe; - urb->transfer_buffer = buffer; - urb->transfer_buffer_length = transfer_len; - urb->interval = interval; - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - dev->status = USB_ST_CRC_ERR; - return 0; - } - -#ifdef DEBUG - urb->actual_length = 0; - pkt_print(urb, dev, pipe, buffer, transfer_len, - setup, "SUB", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_common_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - - if (sohci_submit_job(urb, setup) < 0) { - err("sohci_submit_job failed"); - return -1; - } - -#if 0 - mdelay(10); - /* ohci_dump_status(&gohci); */ -#endif - - timeout = USB_TIMEOUT_MS(pipe); - - /* wait for it to complete */ - for (;;) { - /* check whether the controller is done */ - stat = hc_interrupt(); - if (stat < 0) { - stat = USB_ST_CRC_ERR; - break; - } - - /* NOTE: since we are not interrupt driven in U-Boot and always - * handle only one URB at a time, we cannot assume the - * transaction finished on the first successful return from - * hc_interrupt().. unless the flag for current URB is set, - * meaning that all TD's to/from device got actually - * transferred and processed. If the current URB is not - * finished we need to re-iterate this loop so as - * hc_interrupt() gets called again as there needs to be some - * more TD's to process still */ - if ((stat >= 0) && (stat != 0xff) && (urb->finished)) { - /* 0xff is returned for an SF-interrupt */ - break; - } - - if (--timeout) { - mdelay(1); - if (!urb->finished) - dbg("*"); - - } else { - err("CTL:TIMEOUT "); - dbg("submit_common_msg: TO status %x\n", stat); - urb->finished = 1; - stat = USB_ST_CRC_ERR; - break; - } - } - - dev->status = stat; - dev->act_len = urb->actual_length; - -#ifdef DEBUG - pkt_print(urb, dev, pipe, buffer, transfer_len, - setup, "RET(ctlr)", usb_pipein(pipe)); -#else - mdelay(1); -#endif - - /* free TDs in urb_priv */ - if (!usb_pipeint(pipe)) - urb_free_priv(urb); - return 0; -} - -/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - info("submit_bulk_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) -{ - int maxsize = usb_maxpacket(dev, pipe); - - info("submit_control_msg"); -#ifdef DEBUG - pkt_print(NULL, dev, pipe, buffer, transfer_len, - setup, "SUB", usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_control_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { - gohci.rh.dev = dev; - /* root hub - redirect */ - return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - } - - return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - info("submit_int_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, - interval); -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset(ohci_t *ohci) -{ -#ifdef CONFIG_PCI_EHCI_DEVNO - pci_dev_t pdev; -#endif - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - dbg("%s\n", __FUNCTION__); - -#ifdef CONFIG_PCI_EHCI_DEVNO - /* - * Some multi-function controllers (e.g. ISP1562) allow root hub - * resetting via EHCI registers only. - */ - pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVNO); - if (pdev != -1) { - u32 base; - int timeout = 1000; - - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); - base += EHCI_USBCMD_OFF; - ohci_writel(ohci_readl(base) | EHCI_USBCMD_HCRESET, base); - - while (ohci_readl(base) & EHCI_USBCMD_HCRESET) { - if (timeout-- <= 0) { - printf("USB RootHub reset timed out!"); - break; - } - udelay(1); - } - } else - printf("No EHCI func at %d index!\n", CONFIG_PCI_EHCI_DEVNO); -#endif - if (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) { - /* SMM owns the HC, request ownership */ - ohci_writel(OHCI_OCR, &ohci->regs->cmdstatus); - info("USB HC TakeOver from SMM"); - while (ohci_readl(&ohci->regs->control) & OHCI_CTRL_IR) { - mdelay(10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } - - /* Disable HC interrupts */ - ohci_writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n", - ohci->slot_name, - ohci_readl(&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - ohci->hc_control = 0; - ohci_writel(ohci->hc_control, &ohci->regs->control); - - /* HC Reset requires max 10 us delay */ - ohci_writel(OHCI_HCR, &ohci->regs->cmdstatus); - while ((ohci_readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay(1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start(ohci_t *ohci) -{ - __u32 mask; - unsigned int fminterval; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - ohci_writel(0, &ohci->regs->ed_controlhead); - ohci_writel(0, &ohci->regs->ed_bulkhead); - - ohci_writel((__u32)ohci->hcca, - &ohci->regs->hcca); /* reset clears this */ - - fminterval = 0x2edf; - ohci_writel((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - ohci_writel(fminterval, &ohci->regs->fminterval); - ohci_writel(0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - ohci_writel(ohci->hc_control, &ohci->regs->control); - - /* disable all interrupts */ - mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - ohci_writel(mask, &ohci->regs->intrdisable); - /* clear all interrupts */ - mask &= ~OHCI_INTR_MIE; - ohci_writel(mask, &ohci->regs->intrstatus); - /* Choose the interrupts we care about now - but w/o MIE */ - mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - ohci_writel(mask, &ohci->regs->intrenable); - -#ifdef OHCI_USE_NPS - /* required for AMD-756 and some Mac platforms */ - ohci_writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - ohci_writel(RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - - /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static int hc_interrupt(void) -{ - ohci_t *ohci = &gohci; - struct ohci_regs *regs = ohci->regs; - int ints; - int stat = -1; - - if ((ohci->hcca->done_head != 0) && - !(m32_swap(ohci->hcca->done_head) & 0x01)) { - ints = OHCI_INTR_WDH; - } else { - ints = ohci_readl(®s->intrstatus); - if (ints == ~(u32)0) { - ohci->disabled++; - err("%s device removed!", ohci->slot_name); - return -1; - } else { - ints &= ohci_readl(®s->intrenable); - if (ints == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; - } - } - } - - /* dbg("Interrupt: %x frame: %x", ints, - le16_to_cpu(ohci->hcca->frame_no)); */ - - if (ints & OHCI_INTR_RHSC) - stat = 0xff; - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); - /* e.g. due to PCI Master/Target Abort */ - -#ifdef DEBUG - ohci_dump(ohci, 1); -#else - mdelay(1); -#endif - /* FIXME: be optimistic, hope that bug won't repeat often. */ - /* Make some non-interrupt context restart the controller. */ - /* Count and limit the retries though; either hardware or */ - /* software errors can go forever... */ - hc_reset(ohci); - return -1; - } - - if (ints & OHCI_INTR_WDH) { - mdelay(1); - ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); - (void)ohci_readl(®s->intrdisable); /* flush */ - stat = dl_done_list(&gohci); - ohci_writel(OHCI_INTR_WDH, ®s->intrenable); - (void)ohci_readl(®s->intrdisable); /* flush */ - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun\n"); - ohci_writel(OHCI_INTR_SO, ®s->intrenable); - stat = -1; - } - - /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ - if (ints & OHCI_INTR_SF) { - unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; - mdelay(1); - ohci_writel(OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[frame] != NULL) - ohci_writel(OHCI_INTR_SF, ®s->intrenable); - stat = 0xff; - } - - ohci_writel(ints, ®s->intrstatus); - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci(ohci_t *ohci) -{ - dbg("USB HC release ohci usb-%s", ohci->slot_name); - - if (!ohci->disabled) - hc_reset(ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * low level initalisation routine, called from usb.c - */ -static char ohci_inited = 0; - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ -#ifdef CONFIG_PCI_OHCI - pci_dev_t pdev; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant init */ - if (usb_cpu_init()) - return -1; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant init */ - if (board_usb_init(index, USB_INIT_HOST)) - return -1; -#endif - memset(&gohci, 0, sizeof(ohci_t)); - - /* align the storage */ - if ((__u32)&ghcca[0] & 0xff) { - err("HCCA not aligned!!"); - return -1; - } - phcca = &ghcca[0]; - info("aligned ghcca %p", phcca); - memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32)&ohci_dev.ed[0] & 0x7) { - err("EDs not aligned!!"); - return -1; - } - memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); - if ((__u32)gtd & 0x7) { - err("TDs not aligned!!"); - return -1; - } - ptd = gtd; - gohci.hcca = phcca; - memset(phcca, 0, sizeof(struct ohci_hcca)); - - gohci.disabled = 1; - gohci.sleeping = 0; - gohci.irq = -1; -#ifdef CONFIG_PCI_OHCI - pdev = pci_find_devices(ohci_pci_ids, CONFIG_PCI_OHCI_DEVNO); - - if (pdev != -1) { - u16 vid, did; - u32 base; - pci_read_config_word(pdev, PCI_VENDOR_ID, &vid); - pci_read_config_word(pdev, PCI_DEVICE_ID, &did); - printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n", - vid, did, (pdev >> 16) & 0xff, - (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7); - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); - printf("OHCI regs address 0x%08x\n", base); - gohci.regs = (struct ohci_regs *)base; - } else - return -1; -#else - gohci.regs = (struct ohci_regs *)CONFIG_SYS_USB_OHCI_REGS_BASE; -#endif - - gohci.flags = 0; - gohci.slot_name = CONFIG_SYS_USB_OHCI_SLOT_NAME; - - if (hc_reset (&gohci) < 0) { - hc_release_ohci (&gohci); - err ("can't reset usb-%s", gohci.slot_name); -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - board_usb_cleanup(index, USB_INIT_HOST); -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - usb_cpu_init_fail(); -#endif - return -1; - } - - if (hc_start(&gohci) < 0) { - err("can't start usb-%s", gohci.slot_name); - hc_release_ohci(&gohci); - /* Initialization failed */ -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - usb_board_stop(); -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - usb_cpu_stop(); -#endif - return -1; - } - -#ifdef DEBUG - ohci_dump(&gohci, 1); -#else - mdelay(1); -#endif - ohci_inited = 1; - return 0; -} - -int usb_lowlevel_stop(int index) -{ - /* this gets called really early - before the controller has */ - /* even been initialized! */ - if (!ohci_inited) - return 0; - /* TODO release any interrupts, etc. */ - /* call hc_release_ohci() here ? */ - hc_reset(&gohci); - -#ifdef CONFIG_SYS_USB_OHCI_BOARD_INIT - /* board dependant cleanup */ - if (usb_board_stop()) - return -1; -#endif - -#ifdef CONFIG_SYS_USB_OHCI_CPU_INIT - /* cpu dependant cleanup */ - if (usb_cpu_stop()) - return -1; -#endif - /* This driver is no longer initialised. It needs a new low-level - * init (board/cpu) before it can be used again. */ - ohci_inited = 0; - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c b/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c deleted file mode 100644 index 3c659c60c..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.c +++ /dev/null @@ -1,1691 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB on the S3C2400. - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * Note: Much of this code has been derived from Linux 2.4 - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - */ -/* - * IMPORTANT NOTES - * 1 - this driver is intended for use with USB Mass Storage Devices - * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! - */ - -#include <common.h> -/* #include <pci.h> no PCI on the S3C24X0 */ - -#if defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) - -#include <asm/arch/s3c24x0_cpu.h> -#include <asm/io.h> -#include <malloc.h> -#include <usb.h> -#include "ohci-s3c24xx.h" - -#define OHCI_USE_NPS /* force NoPowerSwitching mode */ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ - - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) - -#undef DEBUG -#ifdef DEBUG -#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) -#else -#define dbg(format, arg...) do {} while(0) -#endif /* DEBUG */ -#define err(format, arg...) printf("ERROR: " format "\n", ## arg) -#undef SHOW_INFO -#ifdef SHOW_INFO -#define info(format, arg...) printf("INFO: " format "\n", ## arg) -#else -#define info(format, arg...) do {} while(0) -#endif - -#define m16_swap(x) swap_16(x) -#define m32_swap(x) swap_32(x) - -/* global struct ohci */ -static struct ohci gohci; -/* this must be aligned to a 256 byte boundary */ -struct ohci_hcca ghcca[1]; -/* a pointer to the aligned storage */ -struct ohci_hcca *phcca; -/* this allocates EDs for all possible endpoints */ -struct ohci_device ohci_dev; -/* urb_priv */ -struct urb_priv urb_priv; -/* RHSC flag */ -int got_rhsc; -/* device which was disconnected */ -struct usb_device *devgone; -/* flag guarding URB transation */ -int urb_finished = 0; - -/*-------------------------------------------------------------------------*/ - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define OHCI_QUIRK_AMD756 0xabcd -#define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ - if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a(struct ohci *hc) -{ - return read_roothub(hc, a, 0xfc0fe000); -} -static inline u32 roothub_b(struct ohci *hc) -{ - return readl(&hc->regs->roothub.b); -} -static inline u32 roothub_status(struct ohci *hc) -{ - return readl(&hc->regs->roothub.status); -} -static u32 roothub_portstatus(struct ohci *hc, int i) -{ - return read_roothub(hc, portstatus[i], 0xffe0fce0); -} - -/* forward declaration */ -static int hc_interrupt(void); -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, struct urb_priv *urb, - int interval); - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv(struct urb_priv *urb) -{ - int i; - int last; - struct td *td; - - last = urb->length - 1; - if (last >= 0) { - for (i = 0; i <= last; i++) { - td = urb->td[i]; - if (td) { - td->usb_dev = NULL; - urb->td[i] = NULL; - } - } - } -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number(struct usb_device *dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void pkt_print(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, char *str, - int small) -{ - struct urb_priv *purb = &urb_priv; - - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? - (usb_pipeint(pipe) ? "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), - purb->actual_length, transfer_len, dev->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol(pipe)) { - printf(__FILE__ ": cmd(8):"); - for (i = 0; i < 8; i++) - printf(" %02x", ((__u8 *) setup)[i]); - printf("\n"); - } - if (transfer_len > 0 && buffer) { - printf(__FILE__ ": data(%d/%d):", - purb->actual_length, transfer_len); - len = usb_pipeout(pipe) ? - transfer_len : purb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the - int ed tree inclusive iso eds*/ -void ep_print_int_eds(struct ohci *ohci, char *str) -{ - int i, j; - __u32 *ed_p; - for (i = 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table[i]); - if (*ed_p == 0) - continue; - printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - struct ed *ed = (struct ed *) m32_swap(ed_p); - printf(" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printf("\n"); - } -} - -static void ohci_dump_intr_mask(char *label, __u32 mask) -{ - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : ""); -} - -static void maybe_print_eds(char *label, __u32 value) -{ - struct ed *edp = (struct ed *) value; - - if (value) { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); - } -} - -static char *hcfs2string(int state) -{ - switch (state) { - case OHCI_USB_RESET: - return "reset"; - case OHCI_USB_RESUME: - return "resume"; - case OHCI_USB_OPER: - return "operational"; - case OHCI_USB_SUSPEND: - return "suspend"; - } - return "?"; -} - -/* dump control and status registers */ -static void ohci_dump_status(struct ohci *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = readl(®s->revision) & 0xff; - if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string(temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", temp & OHCI_CTRL_CBSR); - - temp = readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", (temp & OHCI_HCR) ? " HCR" : ""); - - ohci_dump_intr_mask("intrstatus", readl(®s->intrstatus)); - ohci_dump_intr_mask("intrenable", readl(®s->intrenable)); - - maybe_print_eds("ed_periodcurrent", readl(®s->ed_periodcurrent)); - - maybe_print_eds("ed_controlhead", readl(®s->ed_controlhead)); - maybe_print_eds("ed_controlcurrent", readl(®s->ed_controlcurrent)); - - maybe_print_eds("ed_bulkhead", readl(®s->ed_bulkhead)); - maybe_print_eds("ed_bulkcurrent", readl(®s->ed_bulkcurrent)); - - maybe_print_eds("donehead", readl(®s->donehead)); -} - -static void ohci_dump_roothub(struct ohci *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); - - if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", ndp); - temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", - temp, (temp & RH_B_PPCM) >> 16, (temp & RH_B_DR) - ); - temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : ""); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : ""); - } -} - -static void ohci_dump(struct ohci *controller, int verbose) -{ - dbg("OHCI controller usb-%s state", controller->slot_name); - - /* dumps some of the state we know about */ - ohci_dump_status(controller); - if (verbose) - ep_print_int_eds(controller, "hcca"); - dbg("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub(controller, 1); -} - -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - struct ohci *ohci; - struct ed *ed; - struct urb_priv *purb_priv; - int i, size = 0; - - ohci = &gohci; - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - err("sohci_submit_job: EPIPE"); - return -1; - } - - /* if we have an unfinished URB from previous transaction let's - * fail and scream as quickly as possible so as not to corrupt - * further communication */ - if (!urb_finished) { - err("sohci_submit_job: URB NOT FINISHED"); - return -1; - } - /* we're about to begin a new transaction here - so mark the URB unfinished */ - urb_finished = 0; - - /* every endpoint has a ed, locate and fill it */ - ed = ep_add_ed(dev, pipe); - if (!ed) { - err("sohci_submit_job: ENOMEM"); - return -1; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL: - /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0) ? 2 : (transfer_len - 1) / 4096 + 3; - break; - } - - if (size >= (N_URB_TD - 1)) { - err("need %d TDs, only have %d", size, N_URB_TD); - return -1; - } - purb_priv = &urb_priv; - purb_priv->pipe = pipe; - - /* fill the private part of the URB */ - purb_priv->length = size; - purb_priv->ed = ed; - purb_priv->actual_length = 0; - - /* allocate the TDs */ - /* note that td[0] was allocated in ep_add_ed */ - for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc(dev); - if (!purb_priv->td[i]) { - purb_priv->length = i; - urb_free_priv(purb_priv); - err("sohci_submit_job: ENOMEM"); - return -1; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv(purb_priv); - err("sohci_submit_job: EINVAL"); - return -1; - } - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link(ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, - interval); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number(struct usb_device *usb_dev) -{ - struct ohci *ohci = &gohci; - - return m16_swap(ohci->hcca->frame_no); -} -#endif - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link(struct ohci *ohci, struct ed *edi) -{ - struct ed *ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel((u32)ed, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = (__u32) m32_swap(ed); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel((u32)ed, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = (__u32) m32_swap(ed); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink(struct ohci *ohci, struct ed *ed) -{ - struct ed *next; - ed->hwINFO |= m32_swap(OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel(ohci->hc_control, &ohci->regs->control); - } - writel(m32_swap(*((__u32 *) &ed->hwNextED)), - &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - next = (struct ed *)m32_swap(*((__u32 *)&ed->hwNextED)); - next->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel(ohci->hc_control, &ohci->regs->control); - } - writel(m32_swap(*((__u32 *) &ed->hwNextED)), - &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - next = (struct ed *)m32_swap(*((__u32 *)&ed->hwNextED)); - next->ed_prev = ed->ed_prev; - } - break; - } - ed->state = ED_UNLINK; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the usb_set_configuration - * command, but the USB stack is a little bit stateless so we do it at every - * transaction. If the state of the ed is ED_NEW then a dummy td is added and - * the state is changed to ED_UNLINK. In all other cases the state is left - * unchanged. The ed info fields are setted anyway even though most of them - * should not change */ - -static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe) -{ - struct td *td; - struct ed *ed_ret; - struct ed *ed; - - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint(pipe) << 1) | - (usb_pipecontrol(pipe) ? 0 : - usb_pipeout(pipe))]; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - err("ep_add_ed: pending delete"); - /* pending delete request */ - return NULL; - } - - if (ed->state == ED_NEW) { - ed->hwINFO = m32_swap(OHCI_ED_SKIP); /* skip ed */ - /* dummy td; end of td list for ed */ - td = td_alloc(usb_dev); - ed->hwTailP = (__u32) m32_swap(td); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype(pipe); - ohci_dev.ed_cnt++; - } - - ed->hwINFO = m32_swap(usb_pipedevice(pipe) - | usb_pipeendpoint(pipe) << 7 - | (usb_pipeisoc(pipe) ? 0x8000 : 0) - | (usb_pipecontrol(pipe) ? 0 : - (usb_pipeout(pipe) ? 0x800 : 0x1000)) - | (usb_dev->speed == USB_SPEED_LOW) << 13 | - usb_maxpacket(usb_dev, pipe) << 16); - - return ed_ret; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void td_fill(struct ohci *ohci, unsigned int info, void *data, int len, - struct usb_device *dev, int index, - struct urb_priv *urb_priv) -{ - struct td *td, *td_pt; -#ifdef OHCI_FILL_TRACE - int i; -#endif - - if (index > urb_priv->length) { - err("index > length"); - return; - } - /* use this td as the next dummy */ - td_pt = urb_priv->td[index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td[index] = - (struct td *) (m32_swap(urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->data = (__u32) data; -#ifdef OHCI_FILL_TRACE - if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { - for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ", i, - ((unsigned char *)td->data)[i]); - printf("\n"); - } -#endif - if (!len) - data = 0; - - td->hwINFO = (__u32) m32_swap(info); - td->hwCBP = (__u32) m32_swap(data); - if (data) - td->hwBE = (__u32) m32_swap(data + len - 1); - else - td->hwBE = 0; - td->hwNextTD = (__u32) m32_swap(td_pt); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_job(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *setup, struct urb_priv *urb, - int interval) -{ - struct ohci *ohci = &gohci; - int data_len = transfer_len; - void *data; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just - use the USB-toggle bits for reseting */ - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), - 1); - } - urb->td_cnt = 0; - if (data_len) - data = buffer; - else - data = 0; - - switch (usb_pipetype(pipe)) { - case PIPE_BULK: - info = usb_pipeout(pipe) ? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN; - while (data_len > 4096) { - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - 4096, dev, cnt, urb); - data += 4096; - data_len -= 4096; - cnt++; - } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_OUT : - TD_CC | TD_R | TD_DP_IN; - td_fill(ohci, info | (cnt ? TD_T_TOGGLE : toggle), data, - data_len, dev, cnt, urb); - cnt++; - - if (!ohci->sleeping) - /* start bulk list */ - writel(OHCI_BLF, &ohci->regs->cmdstatus); - break; - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill(ohci, info, setup, 8, dev, cnt++, urb); - if (data_len > 0) { - info = usb_pipeout(pipe) ? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : - TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ohci, info, data, data_len, dev, cnt++, urb); - } - info = usb_pipeout(pipe) ? - TD_CC | TD_DP_IN | TD_T_DATA1 : - TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill(ohci, info, data, 0, dev, cnt++, urb); - if (!ohci->sleeping) - /* start Control list */ - writel(OHCI_CLF, &ohci->regs->cmdstatus); - break; - } - if (urb->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(struct td *td) -{ - __u32 tdBE, tdCBP; - struct urb_priv *lurb_priv = &urb_priv; - - tdBE = m32_swap(td->hwBE); - tdCBP = m32_swap(td->hwCBP); - - if (!(usb_pipecontrol(lurb_priv->pipe) && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - lurb_priv->actual_length += tdBE - td->data + 1; - else - lurb_priv->actual_length += tdCBP - td->data; - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -static struct td *dl_reverse_done_list(struct ohci *ohci) -{ - __u32 td_list_hc; - __u32 tmp; - struct td *td_rev = NULL; - struct td *td_list = NULL; - struct urb_priv *lurb_priv = NULL; - - td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = (struct td *) td_list_hc; - - if (TD_CC_GET(m32_swap(td_list->hwINFO))) { - lurb_priv = &urb_priv; - dbg(" USB-error/status: %x : %p", - TD_CC_GET(m32_swap(td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & m32_swap(0x1)) { - if (lurb_priv && - ((td_list->index+1) < lurb_priv->length)) { - tmp = lurb_priv->length - 1; - td_list->ed->hwHeadP = - (lurb_priv->td[tmp]->hwNextTD & - m32_swap(0xfffffff0)) | - (td_list->ed->hwHeadP & - m32_swap(0x2)); - lurb_priv->td_cnt += lurb_priv->length - - td_list->index - 1; - } else - td_list->ed->hwHeadP &= - m32_swap(0xfffffff2); - } - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; - } - - return td_list; -} - -/*-------------------------------------------------------------------------*/ - -/* td done list */ -static int dl_done_list(struct ohci *ohci, struct td *td_list) -{ - struct td *td_list_next = NULL; - struct ed *ed; - int cc = 0; - int stat = 0; - /* urb_t *urb; */ - struct urb_priv *lurb_priv; - __u32 tdINFO, edHeadP, edTailP; - - while (td_list) { - td_list_next = td_list->next_dl_td; - - lurb_priv = &urb_priv; - tdINFO = m32_swap(td_list->hwINFO); - - ed = td_list->ed; - - dl_transfer_length(td_list); - - /* error code of transfer */ - cc = TD_CC_GET(tdINFO); - if (cc != 0) { - dbg("ConditionCode %#x", cc); - stat = cc_to_error[cc]; - } - - /* see if this done list makes for all TD's of current URB, - * and mark the URB finished if so */ - if (++(lurb_priv->td_cnt) == lurb_priv->length) { - if ((ed->state & (ED_OPER | ED_UNLINK))) - urb_finished = 1; - else - dbg("dl_done_list: strange.., ED state %x, " - "ed->state\n"); - } else - dbg("dl_done_list: processing TD %x, len %x\n", - lurb_priv->td_cnt, lurb_priv->length); - - if (ed->state != ED_NEW) { - edHeadP = m32_swap(ed->hwHeadP) & 0xfffffff0; - edTailP = m32_swap(ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink(ohci, ed); - } - - td_list = td_list_next; - } - return stat; -} - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -/* Hub class-specific descriptor is constructed dynamically */ - - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#ifdef DEBUG -#define WR_RH_STAT(x) \ -{ \ - info("WR:status %#8x", (x)); \ - writel((x), &gohci.regs->roothub.status); \ -} -#define WR_RH_PORTSTAT(x) \ -{ \ - info("WR:portstatus[%d] %#8x", wIndex-1, (x)); \ - writel((x), &gohci.regs->roothub.portstatus[wIndex-1]); \ -} -#else -#define WR_RH_STAT(x) \ - writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x)\ - writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) -#endif -#define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci, wIndex-1) - -/* request to virtual root hub */ - -int rh_check_port_status(struct ohci *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - void *data = buffer; - int leni = transfer_len; - int len = 0; - int stat = 0; - union { - __u32 word[4]; - __u16 hword[8]; - __u8 byte[16]; - } datab; - __u8 *data_buf = datab.byte; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (usb_pipeint(pipe)) { - info("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = m16_swap(cmd->value); - wIndex = m16_swap(cmd->index); - wLength = m16_swap(cmd->length); - - info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - datab.hword[0] = m16_swap(1); - OK(2); - case RH_GET_STATUS | RH_INTERFACE: - datab.hword[0] = m16_swap(0); - OK(2); - case RH_GET_STATUS | RH_ENDPOINT: - datab.hword[0] = m16_swap(0); - OK(2); - case RH_GET_STATUS | RH_CLASS: - datab.word[0] = - m32_swap(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK(4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - datab.word[0] = m32_swap(RD_RH_PORTSTAT); - OK(4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); - OK(0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_CCS); - OK(0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_POCI); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_LSDA); - OK(0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT(RH_PS_CSC); - OK(0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT(RH_PS_PESC); - OK(0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSSC); - OK(0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT(RH_PS_OCIC); - OK(0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT(RH_PS_PRSC); - OK(0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT(RH_PS_PSS); - OK(0); - case (RH_PORT_RESET): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PRS); - OK(0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT(RH_PS_PPS); - OK(0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE ******** */ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT(RH_PS_PES); - OK(0); - } - break; - - case RH_SET_ADDRESS: - gohci.rh.devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), wLength)); - data_buf = root_hub_dev_des; - OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - OK(len); - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - OK(len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - OK(len); - } - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a(&gohci); - - data_buf[0] = 9; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = temp & RH_A_NDP; - data_buf[3] = 0; - if (temp & RH_A_PSM) - /* per-port power switching? */ - data_buf[3] |= 0x1; - if (temp & RH_A_NOCP) - /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (temp & RH_A_OCPM) - /* per-port overcurrent reporting? */ - data_buf[3] |= 0x8; - - /* corresponds to data_buf[4-7] */ - datab.word[1] = 0; - data_buf[5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b(&gohci); - data_buf[7] = temp & RH_B_DR; - if (data_buf[2] < 7) { - data_buf[8] = 0xff; - } else { - data_buf[0] += 2; - data_buf[8] = (temp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - OK(len); - } - - case RH_GET_CONFIGURATION: - *(__u8 *) data_buf = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - WR_RH_STAT(0x10000); - OK(0); - - default: - dbg("unsupported root hub command"); - stat = USB_ST_STALLED; - } - -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#else - mdelay(1); -#endif - - len = min_t(int, len, leni); - if (data != data_buf) - memcpy(data, data_buf, len); - dev->act_len = len; - dev->status = stat; - -#ifdef DEBUG - if (transfer_len) - urb_priv.actual_length = transfer_len; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", - 0 /*usb_pipein(pipe) */); -#else - mdelay(1); -#endif - - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/* common code for handling submit messages - used for all but root hub */ -/* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - int stat = 0; - int maxsize = usb_maxpacket(dev, pipe); - int timeout; - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - dev->status = USB_ST_CRC_ERR; - return 0; - } -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_common_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - - if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < - 0) { - err("sohci_submit_job failed"); - return -1; - } - - mdelay(10); - /* ohci_dump_status(&gohci); */ - - /* allow more time for a BULK device to react - some are slow */ -#define BULK_TO 5000 /* timeout in milliseconds */ - if (usb_pipebulk(pipe)) - timeout = BULK_TO; - else - timeout = 100; - - /* wait for it to complete */ - for (;;) { - /* check whether the controller is done */ - stat = hc_interrupt(); - - if (stat < 0) { - stat = USB_ST_CRC_ERR; - break; - } - - /* NOTE: since we are not interrupt driven in U-Boot and always - * handle only one URB at a time, we cannot assume the - * transaction finished on the first successful return from - * hc_interrupt().. unless the flag for current URB is set, - * meaning that all TD's to/from device got actually - * transferred and processed. If the current URB is not - * finished we need to re-iterate this loop so as - * hc_interrupt() gets called again as there needs to be some - * more TD's to process still */ - if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { - /* 0xff is returned for an SF-interrupt */ - break; - } - - if (--timeout) { - mdelay(1); - if (!urb_finished) - dbg("\%"); - - } else { - err("CTL:TIMEOUT "); - dbg("submit_common_msg: TO status %x\n", stat); - stat = USB_ST_CRC_ERR; - urb_finished = 1; - break; - } - } - -#if 0 - /* we got an Root Hub Status Change interrupt */ - if (got_rhsc) { -#ifdef DEBUG - ohci_dump_roothub(&gohci, 1); -#endif - got_rhsc = 0; - /* abuse timeout */ - timeout = rh_check_port_status(&gohci); - if (timeout >= 0) { -#if 0 /* this does nothing useful, but leave it here - in case that changes */ - /* the called routine adds 1 to the passed value */ - usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); -#endif - /* - * XXX - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } -#endif - - dev->status = stat; - dev->act_len = transfer_len; - -#ifdef DEBUG - pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - - /* free TDs in urb_priv */ - urb_free_priv(&urb_priv); - return 0; -} - -/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - info("submit_bulk_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) -{ - int maxsize = usb_maxpacket(dev, pipe); - - info("submit_control_msg"); -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", - usb_pipein(pipe)); -#else - mdelay(1); -#endif - if (!maxsize) { - err("submit_control_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { - gohci.rh.dev = dev; - /* root hub - redirect */ - return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - } - - return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - info("submit_int_msg"); - return -1; -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset(struct ohci *ohci) -{ - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - if (readl(&ohci->regs->control) & OHCI_CTRL_IR) { - /* SMM owns the HC - request ownership */ - writel(OHCI_OCR, &ohci->regs->cmdstatus); - info("USB HC TakeOver from SMM"); - while (readl(&ohci->regs->control) & OHCI_CTRL_IR) { - mdelay(10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } - - /* Disable HC interrupts */ - writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", - ohci->slot_name, readl(&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - writel(0, &ohci->regs->control); - - /* HC Reset requires max 10 us delay */ - writel(OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay(1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start(struct ohci *ohci) -{ - __u32 mask; - unsigned int fminterval; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - writel(0, &ohci->regs->ed_controlhead); - writel(0, &ohci->regs->ed_bulkhead); - - /* a reset clears this */ - writel((__u32) ohci->hcca, &ohci->regs->hcca); - - fminterval = 0x2edf; - writel((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel(fminterval, &ohci->regs->fminterval); - writel(0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - writel(ohci->hc_control, &ohci->regs->control); - - /* disable all interrupts */ - mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - writel(mask, &ohci->regs->intrdisable); - /* clear all interrupts */ - mask &= ~OHCI_INTR_MIE; - writel(mask, &ohci->regs->intrstatus); - /* Choose the interrupts we care about now - but w/o MIE */ - mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel(mask, &ohci->regs->intrenable); - -#ifdef OHCI_USE_NPS - /* required for AMD-756 and some Mac platforms */ - writel((roothub_a(ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - writel(RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - - /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static int hc_interrupt(void) -{ - struct ohci *ohci = &gohci; - struct ohci_regs *regs = ohci->regs; - int ints; - int stat = -1; - - if ((ohci->hcca->done_head != 0) && - !(m32_swap(ohci->hcca->done_head) & 0x01)) { - - ints = OHCI_INTR_WDH; - - } else { - ints = readl(®s->intrstatus); - if (ints == ~(u32) 0) { - ohci->disabled++; - err("%s device removed!", ohci->slot_name); - return -1; - } - ints &= readl(®s->intrenable); - if (ints == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; - } - } - - /* dbg("Interrupt: %x frame: %x", ints, - le16_to_cpu(ohci->hcca->frame_no)); */ - - if (ints & OHCI_INTR_RHSC) { - got_rhsc = 1; - stat = 0xff; - } - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); - /* e.g. due to PCI Master/Target Abort */ - -#ifdef DEBUG - ohci_dump(ohci, 1); -#else - mdelay(1); -#endif - /* FIXME: be optimistic, hope that bug won't repeat often. */ - /* Make some non-interrupt context restart the controller. */ - /* Count and limit the retries though; either hardware or */ - /* software errors can go forever... */ - hc_reset(ohci); - return -1; - } - - if (ints & OHCI_INTR_WDH) { - mdelay(1); - - writel(OHCI_INTR_WDH, ®s->intrdisable); - stat = dl_done_list(&gohci, dl_reverse_done_list(&gohci)); - writel(OHCI_INTR_WDH, ®s->intrenable); - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun\n"); - writel(OHCI_INTR_SO, ®s->intrenable); - stat = -1; - } - - /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ - if (ints & OHCI_INTR_SF) { - unsigned int frame = m16_swap(ohci->hcca->frame_no) & 1; - mdelay(1); - writel(OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[frame] != NULL) - writel(OHCI_INTR_SF, ®s->intrenable); - stat = 0xff; - } - - writel(ints, ®s->intrstatus); - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci(struct ohci *ohci) -{ - dbg("USB HC release ohci usb-%s", ohci->slot_name); - - if (!ohci->disabled) - hc_reset(ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * low level initalisation routine, called from usb.c - */ -static char ohci_inited = 0; - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); - - /* - * Set the 48 MHz UPLL clocking. Values are taken from - * "PLL value selection guide", 6-23, s3c2400_UM.pdf. - */ - clk_power->upllcon = ((40 << 12) + (1 << 4) + 2); - gpio->misccr |= 0x8; /* 1 = use pads related USB for USB host */ - - /* - * Enable USB host clock. - */ - clk_power->clkcon |= (1 << 4); - - memset(&gohci, 0, sizeof(struct ohci)); - memset(&urb_priv, 0, sizeof(struct urb_priv)); - - /* align the storage */ - if ((__u32) &ghcca[0] & 0xff) { - err("HCCA not aligned!!"); - return -1; - } - phcca = &ghcca[0]; - info("aligned ghcca %p", phcca); - memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32) &ohci_dev.ed[0] & 0x7) { - err("EDs not aligned!!"); - return -1; - } - memset(gtd, 0, sizeof(struct td) * (NUM_TD + 1)); - if ((__u32) gtd & 0x7) { - err("TDs not aligned!!"); - return -1; - } - ptd = gtd; - gohci.hcca = phcca; - memset(phcca, 0, sizeof(struct ohci_hcca)); - - gohci.disabled = 1; - gohci.sleeping = 0; - gohci.irq = -1; - gohci.regs = (struct ohci_regs *)S3C24X0_USB_HOST_BASE; - - gohci.flags = 0; - gohci.slot_name = "s3c2400"; - - if (hc_reset(&gohci) < 0) { - hc_release_ohci(&gohci); - /* Initialization failed */ - clk_power->clkcon &= ~(1 << 4); - return -1; - } - - /* FIXME this is a second HC reset; why?? */ - gohci.hc_control = OHCI_USB_RESET; - writel(gohci.hc_control, &gohci.regs->control); - mdelay(10); - - if (hc_start(&gohci) < 0) { - err("can't start usb-%s", gohci.slot_name); - hc_release_ohci(&gohci); - /* Initialization failed */ - clk_power->clkcon &= ~(1 << 4); - return -1; - } -#ifdef DEBUG - ohci_dump(&gohci, 1); -#else - mdelay(1); -#endif - ohci_inited = 1; - urb_finished = 1; - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - - /* this gets called really early - before the controller has */ - /* even been initialized! */ - if (!ohci_inited) - return 0; - /* TODO release any interrupts, etc. */ - /* call hc_release_ohci() here ? */ - hc_reset(&gohci); - /* may not want to do this */ - clk_power->clkcon &= ~(1 << 4); - return 0; -} - -#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) */ - -#if defined(CONFIG_USB_OHCI_NEW) && \ - defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ - defined(CONFIG_S3C24X0) - -int usb_cpu_init(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); - - /* - * Set the 48 MHz UPLL clocking. Values are taken from - * "PLL value selection guide", 6-23, s3c2400_UM.pdf. - */ - writel((40 << 12) + (1 << 4) + 2, &clk_power->upllcon); - /* 1 = use pads related USB for USB host */ - writel(readl(&gpio->misccr) | 0x8, &gpio->misccr); - - /* - * Enable USB host clock. - */ - writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon); - - return 0; -} - -int usb_cpu_stop(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - /* may not want to do this */ - writel(readl(&clk_power->clkcon) & ~(1 << 4), &clk_power->clkcon); - return 0; -} - -int usb_cpu_init_fail(void) -{ - struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - writel(readl(&clk_power->clkcon) & ~(1 << 4), &clk_power->clkcon); - return 0; -} - -#endif /* defined(CONFIG_USB_OHCI_NEW) && \ - defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ - defined(CONFIG_S3C24X0) */ diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h b/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h deleted file mode 100644 index f272d7885..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci-s3c24xx.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> - * - * usb-ohci.h - */ - - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ 0, - /* CRC Error */ USB_ST_CRC_ERR, - /* Bit Stuff */ USB_ST_BIT_ERR, - /* Data Togg */ USB_ST_CRC_ERR, - /* Stall */ USB_ST_STALLED, - /* DevNotResp */ -1, - /* PIDCheck */ USB_ST_BIT_ERR, - /* UnExpPID */ USB_ST_BIT_ERR, - /* DataOver */ USB_ST_BUF_ERR, - /* DataUnder */ USB_ST_BUF_ERR, - /* reservd */ -1, - /* reservd */ -1, - /* BufferOver */ USB_ST_BUF_ERR, - /* BuffUnder */ USB_ST_BUF_ERR, - /* Not Access */ -1, - /* Not Access */ -1 -}; - -/* ED States */ -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed *ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed *ed_rm_list; - - struct usb_device *usb_dev; - __u32 unused[3]; -} __attribute__ ((aligned(16))); - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) (((td_p) >> 28) & 0x0f) -#define TD_CC_SET(td_p, cc) \ - {(td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)} -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - - __u8 unused; - __u8 index; - struct ed *ed; - struct td *next_dl_td; - struct usb_device *usb_dev; - int transfer_len; - __u32 data; - - __u32 unused2[2]; -} __attribute__ ((aligned(32))); - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute__ ((aligned(256))); - -/* - * Maximum number of root hub ports. - */ -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the readl() and - * writel() macros defined in asm/io.h to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute__ ((aligned(32))); - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *dev; /* was urb */ - void *int_addr; - int send; - int interval; -}; - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status */ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -#define N_URB_TD 48 -struct urb_priv { - struct ed *ed; - __u16 length; /* number of tds associated with this request */ - __u16 td_cnt; /* number of tds already serviced */ - int state; - unsigned long pipe; - int actual_length; - struct td *td[N_URB_TD]; /* list pointer to all corresponding TDs - associated with this request */ -}; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -struct ohci { - struct ohci_hcca *hcca; /* hcca */ - /*dma_addr_t hcca_dma; */ - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - unsigned long flags; /* for HC bugs */ - - struct ohci_regs *regs; /* OHCI controller's memory */ - - struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ - struct ed *ed_bulktail; /* last endpoint of bulk list */ - struct ed *ed_controltail; /* last endpoint of control list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_device *dev[32]; - struct virt_root_hub rh; - - const char *slot_name; -}; - -#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - struct ed ed[NUM_EDS]; - int ed_cnt; -}; - -/* hcd */ -/* endpoint */ -static int ep_link(struct ohci *ohci, struct ed *ed); -static int ep_unlink(struct ohci *ohci, struct ed *ed); -static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe); - -/*-------------------------------------------------------------------------*/ - -/* we need more TDs than EDs */ -#define NUM_TD 64 - -/* +1 so we can align the storage */ -struct td gtd[NUM_TD + 1]; - -/* pointers to aligned storage */ -struct td *ptd; - -/* TDs ... */ -static inline struct td *td_alloc(struct usb_device *usb_dev) -{ - int i; - struct td *td; - - td = NULL; - for (i = 0; i < NUM_TD; i++) { - if (ptd[i].usb_dev == NULL) { - td = &ptd[i]; - td->usb_dev = usb_dev; - break; - } - } - - return td; -} - -static inline void ed_free(struct ed *ed) -{ - ed->usb_dev = NULL; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/ohci.h b/qemu/roms/u-boot/drivers/usb/host/ohci.h deleted file mode 100644 index 9a4a2c247..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/ohci.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> - * - * usb-ohci.h - */ - -/* - * e.g. PCI controllers need this - */ -#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS -# define ohci_readl(a) __swap_32(*((volatile u32 *)(a))) -# define ohci_writel(a, b) (*((volatile u32 *)(b)) = __swap_32((volatile u32)a)) -#else -# define ohci_readl(a) (*((volatile u32 *)(a))) -# define ohci_writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) -#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */ - -/* functions for doing board or CPU specific setup/cleanup */ -int usb_board_stop(void); - -int usb_cpu_init(void); -int usb_cpu_stop(void); -int usb_cpu_init_fail(void); - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ 0, - /* CRC Error */ USB_ST_CRC_ERR, - /* Bit Stuff */ USB_ST_BIT_ERR, - /* Data Togg */ USB_ST_CRC_ERR, - /* Stall */ USB_ST_STALLED, - /* DevNotResp */ -1, - /* PIDCheck */ USB_ST_BIT_ERR, - /* UnExpPID */ USB_ST_BIT_ERR, - /* DataOver */ USB_ST_BUF_ERR, - /* DataUnder */ USB_ST_BUF_ERR, - /* reservd */ -1, - /* reservd */ -1, - /* BufferOver */ USB_ST_BUF_ERR, - /* BuffUnder */ USB_ST_BUF_ERR, - /* Not Access */ -1, - /* Not Access */ -1 -}; - -static const char *cc_to_string[16] = { - "No Error", - "CRC: Last data packet from endpoint contained a CRC error.", - "BITSTUFFING: Last data packet from endpoint contained a bit " \ - "stuffing violation", - "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ - "that did not match the expected value.", - "STALL: TD was moved to the Done Queue because the endpoint returned" \ - " a STALL PID", - "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ - "not provide a handshake (OUT)", - "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ - "(IN) or handshake (OUT)", - "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ - "value is not defined.", - "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ - "either the size of the maximum data packet allowed\n" \ - "from the endpoint (found in MaximumPacketSize field\n" \ - "of ED) or the remaining buffer size.", - "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ - "and that amount was not sufficient to fill the\n" \ - "specified buffer", - "reserved1", - "reserved2", - "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ - "than it could be written to system memory", - "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ - "system memory fast enough to keep up with data USB " \ - "data rate.", - "NOT ACCESSED: This code is set by software before the TD is placed" \ - "on a list to be processed by the HC.(1)", - "NOT ACCESSED: This code is set by software before the TD is placed" \ - "on a list to be processed by the HC.(2)", -}; - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed *ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed *ed_rm_list; - - struct usb_device *usb_dev; - void *purb; - __u32 unused[2]; -} __attribute__((aligned(16))); -typedef struct ed ed_t; - - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - -/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */ - __u16 hwPSW[MAXPSW]; -/* #endif */ - __u8 unused; - __u8 index; - struct ed *ed; - struct td *next_dl_td; - struct usb_device *usb_dev; - int transfer_len; - __u32 data; - - __u32 unused2[2]; -} __attribute__((aligned(32))); -typedef struct td td_t; - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ -#if defined(CONFIG_MPC5200) - __u16 pad1; /* set to 0 on each frame_no change */ - __u16 frame_no; /* current frame number */ -#else - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ -#endif - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute__((aligned(256))); - - -/* - * Maximum number of root hub ports. - */ -#ifndef CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS -# error "CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS undefined!" -#endif - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the ohci_readl() and - * ohci_writel() macros defined in this file to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS]; - } roothub; -} __attribute__((aligned(32))); - -/* Some EHCI controls */ -#define EHCI_USBCMD_OFF 0x20 -#define EHCI_USBCMD_HCRESET (1 << 1) - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *dev; /* was urb */ - void *int_addr; - int send; - int interval; -}; - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -#define N_URB_TD 48 -typedef struct -{ - ed_t *ed; - __u16 length; /* number of tds associated with this request */ - __u16 td_cnt; /* number of tds already serviced */ - struct usb_device *dev; - int state; - unsigned long pipe; - void *transfer_buffer; - int transfer_buffer_length; - int interval; - int actual_length; - int finished; - td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ -} urb_priv_t; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -typedef struct ohci { - struct ohci_hcca *hcca; /* hcca */ - /*dma_addr_t hcca_dma;*/ - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - unsigned long flags; /* for HC bugs */ - - struct ohci_regs *regs; /* OHCI controller's memory */ - - int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ - ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ - ed_t *ed_bulktail; /* last endpoint of bulk list */ - ed_t *ed_controltail; /* last endpoint of control list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_device *dev[32]; - struct virt_root_hub rh; - - const char *slot_name; -} ohci_t; - -#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - ed_t ed[NUM_EDS]; - int ed_cnt; -}; - -/* hcd */ -/* endpoint */ -static int ep_link(ohci_t * ohci, ed_t * ed); -static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe, - int interval, int load); - -/*-------------------------------------------------------------------------*/ - -/* we need more TDs than EDs */ -#define NUM_TD 64 - -/* +1 so we can align the storage */ -td_t gtd[NUM_TD+1]; -/* pointers to aligned storage */ -td_t *ptd; - -/* TDs ... */ -static inline struct td * -td_alloc (struct usb_device *usb_dev) -{ - int i; - struct td *td; - - td = NULL; - for (i = 0; i < NUM_TD; i++) - { - if (ptd[i].usb_dev == NULL) - { - td = &ptd[i]; - td->usb_dev = usb_dev; - break; - } - } - - return td; -} - -static inline void -ed_free (struct ed *ed) -{ - ed->usb_dev = NULL; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c b/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c deleted file mode 100644 index dfe5423b8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/r8a66597-hcd.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * R8A66597 HCD (Host Controller Driver) for u-boot - * - * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <common.h> -#include <usb.h> -#include <asm/io.h> - -#include "r8a66597.h" - -#ifdef R8A66597_DEBUG -#define R8A66597_DPRINT printf -#else -#define R8A66597_DPRINT(...) -#endif - -static const char hcd_name[] = "r8a66597_hcd"; -static struct r8a66597 gr8a66597; - -static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport) -{ - int i; - - *hub_devnum = 0; - *hubport = 0; - - /* check a device connected to root_hub */ - if ((dev->parent && dev->parent->devnum == 1) || - (dev->devnum == 1)) - return; - - for (i = 0; i < USB_MAXCHILDREN; i++) { - if (dev->parent->children[i] == dev) { - *hub_devnum = (u8)dev->parent->devnum; - *hubport = i; - return; - } - } - - printf("get_hub_data error.\n"); -} - -static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address, - struct usb_device *dev, int port) -{ - u16 val, usbspd, upphub, hubport; - unsigned long devadd_reg = get_devadd_addr(r8a66597_address); - - get_hub_data(dev, &upphub, &hubport); - usbspd = r8a66597->speed; - val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001); - r8a66597_write(r8a66597, val, devadd_reg); -} - -static int r8a66597_clock_enable(struct r8a66597 *r8a66597) -{ - u16 tmp; - int i = 0; - -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - do { - r8a66597_write(r8a66597, SCKE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & SCKE) != SCKE); - r8a66597_write(r8a66597, 0x04, 0x02); -#else - do { - r8a66597_write(r8a66597, USBE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & USBE) != USBE); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); - r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0); - - i = 0; - r8a66597_bset(r8a66597, XCKE, SYSCFG0); - do { - udelay(1000); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 500) { - printf("register access fail.\n"); - return -1; - } - } while ((tmp & SCKE) != SCKE); -#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ - - return 0; -} - -static void r8a66597_clock_disable(struct r8a66597 *r8a66597) -{ - r8a66597_bclr(r8a66597, SCKE, SYSCFG0); - udelay(1); -#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - r8a66597_bclr(r8a66597, PLLC, SYSCFG0); - r8a66597_bclr(r8a66597, XCKE, SYSCFG0); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); -#endif -} - -static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port) -{ - u16 val; - - val = port ? DRPD : DCFM | DRPD; - r8a66597_bset(r8a66597, val, get_syscfg_reg(port)); - r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); - - r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port)); -} - -static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port) -{ - u16 val, tmp; - - r8a66597_write(r8a66597, 0, get_intenb_reg(port)); - r8a66597_write(r8a66597, 0, get_intsts_reg(port)); - - r8a66597_port_power(r8a66597, port, 0); - - do { - tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS; - udelay(640); - } while (tmp == EDGESTS); - - val = port ? DRPD : DCFM | DRPD; - r8a66597_bclr(r8a66597, val, get_syscfg_reg(port)); - r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); -} - -static int enable_controller(struct r8a66597 *r8a66597) -{ - int ret, port; - - ret = r8a66597_clock_enable(r8a66597); - if (ret < 0) - return ret; - - r8a66597_bset(r8a66597, CONFIG_R8A66597_LDRV & LDRV, PINCFG); - r8a66597_bset(r8a66597, USBE, SYSCFG0); - - r8a66597_bset(r8a66597, INTL, SOFCFG); - r8a66597_write(r8a66597, 0, INTENB0); - r8a66597_write(r8a66597, 0, INTENB1); - r8a66597_write(r8a66597, 0, INTENB2); - - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, CFIFOSEL); - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D0FIFOSEL); - r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D1FIFOSEL); - r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); - - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) - r8a66597_enable_port(r8a66597, port); - - return 0; -} - -static void disable_controller(struct r8a66597 *r8a66597) -{ - int i; - - if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE)) - return; - - r8a66597_write(r8a66597, 0, INTENB0); - r8a66597_write(r8a66597, 0, INTSTS0); - - r8a66597_write(r8a66597, 0, D0FIFOSEL); - r8a66597_write(r8a66597, 0, D1FIFOSEL); - r8a66597_write(r8a66597, 0, DCPCFG); - r8a66597_write(r8a66597, 0x40, DCPMAXP); - r8a66597_write(r8a66597, 0, DCPCTR); - - for (i = 0; i <= 10; i++) - r8a66597_write(r8a66597, 0, get_devadd_addr(i)); - for (i = 1; i <= 5; i++) { - r8a66597_write(r8a66597, 0, get_pipetre_addr(i)); - r8a66597_write(r8a66597, 0, get_pipetrn_addr(i)); - } - for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) { - r8a66597_write(r8a66597, 0, get_pipectr_addr(i)); - r8a66597_write(r8a66597, i, PIPESEL); - r8a66597_write(r8a66597, 0, PIPECFG); - r8a66597_write(r8a66597, 0, PIPEBUF); - r8a66597_write(r8a66597, 0, PIPEMAXP); - r8a66597_write(r8a66597, 0, PIPEPERI); - } - - for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) - r8a66597_disable_port(r8a66597, i); - - r8a66597_clock_disable(r8a66597); -} - -static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg, - u16 mask, u16 loop) -{ - u16 tmp; - int i = 0; - - do { - tmp = r8a66597_read(r8a66597, reg); - if (i++ > 1000000) { - printf("register%lx, loop %x is timeout\n", reg, loop); - break; - } - } while ((tmp & mask) != loop); -} - -static void pipe_buffer_setting(struct r8a66597 *r8a66597, - struct usb_device *dev, unsigned long pipe) -{ - u16 val = 0; - u16 pipenum, bufnum, maxpacket; - - if (usb_pipein(pipe)) { - pipenum = BULK_IN_PIPENUM; - bufnum = BULK_IN_BUFNUM; - maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; - } else { - pipenum = BULK_OUT_PIPENUM; - bufnum = BULK_OUT_BUFNUM; - maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)]; - } - - if (r8a66597->pipe_config & (1 << pipenum)) - return; - r8a66597->pipe_config |= (1 << pipenum); - - r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum)); - r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum)); - r8a66597_write(r8a66597, pipenum, PIPESEL); - - /* FIXME: This driver support bulk transfer only. */ - if (!usb_pipein(pipe)) - val |= R8A66597_DIR; - else - val |= R8A66597_SHTNAK; - val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe); - r8a66597_write(r8a66597, val, PIPECFG); - - r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF); - r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) | - maxpacket, PIPEMAXP); - r8a66597_write(r8a66597, 0, PIPEPERI); - r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum)); -} - -static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev, - struct devrequest *setup) -{ - int i; - unsigned short *p = (unsigned short *)setup; - unsigned long setup_addr = USBREQ; - u16 intsts1; - int timeout = 3000; - u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum; - - r8a66597_write(r8a66597, make_devsel(devsel) | - (8 << dev->maxpacketsize), DCPMAXP); - r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); - - for (i = 0; i < 4; i++) { - r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr); - setup_addr += 2; - } - r8a66597_write(r8a66597, ~0x0001, BRDYSTS); - r8a66597_write(r8a66597, SUREQ, DCPCTR); - - while (1) { - intsts1 = r8a66597_read(r8a66597, INTSTS1); - if (intsts1 & SACK) - break; - if (intsts1 & SIGN) { - printf("setup packet send error\n"); - return -1; - } - if (timeout-- < 0) { - printf("setup packet timeout\n"); - return -1; - } - udelay(500); - } - - return 0; -} - -static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev, - unsigned long pipe, void *buffer, int transfer_len) -{ - u16 tmp, bufsize; - u16 *buf; - size_t size; - - R8A66597_DPRINT("%s\n", __func__); - - r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM, - MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM); - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set (%x)\n", __func__, tmp); - return -1; - } - - /* prepare parameters */ - bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)]; - buf = (u16 *)(buffer + dev->act_len); - size = min((int)bufsize, transfer_len - dev->act_len); - - /* write fifo */ - r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS); - if (buffer) { - r8a66597_write_fifo(r8a66597, CFIFO, buf, size); - r8a66597_write(r8a66597, BVAL, CFIFOCTR); - } - - /* update parameters */ - dev->act_len += size; - - r8a66597_mdfy(r8a66597, PID_BUF, PID, - get_pipectr_addr(BULK_OUT_PIPENUM)); - - while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM))) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS); - - if (dev->act_len >= transfer_len) - r8a66597_mdfy(r8a66597, PID_NAK, PID, - get_pipectr_addr(BULK_OUT_PIPENUM)); - - return 0; -} - -static int receive_bulk_packet(struct r8a66597 *r8a66597, - struct usb_device *dev, - unsigned long pipe, - void *buffer, int transfer_len) -{ - u16 tmp; - u16 *buf; - const u16 pipenum = BULK_IN_PIPENUM; - int rcv_len; - int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; - - R8A66597_DPRINT("%s\n", __func__); - - /* prepare */ - if (dev->act_len == 0) { - r8a66597_mdfy(r8a66597, PID_NAK, PID, - get_pipectr_addr(pipenum)); - r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); - - r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum)); - r8a66597_write(r8a66597, - (transfer_len + maxpacket - 1) / maxpacket, - get_pipetrn_addr(pipenum)); - r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum)); - - r8a66597_mdfy(r8a66597, PID_BUF, PID, - get_pipectr_addr(pipenum)); - } - - r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); - - while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum))) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); - - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set. (%x)\n", __func__, tmp); - return -1; - } - - buf = (u16 *)(buffer + dev->act_len); - rcv_len = tmp & DTLN; - dev->act_len += rcv_len; - - if (buffer) { - if (rcv_len == 0) - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - else - r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len); - } - - return 0; -} - -static int receive_control_packet(struct r8a66597 *r8a66597, - struct usb_device *dev, - void *buffer, int transfer_len) -{ - u16 tmp; - int rcv_len; - - /* FIXME: limit transfer size : 64byte or less */ - - r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_bset(r8a66597, SQSET, DCPCTR); - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); - - while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001)) - if (ctrlc()) - return -1; - r8a66597_write(r8a66597, ~0x0001, BRDYSTS); - - r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - - tmp = r8a66597_read(r8a66597, CFIFOCTR); - if ((tmp & FRDY) == 0) { - printf("%s FRDY is not set. (%x)\n", __func__, tmp); - return -1; - } - - rcv_len = tmp & DTLN; - dev->act_len += rcv_len; - - r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); - - if (buffer) { - if (rcv_len == 0) - r8a66597_write(r8a66597, BCLR, DCPCTR); - else - r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len); - } - - return 0; -} - -static int send_status_packet(struct r8a66597 *r8a66597, - unsigned long pipe) -{ - r8a66597_bset(r8a66597, SQSET, DCPCTR); - r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); - - if (usb_pipein(pipe)) { - r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); - r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR); - } else { - r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); - r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); - r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, BCLR, CFIFOCTR); - } - r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); - - while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001)) - if (ctrlc()) - return -1; - - return 0; -} - -static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port) -{ - int count = R8A66597_MAX_SAMPLING; - unsigned short syssts, old_syssts; - - R8A66597_DPRINT("%s\n", __func__); - - old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); - while (count > 0) { - mdelay(R8A66597_RH_POLL_TIME); - - syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST); - if (syssts == old_syssts) { - count--; - } else { - count = R8A66597_MAX_SAMPLING; - old_syssts = syssts; - } - } -} - -static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port) -{ - mdelay(10); - r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port)); - mdelay(50); - r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port)); - mdelay(50); -} - -static int check_usb_device_connecting(struct r8a66597 *r8a66597) -{ - int timeout = 10000; /* 100usec * 10000 = 1sec */ - int i; - - for (i = 0; i < 5; i++) { - /* check a usb cable connect */ - while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) { - if (timeout-- < 0) { - printf("%s timeout.\n", __func__); - return -1; - } - udelay(100); - } - - /* check a data line */ - r8a66597_check_syssts(r8a66597, 0); - - r8a66597_bus_reset(r8a66597, 0); - r8a66597->speed = get_rh_usb_speed(r8a66597, 0); - - if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) { - r8a66597->port_change = USB_PORT_STAT_C_CONNECTION; - r8a66597->port_status = USB_PORT_STAT_CONNECTION | - USB_PORT_STAT_ENABLE; - return 0; /* success */ - } - - R8A66597_DPRINT("USB device has detached. retry = %d\n", i); - r8a66597_write(r8a66597, ~DTCH, INTSTS1); - } - - return -1; /* fail */ -} - -/* based on usb_ohci.c */ -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -#include <usbroothubdes.h> - -static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *cmd) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - int leni = transfer_len; - int len = 0; - int stat = 0; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wLength; - unsigned char data[32]; - - R8A66597_DPRINT("%s\n", __func__); - - if (usb_pipeint(pipe)) { - printf("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = cpu_to_le16 (cmd->value); - wLength = cpu_to_le16 (cmd->length); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - *(__u16 *)buffer = cpu_to_le16(1); - len = 2; - break; - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *)buffer = cpu_to_le16(0); - len = 2; - break; - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *)buffer = cpu_to_le16(0); - len = 2; - break; - case RH_GET_STATUS | RH_CLASS: - *(__u32 *)buffer = cpu_to_le32(0); - len = 4; - break; - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status | - (r8a66597->port_change << 16)); - len = 4; - break; - case RH_CLEAR_FEATURE | RH_ENDPOINT: - case RH_CLEAR_FEATURE | RH_CLASS: - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case RH_C_PORT_CONNECTION: - r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION; - break; - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - break; - case (RH_PORT_RESET): - r8a66597_bus_reset(r8a66597, 0); - break; - case (RH_PORT_POWER): - break; - case (RH_PORT_ENABLE): - break; - } - break; - case RH_SET_ADDRESS: - gr8a66597.rh_devnum = wValue; - break; - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - memcpy(buffer, root_hub_dev_des, len); - break; - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - memcpy(buffer, root_hub_config_des, len); - break; - case (0x03): /* string descriptors */ - if (wValue == 0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - memcpy(buffer, root_hub_str_index0, len); - } - if (wValue == 0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - memcpy(buffer, root_hub_str_index1, len); - } - break; - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = 0x00000001; - - data[0] = 9; /* min length; */ - data[1] = 0x29; - data[2] = temp & RH_A_NDP; - data[3] = 0; - if (temp & RH_A_PSM) - data[3] |= 0x1; - if (temp & RH_A_NOCP) - data[3] |= 0x10; - else if (temp & RH_A_OCPM) - data[3] |= 0x8; - - /* corresponds to data[4-7] */ - data[5] = (temp & RH_A_POTPGT) >> 24; - data[7] = temp & RH_B_DR; - if (data[2] < 7) { - data[8] = 0xff; - } else { - data[0] += 2; - data[8] = (temp & RH_B_DR) >> 8; - data[10] = data[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data[0], wLength)); - memcpy(buffer, data, len); - break; - } - - case RH_GET_CONFIGURATION: - *(__u8 *) buffer = 0x01; - len = 1; - break; - case RH_SET_CONFIGURATION: - break; - default: - R8A66597_DPRINT("unsupported root hub command"); - stat = USB_ST_STALLED; - } - - mdelay(1); - - len = min_t(int, len, leni); - - dev->act_len = len; - dev->status = stat; - - return stat; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - int ret = 0; - - R8A66597_DPRINT("%s\n", __func__); - R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n", - pipe, buffer, transfer_len, dev->devnum); - - set_devadd(r8a66597, dev->devnum, dev, 0); - - pipe_buffer_setting(r8a66597, dev, pipe); - - dev->act_len = 0; - while (dev->act_len < transfer_len && ret == 0) { - if (ctrlc()) - return -1; - - if (usb_pipein(pipe)) - ret = receive_bulk_packet(r8a66597, dev, pipe, buffer, - transfer_len); - else - ret = send_bulk_packet(r8a66597, dev, pipe, buffer, - transfer_len); - } - - if (ret == 0) - dev->status = 0; - - return ret; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, struct devrequest *setup) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ? - 0 : dev->devnum; - - R8A66597_DPRINT("%s\n", __func__); - if (usb_pipedevice(pipe) == r8a66597->rh_devnum) - return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - - R8A66597_DPRINT("%s: setup\n", __func__); - set_devadd(r8a66597, r8a66597_address, dev, 0); - - if (send_setup_packet(r8a66597, dev, setup) < 0) { - printf("setup packet send error\n"); - return -1; - } - - dev->act_len = 0; - if (usb_pipein(pipe)) - if (receive_control_packet(r8a66597, dev, buffer, - transfer_len) < 0) - return -1; - - if (send_status_packet(r8a66597, pipe) < 0) - return -1; - - dev->status = 0; - - return 0; -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - /* no implement */ - R8A66597_DPRINT("%s\n", __func__); - return 0; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - struct r8a66597 *r8a66597 = &gr8a66597; - - R8A66597_DPRINT("%s\n", __func__); - - memset(r8a66597, 0, sizeof(r8a66597)); - r8a66597->reg = CONFIG_R8A66597_BASE_ADDR; - - disable_controller(r8a66597); - mdelay(100); - - enable_controller(r8a66597); - r8a66597_port_power(r8a66597, 0 , 1); - - /* check usb device */ - check_usb_device_connecting(r8a66597); - - mdelay(50); - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - disable_controller(&gr8a66597); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/r8a66597.h b/qemu/roms/u-boot/drivers/usb/host/r8a66597.h deleted file mode 100644 index ca1b67155..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/r8a66597.h +++ /dev/null @@ -1,659 +0,0 @@ -/* - * R8A66597 HCD (Host Controller Driver) for u-boot - * - * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __R8A66597_H__ -#define __R8A66597_H__ - -#define SYSCFG0 0x00 -#define SYSCFG1 0x02 -#define SYSSTS0 0x04 -#define SYSSTS1 0x06 -#define DVSTCTR0 0x08 -#define DVSTCTR1 0x0A -#define TESTMODE 0x0C -#define PINCFG 0x0E -#define DMA0CFG 0x10 -#define DMA1CFG 0x12 -#define CFIFO 0x14 -#define D0FIFO 0x18 -#define D1FIFO 0x1C -#define CFIFOSEL 0x20 -#define CFIFOCTR 0x22 -#define CFIFOSIE 0x24 -#define D0FIFOSEL 0x28 -#define D0FIFOCTR 0x2A -#define D1FIFOSEL 0x2C -#define D1FIFOCTR 0x2E -#define INTENB0 0x30 -#define INTENB1 0x32 -#define INTENB2 0x34 -#define BRDYENB 0x36 -#define NRDYENB 0x38 -#define BEMPENB 0x3A -#define SOFCFG 0x3C -#define INTSTS0 0x40 -#define INTSTS1 0x42 -#define INTSTS2 0x44 -#define BRDYSTS 0x46 -#define NRDYSTS 0x48 -#define BEMPSTS 0x4A -#define FRMNUM 0x4C -#define UFRMNUM 0x4E -#define USBADDR 0x50 -#define USBREQ 0x54 -#define USBVAL 0x56 -#define USBINDX 0x58 -#define USBLENG 0x5A -#define DCPCFG 0x5C -#define DCPMAXP 0x5E -#define DCPCTR 0x60 -#define PIPESEL 0x64 -#define PIPECFG 0x68 -#define PIPEBUF 0x6A -#define PIPEMAXP 0x6C -#define PIPEPERI 0x6E -#define PIPE1CTR 0x70 -#define PIPE2CTR 0x72 -#define PIPE3CTR 0x74 -#define PIPE4CTR 0x76 -#define PIPE5CTR 0x78 -#define PIPE6CTR 0x7A -#define PIPE7CTR 0x7C -#define PIPE8CTR 0x7E -#define PIPE9CTR 0x80 -#define PIPE1TRE 0x90 -#define PIPE1TRN 0x92 -#define PIPE2TRE 0x94 -#define PIPE2TRN 0x96 -#define PIPE3TRE 0x98 -#define PIPE3TRN 0x9A -#define PIPE4TRE 0x9C -#define PIPE4TRN 0x9E -#define PIPE5TRE 0xA0 -#define PIPE5TRN 0xA2 -#define DEVADD0 0xD0 -#define DEVADD1 0xD2 -#define DEVADD2 0xD4 -#define DEVADD3 0xD6 -#define DEVADD4 0xD8 -#define DEVADD5 0xDA -#define DEVADD6 0xDC -#define DEVADD7 0xDE -#define DEVADD8 0xE0 -#define DEVADD9 0xE2 -#define DEVADDA 0xE4 - -/* System Configuration Control Register */ -#define XTAL 0xC000 /* b15-14: Crystal selection */ -#define XTAL48 0x8000 /* 48MHz */ -#define XTAL24 0x4000 /* 24MHz */ -#define XTAL12 0x0000 /* 12MHz */ -#define XCKE 0x2000 /* b13: External clock enable */ -#define PLLC 0x0800 /* b11: PLL control */ -#define SCKE 0x0400 /* b10: USB clock enable */ -#define PCSDIS 0x0200 /* b9: not CS wakeup */ -#define LPSME 0x0100 /* b8: Low power sleep mode */ -#define HSE 0x0080 /* b7: Hi-speed enable */ -#define DCFM 0x0040 /* b6: Controller function select */ -#define DRPD 0x0020 /* b5: D+/- pull down control */ -#define DPRPU 0x0010 /* b4: D+ pull up control */ -#define USBE 0x0001 /* b0: USB module operation enable */ - -/* System Configuration Status Register */ -#define OVCBIT 0x8000 /* b15-14: Over-current bit */ -#define OVCMON 0xC000 /* b15-14: Over-current monitor */ -#define SOFEA 0x0020 /* b5: SOF monitor */ -#define IDMON 0x0004 /* b3: ID-pin monitor */ -#define LNST 0x0003 /* b1-0: D+, D- line status */ -#define SE1 0x0003 /* SE1 */ -#define FS_KSTS 0x0002 /* Full-Speed K State */ -#define FS_JSTS 0x0001 /* Full-Speed J State */ -#define LS_JSTS 0x0002 /* Low-Speed J State */ -#define LS_KSTS 0x0001 /* Low-Speed K State */ -#define SE0 0x0000 /* SE0 */ - -/* Device State Control Register */ -#define EXTLP0 0x0400 /* b10: External port */ -#define VBOUT 0x0200 /* b9: VBUS output */ -#define WKUP 0x0100 /* b8: Remote wakeup */ -#define RWUPE 0x0080 /* b7: Remote wakeup sense */ -#define USBRST 0x0040 /* b6: USB reset enable */ -#define RESUME 0x0020 /* b5: Resume enable */ -#define UACT 0x0010 /* b4: USB bus enable */ -#define RHST 0x0007 /* b1-0: Reset handshake status */ -#define HSPROC 0x0004 /* HS handshake is processing */ -#define HSMODE 0x0003 /* Hi-Speed mode */ -#define FSMODE 0x0002 /* Full-Speed mode */ -#define LSMODE 0x0001 /* Low-Speed mode */ -#define UNDECID 0x0000 /* Undecided */ - -/* Test Mode Register */ -#define UTST 0x000F /* b3-0: Test select */ -#define H_TST_PACKET 0x000C /* HOST TEST Packet */ -#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ -#define H_TST_K 0x000A /* HOST TEST K */ -#define H_TST_J 0x0009 /* HOST TEST J */ -#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */ -#define P_TST_PACKET 0x0004 /* PERI TEST Packet */ -#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ -#define P_TST_K 0x0002 /* PERI TEST K */ -#define P_TST_J 0x0001 /* PERI TEST J */ -#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */ - -/* Data Pin Configuration Register */ -#define LDRV 0x8000 /* b15: Drive Current Adjust */ -#define VIF1 0x0000 /* VIF = 1.8V */ -#define VIF3 0x8000 /* VIF = 3.3V */ -#define INTA 0x0001 /* b1: USB INT-pin active */ - -/* DMAx Pin Configuration Register */ -#define DREQA 0x4000 /* b14: Dreq active select */ -#define BURST 0x2000 /* b13: Burst mode */ -#define DACKA 0x0400 /* b10: Dack active select */ -#define DFORM 0x0380 /* b9-7: DMA mode select */ -#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ -#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ -#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ -#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ -#define DENDA 0x0040 /* b6: Dend active select */ -#define PKTM 0x0020 /* b5: Packet mode */ -#define DENDE 0x0010 /* b4: Dend enable */ -#define OBUS 0x0004 /* b2: OUTbus mode */ - -/* CFIFO/DxFIFO Port Select Register */ -#define RCNT 0x8000 /* b15: Read count mode */ -#define REW 0x4000 /* b14: Buffer rewind */ -#define DCLRM 0x2000 /* b13: DMA buffer clear mode */ -#define DREQE 0x1000 /* b12: DREQ output enable */ -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define MBW 0x0800 -#else -#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ -#endif -#define MBW_8 0x0000 /* 8bit */ -#define MBW_16 0x0400 /* 16bit */ -#define BIGEND 0x0100 /* b8: Big endian mode */ -#define BYTE_LITTLE 0x0000 /* little dendian */ -#define BYTE_BIG 0x0100 /* big endifan */ -#define ISEL 0x0020 /* b5: DCP FIFO port direction select */ -#define CURPIPE 0x000F /* b2-0: PIPE select */ - -/* CFIFO/DxFIFO Port Control Register */ -#define BVAL 0x8000 /* b15: Buffer valid flag */ -#define BCLR 0x4000 /* b14: Buffer clear */ -#define FRDY 0x2000 /* b13: FIFO ready */ -#define DTLN 0x0FFF /* b11-0: FIFO received data length */ - -/* Interrupt Enable Register 0 */ -#define VBSE 0x8000 /* b15: VBUS interrupt */ -#define RSME 0x4000 /* b14: Resume interrupt */ -#define SOFE 0x2000 /* b13: Frame update interrupt */ -#define DVSE 0x1000 /* b12: Device state transition interrupt */ -#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ - -/* Interrupt Enable Register 1 */ -#define OVRCRE 0x8000 /* b15: Over-current interrupt */ -#define BCHGE 0x4000 /* b14: USB us chenge interrupt */ -#define DTCHE 0x1000 /* b12: Detach sense interrupt */ -#define ATTCHE 0x0800 /* b11: Attach sense interrupt */ -#define EOFERRE 0x0040 /* b6: EOF error interrupt */ -#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ -#define SACKE 0x0010 /* b4: SETUP ACK interrupt */ - -/* BRDY Interrupt Enable/Status Register */ -#define BRDY9 0x0200 /* b9: PIPE9 */ -#define BRDY8 0x0100 /* b8: PIPE8 */ -#define BRDY7 0x0080 /* b7: PIPE7 */ -#define BRDY6 0x0040 /* b6: PIPE6 */ -#define BRDY5 0x0020 /* b5: PIPE5 */ -#define BRDY4 0x0010 /* b4: PIPE4 */ -#define BRDY3 0x0008 /* b3: PIPE3 */ -#define BRDY2 0x0004 /* b2: PIPE2 */ -#define BRDY1 0x0002 /* b1: PIPE1 */ -#define BRDY0 0x0001 /* b1: PIPE0 */ - -/* NRDY Interrupt Enable/Status Register */ -#define NRDY9 0x0200 /* b9: PIPE9 */ -#define NRDY8 0x0100 /* b8: PIPE8 */ -#define NRDY7 0x0080 /* b7: PIPE7 */ -#define NRDY6 0x0040 /* b6: PIPE6 */ -#define NRDY5 0x0020 /* b5: PIPE5 */ -#define NRDY4 0x0010 /* b4: PIPE4 */ -#define NRDY3 0x0008 /* b3: PIPE3 */ -#define NRDY2 0x0004 /* b2: PIPE2 */ -#define NRDY1 0x0002 /* b1: PIPE1 */ -#define NRDY0 0x0001 /* b1: PIPE0 */ - -/* BEMP Interrupt Enable/Status Register */ -#define BEMP9 0x0200 /* b9: PIPE9 */ -#define BEMP8 0x0100 /* b8: PIPE8 */ -#define BEMP7 0x0080 /* b7: PIPE7 */ -#define BEMP6 0x0040 /* b6: PIPE6 */ -#define BEMP5 0x0020 /* b5: PIPE5 */ -#define BEMP4 0x0010 /* b4: PIPE4 */ -#define BEMP3 0x0008 /* b3: PIPE3 */ -#define BEMP2 0x0004 /* b2: PIPE2 */ -#define BEMP1 0x0002 /* b1: PIPE1 */ -#define BEMP0 0x0001 /* b0: PIPE0 */ - -/* SOF Pin Configuration Register */ -#define TRNENSEL 0x0100 /* b8: Select transaction enable period */ -#define BRDYM 0x0040 /* b6: BRDY clear timing */ -#define INTL 0x0020 /* b5: Interrupt sense select */ -#define EDGESTS 0x0010 /* b4: */ -#define SOFMODE 0x000C /* b3-2: SOF pin select */ -#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */ -#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ -#define SOF_DISABLE 0x0000 /* SOF OUT Disable */ - -/* Interrupt Status Register 0 */ -#define VBINT 0x8000 /* b15: VBUS interrupt */ -#define RESM 0x4000 /* b14: Resume interrupt */ -#define SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define DVST 0x1000 /* b12: Device state transition interrupt */ -#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define VBSTS 0x0080 /* b7: VBUS input port */ -#define DVSQ 0x0070 /* b6-4: Device state */ -#define DS_SPD_CNFG 0x0070 /* Suspend Configured */ -#define DS_SPD_ADDR 0x0060 /* Suspend Address */ -#define DS_SPD_DFLT 0x0050 /* Suspend Default */ -#define DS_SPD_POWR 0x0040 /* Suspend Powered */ -#define DS_SUSP 0x0040 /* Suspend */ -#define DS_CNFG 0x0030 /* Configured */ -#define DS_ADDS 0x0020 /* Address */ -#define DS_DFLT 0x0010 /* Default */ -#define DS_POWR 0x0000 /* Powered */ -#define DVSQS 0x0030 /* b5-4: Device state */ -#define VALID 0x0008 /* b3: Setup packet detected flag */ -#define CTSQ 0x0007 /* b2-0: Control transfer stage */ -#define CS_SQER 0x0006 /* Sequence error */ -#define CS_WRND 0x0005 /* Control write nodata status stage */ -#define CS_WRSS 0x0004 /* Control write status stage */ -#define CS_WRDS 0x0003 /* Control write data stage */ -#define CS_RDSS 0x0002 /* Control read status stage */ -#define CS_RDDS 0x0001 /* Control read data stage */ -#define CS_IDST 0x0000 /* Idle or setup stage */ - -/* Interrupt Status Register 1 */ -#define OVRCR 0x8000 /* b15: Over-current interrupt */ -#define BCHG 0x4000 /* b14: USB bus chenge interrupt */ -#define DTCH 0x1000 /* b12: Detach sense interrupt */ -#define ATTCH 0x0800 /* b11: Attach sense interrupt */ -#define EOFERR 0x0040 /* b6: EOF-error interrupt */ -#define SIGN 0x0020 /* b5: Setup ignore interrupt */ -#define SACK 0x0010 /* b4: Setup acknowledge interrupt */ - -/* Frame Number Register */ -#define OVRN 0x8000 /* b15: Overrun error */ -#define CRCE 0x4000 /* b14: Received data error */ -#define FRNM 0x07FF /* b10-0: Frame number */ - -/* Micro Frame Number Register */ -#define UFRNM 0x0007 /* b2-0: Micro frame number */ - -/* Default Control Pipe Maxpacket Size Register */ -/* Pipe Maxpacket Size Register */ -#define DEVSEL 0xF000 /* b15-14: Device address select */ -#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ - -/* Default Control Pipe Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define SUREQ 0x4000 /* b14: Send USB request */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define SUREQCLR 0x0800 /* b11: stop setup request */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PINGE 0x0010 /* b4: ping enable */ -#define CCPL 0x0004 /* b2: Enable control transfer complete */ -#define PID 0x0003 /* b1-0: Response PID */ -#define PID_STALL11 0x0003 /* STALL */ -#define PID_STALL 0x0002 /* STALL */ -#define PID_BUF 0x0001 /* BUF */ -#define PID_NAK 0x0000 /* NAK */ - -/* Pipe Window Select Register */ -#define PIPENM 0x0007 /* b2-0: Pipe select */ - -/* Pipe Configuration Register */ -#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */ -#define R8A66597_ISO 0xC000 /* Isochronous */ -#define R8A66597_INT 0x8000 /* Interrupt */ -#define R8A66597_BULK 0x4000 /* Bulk */ -#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ -#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */ -#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */ -#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */ -#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */ -#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */ - -/* Pipe Buffer Configuration Register */ -#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ -#define BUFNMB 0x007F /* b6-0: Pipe buffer number */ -#define PIPE0BUF 256 -#define PIPExBUF 64 - -/* Pipe Maxpacket Size Register */ -#define MXPS 0x07FF /* b10-0: Maxpacket size */ - -/* Pipe Cycle Configuration Register */ -#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define IITV 0x0007 /* b2-0: Isochronous interval */ - -/* Pipex Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define ATREPM 0x0400 /* b10: Auto repeat mode */ -#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PID 0x0003 /* b1-0: Response PID */ - -/* PIPExTRE */ -#define TRENB 0x0200 /* b9: Transaction counter enable */ -#define TRCLR 0x0100 /* b8: Transaction counter clear */ - -/* PIPExTRN */ -#define TRNCNT 0xFFFF /* b15-0: Transaction counter */ - -/* DEVADDx */ -#define UPPHUB 0x7800 -#define HUBPORT 0x0700 -#define USBSPD 0x00C0 -#define RTPORT 0x0001 - -#define R8A66597_MAX_NUM_PIPE 10 -#define R8A66597_BUF_BSIZE 8 -#define R8A66597_MAX_DEVICE 10 -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define R8A66597_MAX_ROOT_HUB 1 -#else -#define R8A66597_MAX_ROOT_HUB 2 -#endif -#define R8A66597_MAX_SAMPLING 5 -#define R8A66597_RH_POLL_TIME 10 - -#define BULK_IN_PIPENUM 3 -#define BULK_IN_BUFNUM 8 - -#define BULK_OUT_PIPENUM 4 -#define BULK_OUT_BUFNUM 40 - -#define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5)) -#define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9)) -#define make_devsel(addr) (addr << 12) - -struct r8a66597 { - unsigned long reg; - unsigned short pipe_config; /* bit field */ - unsigned short port_status; - unsigned short port_change; - u16 speed; /* HSMODE or FSMODE or LSMODE */ - unsigned char rh_devnum; -}; - -static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) -{ - return inw(r8a66597->reg + offset); -} - -static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, - unsigned long offset, void *buf, - int len) -{ - int i; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - unsigned long fifoaddr = r8a66597->reg + offset; - unsigned long count; - unsigned long *p = buf; - - count = len / 4; - for (i = 0; i < count; i++) - p[i] = inl(r8a66597->reg + offset); - - if (len & 0x00000003) { - unsigned long tmp = inl(fifoaddr); - memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03); - } -#else - unsigned short *p = buf; - - len = (len + 1) / 2; - for (i = 0; i < len; i++) - p[i] = inw(r8a66597->reg + offset); -#endif -} - -static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, - unsigned long offset) -{ - outw(val, r8a66597->reg + offset); -} - -static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, - unsigned long offset, void *buf, - int len) -{ - int i; - unsigned long fifoaddr = r8a66597->reg + offset; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) - unsigned long count; - unsigned char *pb; - unsigned long *p = buf; - - count = len / 4; - for (i = 0; i < count; i++) - outl(p[i], fifoaddr); - - if (len & 0x00000003) { - pb = (unsigned char *)buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) { - if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) - outb(pb[i], fifoaddr + i); - else - outb(pb[i], fifoaddr + 3 - i); - } - } -#else - int odd = len & 0x0001; - unsigned short *p = buf; - - len = len / 2; - for (i = 0; i < len; i++) - outw(p[i], fifoaddr); - - if (odd) { - unsigned char *pb = (unsigned char *)(buf + len); - outb(*pb, fifoaddr); - } -#endif -} - -static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, - u16 val, u16 pat, unsigned long offset) -{ - u16 tmp; - tmp = r8a66597_read(r8a66597, offset); - tmp = tmp & (~pat); - tmp = tmp | val; - r8a66597_write(r8a66597, tmp, offset); -} - -#define r8a66597_bclr(r8a66597, val, offset) \ - r8a66597_mdfy(r8a66597, 0, val, offset) -#define r8a66597_bset(r8a66597, val, offset) \ - r8a66597_mdfy(r8a66597, val, 0, offset) - -static inline unsigned long get_syscfg_reg(int port) -{ - return port == 0 ? SYSCFG0 : SYSCFG1; -} - -static inline unsigned long get_syssts_reg(int port) -{ - return port == 0 ? SYSSTS0 : SYSSTS1; -} - -static inline unsigned long get_dvstctr_reg(int port) -{ - return port == 0 ? DVSTCTR0 : DVSTCTR1; -} - -static inline unsigned long get_dmacfg_reg(int port) -{ - return port == 0 ? DMA0CFG : DMA1CFG; -} - -static inline unsigned long get_intenb_reg(int port) -{ - return port == 0 ? INTENB1 : INTENB2; -} - -static inline unsigned long get_intsts_reg(int port) -{ - return port == 0 ? INTSTS1 : INTSTS2; -} - -static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port) -{ - unsigned long dvstctr_reg = get_dvstctr_reg(port); - - return r8a66597_read(r8a66597, dvstctr_reg) & RHST; -} - -static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port, - int power) -{ - unsigned long dvstctr_reg = get_dvstctr_reg(port); - - if (power) - r8a66597_bset(r8a66597, VBOUT, dvstctr_reg); - else - r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg); -} - -#define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) -#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) -#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) -#define get_devadd_addr(address) (DEVADD0 + address * 2) - - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -#endif /* __R8A66597_H__ */ diff --git a/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c b/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c deleted file mode 100644 index b29c67e18..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/sl811-hcd.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * This code is based on linux driver for sl811hs chip, source at - * drivers/usb/host/sl811.c: - * - * SL811 Host Controller Interface driver for USB. - * - * Copyright (c) 2003/06, Courage Co., Ltd. - * - * Based on: - * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, - * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, - * Adam Richter, Gregory P. Smith; - * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> - * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <mpc8xx.h> -#include <usb.h> -#include "sl811.h" - -#include "../../../board/kup/common/kup.h" - -#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -#else -# define EIEIO /* nothing */ -#endif - -#define SL811_ADR (0x50000000) -#define SL811_DAT (0x50000001) - -#ifdef SL811_DEBUG -static int debug = 9; -#endif - -static int root_hub_devnum = 0; -static struct usb_port_status rh_status = { 0 };/* root hub port status */ - -static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, - void *data, int buf_len, struct devrequest *cmd); - -static void sl811_write (__u8 index, __u8 data) -{ - *(volatile unsigned char *) (SL811_ADR) = index; - EIEIO; - *(volatile unsigned char *) (SL811_DAT) = data; - EIEIO; -} - -static __u8 sl811_read (__u8 index) -{ - __u8 data; - - *(volatile unsigned char *) (SL811_ADR) = index; - EIEIO; - data = *(volatile unsigned char *) (SL811_DAT); - EIEIO; - return (data); -} - -/* - * Read consecutive bytes of data from the SL811H/SL11H buffer - */ -static void inline sl811_read_buf(__u8 offset, __u8 *buf, __u8 size) -{ - *(volatile unsigned char *) (SL811_ADR) = offset; - EIEIO; - while (size--) { - *buf++ = *(volatile unsigned char *) (SL811_DAT); - EIEIO; - } -} - -/* - * Write consecutive bytes of data to the SL811H/SL11H buffer - */ -static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size) -{ - *(volatile unsigned char *) (SL811_ADR) = offset; - EIEIO; - while (size--) { - *(volatile unsigned char *) (SL811_DAT) = *buf++; - EIEIO; - } -} - -int usb_init_kup4x (void) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - volatile memctl8xx_t *memctl = &immap->im_memctl; - int i; - unsigned char tmp; - - memctl = &immap->im_memctl; - memctl->memc_or7 = 0xFFFF8726; - memctl->memc_br7 = 0x50000401; /* start at 0x50000000 */ - /* BP 14 low = USB ON */ - immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC); - /* PB 14 nomal port */ - immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC); - /* output */ - immap->im_cpm.cp_pbdir |= (BP_USB_VCC); - - puts ("USB: "); - - for (i = 0x10; i < 0xff; i++) { - sl811_write(i, i); - tmp = (sl811_read(i)); - if (tmp != i) { - printf ("SL811 compare error index=0x%02x read=0x%02x\n", i, tmp); - return (-1); - } - } - printf ("SL811 ready\n"); - return (0); -} - -/* - * This function resets SL811HS controller and detects the speed of - * the connecting device - * - * Return: 0 = no device attached; 1 = USB device attached - */ -static int sl811_hc_reset(void) -{ - int status ; - - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - - mdelay(20); - - /* Disable hardware SOF generation, clear all irq status. */ - sl811_write(SL811_CTRL1, 0); - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - status = sl811_read(SL811_INTRSTS); - - if (status & SL811_INTR_NOTPRESENT) { - /* Device is not present */ - PDEBUG(0, "Device not present\n"); - rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE); - rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; - sl811_write(SL811_INTR, SL811_INTR_INSRMV); - return 0; - } - - /* Send SOF to address 0, endpoint 0. */ - sl811_write(SL811_LEN_B, 0); - sl811_write(SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0)); - sl811_write(SL811_DEV_B, 0x00); - sl811_write(SL811_SOFLOW, SL811_12M_LOW); - - if (status & SL811_INTR_SPEED_FULL) { - /* full speed device connect directly to root hub */ - PDEBUG (0, "Full speed Device attached\n"); - - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - mdelay(20); - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_SOF); - - /* start the SOF or EOP */ - sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM); - rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION; - rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED; - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - } else { - /* slow speed device connect directly to root-hub */ - PDEBUG(0, "Low speed Device attached\n"); - - sl811_write(SL811_CTRL1, SL811_CTRL1_RESET); - mdelay(20); - sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI); - sl811_write(SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF); - - /* start the SOF or EOP */ - sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM); - rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED; - mdelay(2); - sl811_write(SL811_INTRSTS, 0xff); - } - - rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION; - sl811_write(SL811_INTR, /*SL811_INTR_INSRMV*/SL811_INTR_DONE_A); - - return 1; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - root_hub_devnum = 0; - sl811_hc_reset(); - return 0; -} - -int usb_lowlevel_stop(int index) -{ - sl811_hc_reset(); - return 0; -} - -static int calc_needed_buswidth(int bytes, int need_preamble) -{ - return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048; -} - -static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len) -{ - __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE; - __u16 status = 0; - int err = 0, time_start = get_timer(0); - int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && - (dev->speed == USB_SPEED_LOW); - - if (len > 239) - return -1; - - if (usb_pipeout(pipe)) - ctrl |= SL811_USB_CTRL_DIR_OUT; - if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) - ctrl |= SL811_USB_CTRL_TOGGLE_1; - if (need_preamble) - ctrl |= SL811_USB_CTRL_PREAMBLE; - - sl811_write(SL811_INTRSTS, 0xff); - - while (err < 3) { - sl811_write(SL811_ADDR_A, 0x10); - sl811_write(SL811_LEN_A, len); - if (usb_pipeout(pipe) && len) - sl811_write_buf(0x10, buffer, len); - - if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) && - sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble)) - ctrl |= SL811_USB_CTRL_SOF; - else - ctrl &= ~SL811_USB_CTRL_SOF; - - sl811_write(SL811_CTRL_A, ctrl); - while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) { - if (5*CONFIG_SYS_HZ < get_timer(time_start)) { - printf("USB transmit timed out\n"); - return -USB_ST_CRC_ERR; - } - } - - sl811_write(SL811_INTRSTS, 0xff); - status = sl811_read(SL811_STS_A); - - if (status & SL811_USB_STS_ACK) { - int remainder = sl811_read(SL811_CNT_A); - if (remainder) { - PDEBUG(0, "usb transfer remainder = %d\n", remainder); - len -= remainder; - } - if (usb_pipein(pipe) && len) - sl811_read_buf(0x10, buffer, len); - return len; - } - - if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK) - continue; - - PDEBUG(0, "usb transfer error %#x\n", (int)status); - err++; - } - - err = 0; - - if (status & SL811_USB_STS_ERROR) - err |= USB_ST_BUF_ERR; - if (status & SL811_USB_STS_TIMEOUT) - err |= USB_ST_CRC_ERR; - if (status & SL811_USB_STS_STALL) - err |= USB_ST_STALLED; - - return -err; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len) -{ - int dir_out = usb_pipeout(pipe); - int ep = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int done = 0; - - PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n", - usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); - - dev->status = 0; - - sl811_write(SL811_DEV_A, usb_pipedevice(pipe)); - sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep)); - while (done < len) { - int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, - max > len - done ? len - done : max); - if (res < 0) { - dev->status = -res; - return res; - } - - if (!dir_out && res < max) /* short packet */ - break; - - done += res; - usb_dotoggle(dev, ep, dir_out); - } - - dev->act_len = done; - - return 0; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len,struct devrequest *setup) -{ - int done = 0; - int devnum = usb_pipedevice(pipe); - int ep = usb_pipeendpoint(pipe); - - dev->status = 0; - - if (devnum == root_hub_devnum) - return sl811_rh_submit_urb(dev, pipe, buffer, len, setup); - - PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n", - devnum, ep, buffer, len, (int)setup->requesttype, - (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64); - - sl811_write(SL811_DEV_A, devnum); - sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep)); - /* setup phase */ - usb_settoggle(dev, ep, 1, 0); - if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep), - (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) { - int dir_in = usb_pipein(pipe); - int max = usb_maxpacket(dev, pipe); - - /* data phase */ - sl811_write(SL811_PIDEP_A, - PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep)); - usb_settoggle(dev, ep, usb_pipeout(pipe), 1); - while (done < len) { - int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done, - max > len - done ? len - done : max); - if (res < 0) { - PDEBUG(0, "status data failed!\n"); - dev->status = -res; - return 0; - } - done += res; - usb_dotoggle(dev, ep, usb_pipeout(pipe)); - if (dir_in && res < max) /* short packet */ - break; - } - - /* status phase */ - sl811_write(SL811_PIDEP_A, - PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep)); - usb_settoggle(dev, ep, !usb_pipeout(pipe), 1); - if (sl811_send_packet(dev, - !dir_in ? usb_rcvctrlpipe(dev, ep) : - usb_sndctrlpipe(dev, ep), - 0, 0) < 0) { - PDEBUG(0, "status phase failed!\n"); - dev->status = -1; - } - } else { - PDEBUG(0, "setup phase failed!\n"); - dev->status = -1; - } - - dev->act_len = done; - - return done; -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) -{ - PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe, - buffer, len, interval); - return -1; -} - -/* - * SL811 Virtual Root Hub - */ - -/* Device descriptor */ -static __u8 sl811_rh_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, /* __u16 bcdUSB; v1.1 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 sl811_rh_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -/* root hub class descriptor*/ -static __u8 sl811_rh_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x01, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -/* - * helper routine for returning string descriptors in UTF-16LE - * input can actually be ISO-8859-1; ASCII is its 7-bit subset - */ -static int ascii2utf (char *s, u8 *utf, int utfmax) -{ - int retval; - - for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { - *utf++ = *s++; - *utf++ = 0; - } - return retval; -} - -/* - * root_hub_string is used by each host controller's root hub code, - * so that they're identified consistently throughout the system. - */ -static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) -{ - char buf [30]; - - /* assert (len > (2 * (sizeof (buf) + 1))); - assert (strlen (type) <= 8);*/ - - /* language ids */ - if (id == 0) { - *data++ = 4; *data++ = 3; /* 4 bytes data */ - *data++ = 0; *data++ = 0; /* some language id */ - return 4; - - /* serial number */ - } else if (id == 1) { - sprintf (buf, "%#x", serial); - - /* product description */ - } else if (id == 2) { - sprintf (buf, "USB %s Root Hub", type); - - /* id 3 == vendor description */ - - /* unsupported IDs --> "stall" */ - } else - return 0; - - ascii2utf (buf, data + 2, len - 2); - data [0] = 2 + strlen(buf) * 2; - data [1] = 3; - return data [0]; -} - -/* helper macro */ -#define OK(x) len = (x); break - -/* - * This function handles all USB request to the the virtual root hub - */ -static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, - void *data, int buf_len, struct devrequest *cmd) -{ - __u8 data_buf[16]; - __u8 *bufp = data_buf; - int len = 0; - int status = 0; - __u16 bmRType_bReq; - __u16 wValue = le16_to_cpu (cmd->value); - __u16 wLength = le16_to_cpu (cmd->length); -#ifdef SL811_DEBUG - __u16 wIndex = le16_to_cpu (cmd->index); -#endif - - if (usb_pipeint(pipe)) { - PDEBUG(0, "interrupt transfer unimplemented!\n"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - - PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n", - bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength); - - /* Request Destination: - without flags: Device, - USB_RECIP_INTERFACE: interface, - USB_RECIP_ENDPOINT: endpoint, - USB_TYPE_CLASS means HUB here, - USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here - */ - switch (bmRType_bReq) { - case RH_GET_STATUS: - *(__u16 *)bufp = cpu_to_le16(1); - OK(2); - - case RH_GET_STATUS | USB_RECIP_INTERFACE: - *(__u16 *)bufp = cpu_to_le16(0); - OK(2); - - case RH_GET_STATUS | USB_RECIP_ENDPOINT: - *(__u16 *)bufp = cpu_to_le16(0); - OK(2); - - case RH_GET_STATUS | USB_TYPE_CLASS: - *(__u32 *)bufp = cpu_to_le32(0); - OK(4); - - case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS: - *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus); - OK(4); - - case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT: - switch (wValue) { - case 1: - OK(0); - } - break; - - case RH_CLEAR_FEATURE | USB_TYPE_CLASS: - switch (wValue) { - case C_HUB_LOCAL_POWER: - OK(0); - - case C_HUB_OVER_CURRENT: - OK(0); - } - break; - - case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE; - OK(0); - - case USB_PORT_FEAT_SUSPEND: - rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND; - OK(0); - - case USB_PORT_FEAT_POWER: - rh_status.wPortStatus &= ~USB_PORT_STAT_POWER; - OK(0); - - case USB_PORT_FEAT_C_CONNECTION: - rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION; - OK(0); - - case USB_PORT_FEAT_C_ENABLE: - rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE; - OK(0); - - case USB_PORT_FEAT_C_SUSPEND: - rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND; - OK(0); - - case USB_PORT_FEAT_C_OVER_CURRENT: - rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT; - OK(0); - - case USB_PORT_FEAT_C_RESET: - rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET; - OK(0); - } - break; - - case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND; - OK(0); - - case USB_PORT_FEAT_RESET: - rh_status.wPortStatus |= USB_PORT_STAT_RESET; - rh_status.wPortChange = 0; - rh_status.wPortChange |= USB_PORT_STAT_C_RESET; - rh_status.wPortStatus &= ~USB_PORT_STAT_RESET; - rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; - OK(0); - - case USB_PORT_FEAT_POWER: - rh_status.wPortStatus |= USB_PORT_STAT_POWER; - OK(0); - - case USB_PORT_FEAT_ENABLE: - rh_status.wPortStatus |= USB_PORT_STAT_ENABLE; - OK(0); - } - break; - - case RH_SET_ADDRESS: - root_hub_devnum = wValue; - OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case USB_DT_DEVICE: - len = sizeof(sl811_rh_dev_des); - bufp = sl811_rh_dev_des; - OK(len); - - case USB_DT_CONFIG: - len = sizeof(sl811_rh_config_des); - bufp = sl811_rh_config_des; - OK(len); - - case USB_DT_STRING: - len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength); - if (len > 0) { - bufp = data; - OK(len); - } - - default: - status = -32; - } - break; - - case RH_GET_DESCRIPTOR | USB_TYPE_CLASS: - len = sizeof(sl811_rh_hub_des); - bufp = sl811_rh_hub_des; - OK(len); - - case RH_GET_CONFIGURATION: - bufp[0] = 0x01; - OK(1); - - case RH_SET_CONFIGURATION: - OK(0); - - default: - PDEBUG(1, "unsupported root hub command\n"); - status = -32; - } - - len = min(len, buf_len); - if (data != bufp) - memcpy(data, bufp, len); - - PDEBUG(5, "len = %d, status = %d\n", len, status); - - usb_dev->status = status; - usb_dev->act_len = len; - - return status == 0 ? len : status; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/sl811.h b/qemu/roms/u-boot/drivers/usb/host/sl811.h deleted file mode 100644 index c1f9f013b..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/sl811.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __UBOOT_SL811_H -#define __UBOOT_SL811_H - -#undef SL811_DEBUG - -#ifdef SL811_DEBUG - #define PDEBUG(level, fmt, args...) \ - if (debug >= (level)) printf("[%s:%d] " fmt, \ - __PRETTY_FUNCTION__, __LINE__ , ## args) -#else - #define PDEBUG(level, fmt, args...) do {} while(0) -#endif - -/* Sl811 host control register */ -#define SL811_CTRL_A 0x00 -#define SL811_ADDR_A 0x01 -#define SL811_LEN_A 0x02 -#define SL811_STS_A 0x03 /* read */ -#define SL811_PIDEP_A 0x03 /* write */ -#define SL811_CNT_A 0x04 /* read */ -#define SL811_DEV_A 0x04 /* write */ -#define SL811_CTRL1 0x05 -#define SL811_INTR 0x06 -#define SL811_CTRL_B 0x08 -#define SL811_ADDR_B 0x09 -#define SL811_LEN_B 0x0A -#define SL811_STS_B 0x0B /* read */ -#define SL811_PIDEP_B 0x0B /* write */ -#define SL811_CNT_B 0x0C /* read */ -#define SL811_DEV_B 0x0C /* write */ -#define SL811_INTRSTS 0x0D /* write clears bitwise */ -#define SL811_HWREV 0x0E /* read */ -#define SL811_SOFLOW 0x0E /* write */ -#define SL811_SOFCNTDIV 0x0F /* read */ -#define SL811_CTRL2 0x0F /* write */ - -/* USB control register bits (addr 0x00 and addr 0x08) */ -#define SL811_USB_CTRL_ARM 0x01 -#define SL811_USB_CTRL_ENABLE 0x02 -#define SL811_USB_CTRL_DIR_OUT 0x04 -#define SL811_USB_CTRL_ISO 0x10 -#define SL811_USB_CTRL_SOF 0x20 -#define SL811_USB_CTRL_TOGGLE_1 0x40 -#define SL811_USB_CTRL_PREAMBLE 0x80 - -/* USB status register bits (addr 0x03 and addr 0x0B) */ -#define SL811_USB_STS_ACK 0x01 -#define SL811_USB_STS_ERROR 0x02 -#define SL811_USB_STS_TIMEOUT 0x04 -#define SL811_USB_STS_TOGGLE_1 0x08 -#define SL811_USB_STS_SETUP 0x10 -#define SL811_USB_STS_OVERFLOW 0x20 -#define SL811_USB_STS_NAK 0x40 -#define SL811_USB_STS_STALL 0x80 - -/* Control register 1 bits (addr 0x05) */ -#define SL811_CTRL1_SOF 0x01 -#define SL811_CTRL1_RESET 0x08 -#define SL811_CTRL1_JKSTATE 0x10 -#define SL811_CTRL1_SPEED_LOW 0x20 -#define SL811_CTRL1_SUSPEND 0x40 - -/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */ -#define SL811_INTR_DONE_A 0x01 -#define SL811_INTR_DONE_B 0x02 -#define SL811_INTR_SOF 0x10 -#define SL811_INTR_INSRMV 0x20 -#define SL811_INTR_DETECT 0x40 -#define SL811_INTR_NOTPRESENT 0x40 -#define SL811_INTR_SPEED_FULL 0x80 /* only in status reg */ - -/* HW rev and SOF lo register bits (addr 0x0E) */ -#define SL811_HWR_HWREV 0xF0 - -/* SOF counter and control reg 2 (addr 0x0F) */ -#define SL811_CTL2_SOFHI 0x3F -#define SL811_CTL2_DSWAP 0x40 -#define SL811_CTL2_HOST 0x80 - -/* Set up for 1-ms SOF time. */ -#define SL811_12M_LOW 0xE0 -#define SL811_12M_HI 0x2E - -#define SL811_DATA_START 0x10 -#define SL811_DATA_LIMIT 240 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 - - -#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep)) - -#endif /* __UBOOT_SL811_H */ diff --git a/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c b/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c deleted file mode 100644 index 1e878280f..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/utmi-armada100.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * (C) Copyright 2012 - * eInfochips Ltd. <www.einfochips.com> - * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com> - * - * (C) Copyright 2009 - * Marvell Semiconductor <www.marvell.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <asm/arch/cpu.h> -#include <asm/arch/armada100.h> -#include <asm/arch/utmi-armada100.h> - -static int utmi_phy_init(void) -{ - struct armd1usb_phy_reg *phy_regs = - (struct armd1usb_phy_reg *)UTMI_PHY_BASE; - int timeout; - - setbits_le32(&phy_regs->utmi_ctrl, INPKT_DELAY_SOF | PLL_PWR_UP); - udelay(1000); - setbits_le32(&phy_regs->utmi_ctrl, PHY_PWR_UP); - - clrbits_le32(&phy_regs->utmi_pll, PLL_FBDIV_MASK | PLL_REFDIV_MASK); - setbits_le32(&phy_regs->utmi_pll, N_DIVIDER << PLL_FBDIV | M_DIVIDER); - - setbits_le32(&phy_regs->utmi_tx, PHSEL_VAL << CK60_PHSEL); - - /* Calibrate pll */ - timeout = 10000; - while (--timeout && ((readl(&phy_regs->utmi_pll) & PLL_READY) == 0)) - ; - if (!timeout) - return -1; - - udelay(200); - setbits_le32(&phy_regs->utmi_pll, VCOCAL_START); - udelay(400); - clrbits_le32(&phy_regs->utmi_pll, VCOCAL_START); - - udelay(200); - setbits_le32(&phy_regs->utmi_tx, RCAL_START); - udelay(400); - clrbits_le32(&phy_regs->utmi_tx, RCAL_START); - - timeout = 10000; - while (--timeout && ((readl(&phy_regs->utmi_pll) & PLL_READY) == 0)) - ; - if (!timeout) - return -1; - - return 0; -} - -/* - * Initialize USB host controller's UTMI Physical interface - */ -int utmi_init(void) -{ - struct armd1mpmu_registers *mpmu_regs = - (struct armd1mpmu_registers *)ARMD1_MPMU_BASE; - - struct armd1apmu_registers *apmu_regs = - (struct armd1apmu_registers *)ARMD1_APMU_BASE; - - /* Turn on 26Mhz ref clock for UTMI PLL */ - setbits_le32(&mpmu_regs->acgr, APB2_26M_EN | AP_26M); - - /* USB Clock reset */ - writel(USB_SPH_AXICLK_EN, &apmu_regs->usbcrc); - writel(USB_SPH_AXICLK_EN | USB_SPH_AXI_RST, &apmu_regs->usbcrc); - - /* Initialize UTMI transceiver */ - return utmi_phy_init(); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c b/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c deleted file mode 100644 index b4946a3f1..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-exynos5.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * SAMSUNG EXYNOS5 USB HOST XHCI Controller - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This file is a conglomeration for DWC3-init sequence and further - * exynos5 specific PHY-init sequence. - */ - -#include <common.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <malloc.h> -#include <usb.h> -#include <watchdog.h> -#include <asm/arch/cpu.h> -#include <asm/arch/power.h> -#include <asm/arch/xhci-exynos.h> -#include <asm/gpio.h> -#include <asm-generic/errno.h> -#include <linux/compat.h> -#include <linux/usb/dwc3.h> - -#include "xhci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -/** - * Contains pointers to register base addresses - * for the usb controller. - */ -struct exynos_xhci { - struct exynos_usb3_phy *usb3_phy; - struct xhci_hccr *hcd; - struct dwc3 *dwc3_reg; - struct fdt_gpio_state vbus_gpio; -}; - -static struct exynos_xhci exynos; - -#ifdef CONFIG_OF_CONTROL -static int exynos_usb3_parse_dt(const void *blob, struct exynos_xhci *exynos) -{ - fdt_addr_t addr; - unsigned int node; - int depth; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_XHCI); - if (node <= 0) { - debug("XHCI: Can't get device node for xhci\n"); - return -ENODEV; - } - - /* - * Get the base address for XHCI controller from the device node - */ - addr = fdtdec_get_addr(blob, node, "reg"); - if (addr == FDT_ADDR_T_NONE) { - debug("Can't get the XHCI register base address\n"); - return -ENXIO; - } - exynos->hcd = (struct xhci_hccr *)addr; - - /* Vbus gpio */ - fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio); - - depth = 0; - node = fdtdec_next_compatible_subnode(blob, node, - COMPAT_SAMSUNG_EXYNOS5_USB3_PHY, &depth); - if (node <= 0) { - debug("XHCI: Can't get device node for usb3-phy controller\n"); - return -ENODEV; - } - - /* - * Get the base address for usbphy from the device node - */ - exynos->usb3_phy = (struct exynos_usb3_phy *)fdtdec_get_addr(blob, node, - "reg"); - if (exynos->usb3_phy == NULL) { - debug("Can't get the usbphy register address\n"); - return -ENXIO; - } - - return 0; -} -#endif - -static void exynos5_usb3_phy_init(struct exynos_usb3_phy *phy) -{ - u32 reg; - - /* enabling usb_drd phy */ - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN); - - /* Reset USB 3.0 PHY */ - writel(0x0, &phy->phy_reg0); - - clrbits_le32(&phy->phy_param0, - /* Select PHY CLK source */ - PHYPARAM0_REF_USE_PAD | - /* Set Loss-of-Signal Detector sensitivity */ - PHYPARAM0_REF_LOSLEVEL_MASK); - setbits_le32(&phy->phy_param0, PHYPARAM0_REF_LOSLEVEL); - - writel(0x0, &phy->phy_resume); - - /* - * Setting the Frame length Adj value[6:1] to default 0x20 - * See xHCI 1.0 spec, 5.2.4 - */ - setbits_le32(&phy->link_system, - LINKSYSTEM_XHCI_VERSION_CONTROL | - LINKSYSTEM_FLADJ(0x20)); - - /* Set Tx De-Emphasis level */ - clrbits_le32(&phy->phy_param1, PHYPARAM1_PCS_TXDEEMPH_MASK); - setbits_le32(&phy->phy_param1, PHYPARAM1_PCS_TXDEEMPH); - - setbits_le32(&phy->phy_batchg, PHYBATCHG_UTMI_CLKSEL); - - /* PHYTEST POWERDOWN Control */ - clrbits_le32(&phy->phy_test, - PHYTEST_POWERDOWN_SSP | - PHYTEST_POWERDOWN_HSP); - - /* UTMI Power Control */ - writel(PHYUTMI_OTGDISABLE, &phy->phy_utmi); - - /* Use core clock from main PLL */ - reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK | - /* Default 24Mhz crystal clock */ - PHYCLKRST_FSEL(FSEL_CLKSEL_24M) | - PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | - PHYCLKRST_SSC_REFCLKSEL(0x88) | - /* Force PortReset of PHY */ - PHYCLKRST_PORTRESET | - /* Digital power supply in normal operating mode */ - PHYCLKRST_RETENABLEN | - /* Enable ref clock for SS function */ - PHYCLKRST_REF_SSP_EN | - /* Enable spread spectrum */ - PHYCLKRST_SSC_EN | - /* Power down HS Bias and PLL blocks in suspend mode */ - PHYCLKRST_COMMONONN; - - writel(reg, &phy->phy_clk_rst); - - /* giving time to Phy clock to settle before resetting */ - udelay(10); - - reg &= ~PHYCLKRST_PORTRESET; - writel(reg, &phy->phy_clk_rst); -} - -static void exynos5_usb3_phy_exit(struct exynos_usb3_phy *phy) -{ - setbits_le32(&phy->phy_utmi, - PHYUTMI_OTGDISABLE | - PHYUTMI_FORCESUSPEND | - PHYUTMI_FORCESLEEP); - - clrbits_le32(&phy->phy_clk_rst, - PHYCLKRST_REF_SSP_EN | - PHYCLKRST_SSC_EN | - PHYCLKRST_COMMONONN); - - /* PHYTEST POWERDOWN Control to remove leakage current */ - setbits_le32(&phy->phy_test, - PHYTEST_POWERDOWN_SSP | - PHYTEST_POWERDOWN_HSP); - - /* disabling usb_drd phy */ - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE); -} - -void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) -{ - clrsetbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), - DWC3_GCTL_PRTCAPDIR(mode)); -} - -static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) -{ - /* Before Resetting PHY, put Core in Reset */ - setbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_CORESOFTRESET); - - /* Assert USB3 PHY reset */ - setbits_le32(&dwc3_reg->g_usb3pipectl[0], - DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Assert USB2 PHY reset */ - setbits_le32(&dwc3_reg->g_usb2phycfg, - DWC3_GUSB2PHYCFG_PHYSOFTRST); - - mdelay(100); - - /* Clear USB3 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb3pipectl[0], - DWC3_GUSB3PIPECTL_PHYSOFTRST); - - /* Clear USB2 PHY reset */ - clrbits_le32(&dwc3_reg->g_usb2phycfg, - DWC3_GUSB2PHYCFG_PHYSOFTRST); - - /* After PHYs are stable we can take Core out of reset state */ - clrbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_CORESOFTRESET); -} - -static int dwc3_core_init(struct dwc3 *dwc3_reg) -{ - u32 reg; - u32 revision; - unsigned int dwc3_hwparams1; - - revision = readl(&dwc3_reg->g_snpsid); - /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { - puts("this is not a DesignWare USB3 DRD Core\n"); - return -EINVAL; - } - - dwc3_core_soft_reset(dwc3_reg); - - dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); - - reg = readl(&dwc3_reg->g_ctl); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { - case DWC3_GHWPARAMS1_EN_PWROPT_CLK: - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - break; - default: - debug("No power optimization available\n"); - } - - /* - * WORKAROUND: DWC3 revisions <1.90a have a bug - * where the device can fail to connect at SuperSpeed - * and falls back to high-speed mode which causes - * the device to enter a Connect/Disconnect loop - */ - if ((revision & DWC3_REVISION_MASK) < 0x190a) - reg |= DWC3_GCTL_U2RSTECN; - - writel(reg, &dwc3_reg->g_ctl); - - return 0; -} - -static int exynos_xhci_core_init(struct exynos_xhci *exynos) -{ - int ret; - - exynos5_usb3_phy_init(exynos->usb3_phy); - - ret = dwc3_core_init(exynos->dwc3_reg); - if (ret) { - debug("failed to initialize core\n"); - return -EINVAL; - } - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(exynos->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return 0; -} - -static void exynos_xhci_core_exit(struct exynos_xhci *exynos) -{ - exynos5_usb3_phy_exit(exynos->usb3_phy); -} - -int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) -{ - struct exynos_xhci *ctx = &exynos; - int ret; - -#ifdef CONFIG_OF_CONTROL - exynos_usb3_parse_dt(gd->fdt_blob, ctx); -#else - ctx->usb3_phy = (struct exynos_usb3_phy *)samsung_get_base_usb3_phy(); - ctx->hcd = (struct xhci_hccr *)samsung_get_base_usb_xhci(); -#endif - - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - -#ifdef CONFIG_OF_CONTROL - /* setup the Vbus gpio here */ - if (fdt_gpio_isvalid(&ctx->vbus_gpio) && - !fdtdec_setup_gpio(&ctx->vbus_gpio)) - gpio_direction_output(ctx->vbus_gpio.gpio, 1); -#endif - - ret = exynos_xhci_core_init(ctx); - if (ret) { - puts("XHCI: failed to initialize controller\n"); - return -EINVAL; - } - - *hccr = (ctx->hcd); - *hcor = (struct xhci_hcor *)((uint32_t) *hccr - + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - debug("Exynos5-xhci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - return 0; -} - -void xhci_hcd_stop(int index) -{ - struct exynos_xhci *ctx = &exynos; - - exynos_xhci_core_exit(ctx); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c b/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c deleted file mode 100644 index 89908e8a8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-mem.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <malloc.h> -#include <asm/cache.h> -#include <asm-generic/errno.h> - -#include "xhci.h" - -#define CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE -/** - * flushes the address passed till the length - * - * @param addr pointer to memory region to be flushed - * @param len the length of the cache line to be flushed - * @return none - */ -void xhci_flush_cache(uint32_t addr, u32 len) -{ - BUG_ON((void *)addr == NULL || len == 0); - - flush_dcache_range(addr & ~(CACHELINE_SIZE - 1), - ALIGN(addr + len, CACHELINE_SIZE)); -} - -/** - * invalidates the address passed till the length - * - * @param addr pointer to memory region to be invalidates - * @param len the length of the cache line to be invalidated - * @return none - */ -void xhci_inval_cache(uint32_t addr, u32 len) -{ - BUG_ON((void *)addr == NULL || len == 0); - - invalidate_dcache_range(addr & ~(CACHELINE_SIZE - 1), - ALIGN(addr + len, CACHELINE_SIZE)); -} - - -/** - * frees the "segment" pointer passed - * - * @param ptr pointer to "segement" to be freed - * @return none - */ -static void xhci_segment_free(struct xhci_segment *seg) -{ - free(seg->trbs); - seg->trbs = NULL; - - free(seg); -} - -/** - * frees the "ring" pointer passed - * - * @param ptr pointer to "ring" to be freed - * @return none - */ -static void xhci_ring_free(struct xhci_ring *ring) -{ - struct xhci_segment *seg; - struct xhci_segment *first_seg; - - BUG_ON(!ring); - - first_seg = ring->first_seg; - seg = first_seg->next; - while (seg != first_seg) { - struct xhci_segment *next = seg->next; - xhci_segment_free(seg); - seg = next; - } - xhci_segment_free(first_seg); - - free(ring); -} - -/** - * frees the "xhci_container_ctx" pointer passed - * - * @param ptr pointer to "xhci_container_ctx" to be freed - * @return none - */ -static void xhci_free_container_ctx(struct xhci_container_ctx *ctx) -{ - free(ctx->bytes); - free(ctx); -} - -/** - * frees the virtual devices for "xhci_ctrl" pointer passed - * - * @param ptr pointer to "xhci_ctrl" whose virtual devices are to be freed - * @return none - */ -static void xhci_free_virt_devices(struct xhci_ctrl *ctrl) -{ - int i; - int slot_id; - struct xhci_virt_device *virt_dev; - - /* - * refactored here to loop through all virt_dev - * Slot ID 0 is reserved - */ - for (slot_id = 0; slot_id < MAX_HC_SLOTS; slot_id++) { - virt_dev = ctrl->devs[slot_id]; - if (!virt_dev) - continue; - - ctrl->dcbaa->dev_context_ptrs[slot_id] = 0; - - for (i = 0; i < 31; ++i) - if (virt_dev->eps[i].ring) - xhci_ring_free(virt_dev->eps[i].ring); - - if (virt_dev->in_ctx) - xhci_free_container_ctx(virt_dev->in_ctx); - if (virt_dev->out_ctx) - xhci_free_container_ctx(virt_dev->out_ctx); - - free(virt_dev); - /* make sure we are pointing to NULL */ - ctrl->devs[slot_id] = NULL; - } -} - -/** - * frees all the memory allocated - * - * @param ptr pointer to "xhci_ctrl" to be cleaned up - * @return none - */ -void xhci_cleanup(struct xhci_ctrl *ctrl) -{ - xhci_ring_free(ctrl->event_ring); - xhci_ring_free(ctrl->cmd_ring); - xhci_free_virt_devices(ctrl); - free(ctrl->erst.entries); - free(ctrl->dcbaa); - memset(ctrl, '\0', sizeof(struct xhci_ctrl)); -} - -/** - * Malloc the aligned memory - * - * @param size size of memory to be allocated - * @return allocates the memory and returns the aligned pointer - */ -static void *xhci_malloc(unsigned int size) -{ - void *ptr; - size_t cacheline_size = max(XHCI_ALIGNMENT, CACHELINE_SIZE); - - ptr = memalign(cacheline_size, ALIGN(size, cacheline_size)); - BUG_ON(!ptr); - memset(ptr, '\0', size); - - xhci_flush_cache((uint32_t)ptr, size); - - return ptr; -} - -/** - * Make the prev segment point to the next segment. - * Change the last TRB in the prev segment to be a Link TRB which points to the - * address of the next segment. The caller needs to set any Link TRB - * related flags, such as End TRB, Toggle Cycle, and no snoop. - * - * @param prev pointer to the previous segment - * @param next pointer to the next segment - * @param link_trbs flag to indicate whether to link the trbs or NOT - * @return none - */ -static void xhci_link_segments(struct xhci_segment *prev, - struct xhci_segment *next, bool link_trbs) -{ - u32 val; - u64 val_64 = 0; - - if (!prev || !next) - return; - prev->next = next; - if (link_trbs) { - val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; - - /* - * Set the last TRB in the segment to - * have a TRB type ID of Link TRB - */ - val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); - val &= ~TRB_TYPE_BITMASK; - val |= (TRB_LINK << TRB_TYPE_SHIFT); - - prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); - } -} - -/** - * Initialises the Ring's enqueue,dequeue,enq_seg pointers - * - * @param ring pointer to the RING to be intialised - * @return none - */ -static void xhci_initialize_ring_info(struct xhci_ring *ring) -{ - /* - * The ring is empty, so the enqueue pointer == dequeue pointer - */ - ring->enqueue = ring->first_seg->trbs; - ring->enq_seg = ring->first_seg; - ring->dequeue = ring->enqueue; - ring->deq_seg = ring->first_seg; - - /* - * The ring is initialized to 0. The producer must write 1 to the - * cycle bit to handover ownership of the TRB, so PCS = 1. - * The consumer must compare CCS to the cycle bit to - * check ownership, so CCS = 1. - */ - ring->cycle_state = 1; -} - -/** - * Allocates a generic ring segment from the ring pool, sets the dma address, - * initializes the segment to zero, and sets the private next pointer to NULL. - * Section 4.11.1.1: - * "All components of all Command and Transfer TRBs shall be initialized to '0'" - * - * @param none - * @return pointer to the newly allocated SEGMENT - */ -static struct xhci_segment *xhci_segment_alloc(void) -{ - struct xhci_segment *seg; - - seg = (struct xhci_segment *)malloc(sizeof(struct xhci_segment)); - BUG_ON(!seg); - - seg->trbs = (union xhci_trb *)xhci_malloc(SEGMENT_SIZE); - - seg->next = NULL; - - return seg; -} - -/** - * Create a new ring with zero or more segments. - * TODO: current code only uses one-time-allocated single-segment rings - * of 1KB anyway, so we might as well get rid of all the segment and - * linking code (and maybe increase the size a bit, e.g. 4KB). - * - * - * Link each segment together into a ring. - * Set the end flag and the cycle toggle bit on the last segment. - * See section 4.9.2 and figures 15 and 16 of XHCI spec rev1.0. - * - * @param num_segs number of segments in the ring - * @param link_trbs flag to indicate whether to link the trbs or NOT - * @return pointer to the newly created RING - */ -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) -{ - struct xhci_ring *ring; - struct xhci_segment *prev; - - ring = (struct xhci_ring *)malloc(sizeof(struct xhci_ring)); - BUG_ON(!ring); - - if (num_segs == 0) - return ring; - - ring->first_seg = xhci_segment_alloc(); - BUG_ON(!ring->first_seg); - - num_segs--; - - prev = ring->first_seg; - while (num_segs > 0) { - struct xhci_segment *next; - - next = xhci_segment_alloc(); - BUG_ON(!next); - - xhci_link_segments(prev, next, link_trbs); - - prev = next; - num_segs--; - } - xhci_link_segments(prev, ring->first_seg, link_trbs); - if (link_trbs) { - /* See section 4.9.2.1 and 6.4.4.1 */ - prev->trbs[TRBS_PER_SEGMENT-1].link.control |= - cpu_to_le32(LINK_TOGGLE); - } - xhci_initialize_ring_info(ring); - - return ring; -} - -/** - * Allocates the Container context - * - * @param ctrl Host controller data structure - * @param type type of XHCI Container Context - * @return NULL if failed else pointer to the context on success - */ -static struct xhci_container_ctx - *xhci_alloc_container_ctx(struct xhci_ctrl *ctrl, int type) -{ - struct xhci_container_ctx *ctx; - - ctx = (struct xhci_container_ctx *) - malloc(sizeof(struct xhci_container_ctx)); - BUG_ON(!ctx); - - BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); - ctx->type = type; - ctx->size = (MAX_EP_CTX_NUM + 1) * - CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); - if (type == XHCI_CTX_TYPE_INPUT) - ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); - - ctx->bytes = (u8 *)xhci_malloc(ctx->size); - - return ctx; -} - -/** - * Allocating virtual device - * - * @param udev pointer to USB deivce structure - * @return 0 on success else -1 on failure - */ -int xhci_alloc_virt_device(struct usb_device *udev) -{ - u64 byte_64 = 0; - unsigned int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev; - struct xhci_ctrl *ctrl = udev->controller; - - /* Slot ID 0 is reserved */ - if (ctrl->devs[slot_id]) { - printf("Virt dev for slot[%d] already allocated\n", slot_id); - return -EEXIST; - } - - ctrl->devs[slot_id] = (struct xhci_virt_device *) - malloc(sizeof(struct xhci_virt_device)); - - if (!ctrl->devs[slot_id]) { - puts("Failed to allocate virtual device\n"); - return -ENOMEM; - } - - memset(ctrl->devs[slot_id], 0, sizeof(struct xhci_virt_device)); - virt_dev = ctrl->devs[slot_id]; - - /* Allocate the (output) device context that will be used in the HC. */ - virt_dev->out_ctx = xhci_alloc_container_ctx(ctrl, - XHCI_CTX_TYPE_DEVICE); - if (!virt_dev->out_ctx) { - puts("Failed to allocate out context for virt dev\n"); - return -ENOMEM; - } - - /* Allocate the (input) device context for address device command */ - virt_dev->in_ctx = xhci_alloc_container_ctx(ctrl, - XHCI_CTX_TYPE_INPUT); - if (!virt_dev->in_ctx) { - puts("Failed to allocate in context for virt dev\n"); - return -ENOMEM; - } - - /* Allocate endpoint 0 ring */ - virt_dev->eps[0].ring = xhci_ring_alloc(1, true); - - byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); - - /* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; - - xhci_flush_cache((uint32_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], - sizeof(__le64)); - return 0; -} - -/** - * Allocates the necessary data structures - * for XHCI host controller - * - * @param ctrl Host controller data structure - * @param hccr pointer to HOST Controller Control Registers - * @param hcor pointer to HOST Controller Operational Registers - * @return 0 if successful else -1 on failure - */ -int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, - struct xhci_hcor *hcor) -{ - uint64_t val_64; - uint64_t trb_64; - uint32_t val; - unsigned long deq; - int i; - struct xhci_segment *seg; - - /* DCBAA initialization */ - ctrl->dcbaa = (struct xhci_device_context_array *) - xhci_malloc(sizeof(struct xhci_device_context_array)); - if (ctrl->dcbaa == NULL) { - puts("unable to allocate DCBA\n"); - return -ENOMEM; - } - - val_64 = (uintptr_t)ctrl->dcbaa; - /* Set the pointer in DCBAA register */ - xhci_writeq(&hcor->or_dcbaap, val_64); - - /* Command ring control pointer register initialization */ - ctrl->cmd_ring = xhci_ring_alloc(1, true); - - /* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; - val_64 = xhci_readq(&hcor->or_crcr); - val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | - (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | - ctrl->cmd_ring->cycle_state; - xhci_writeq(&hcor->or_crcr, val_64); - - /* write the address of db register */ - val = xhci_readl(&hccr->cr_dboff); - val &= DBOFF_MASK; - ctrl->dba = (struct xhci_doorbell_array *)((char *)hccr + val); - - /* write the address of runtime register */ - val = xhci_readl(&hccr->cr_rtsoff); - val &= RTSOFF_MASK; - ctrl->run_regs = (struct xhci_run_regs *)((char *)hccr + val); - - /* writting the address of ir_set structure */ - ctrl->ir_set = &ctrl->run_regs->ir_set[0]; - - /* Event ring does not maintain link TRB */ - ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false); - ctrl->erst.entries = (struct xhci_erst_entry *) - xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); - - ctrl->erst.num_entries = ERST_NUM_SEGS; - - for (val = 0, seg = ctrl->event_ring->first_seg; - val < ERST_NUM_SEGS; - val++) { - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; - struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - xhci_writeq(&entry->seg_addr, trb_64); - entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); - entry->rsvd = 0; - seg = seg->next; - } - xhci_flush_cache((uint32_t)ctrl->erst.entries, - ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - - deq = (unsigned long)ctrl->event_ring->dequeue; - - /* Update HC event ring dequeue pointer */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (u64)deq & (u64)~ERST_PTR_MASK); - - /* set ERST count with the number of entries in the segment table */ - val = xhci_readl(&ctrl->ir_set->erst_size); - val &= ERST_SIZE_MASK; - val |= ERST_NUM_SEGS; - xhci_writel(&ctrl->ir_set->erst_size, val); - - /* this is the event ring segment table pointer */ - val_64 = xhci_readq(&ctrl->ir_set->erst_base); - val_64 &= ERST_PTR_MASK; - val_64 |= ((u32)(ctrl->erst.entries) & ~ERST_PTR_MASK); - - xhci_writeq(&ctrl->ir_set->erst_base, val_64); - - /* initializing the virtual devices to NULL */ - for (i = 0; i < MAX_HC_SLOTS; ++i) - ctrl->devs[i] = NULL; - - /* - * Just Zero'ing this register completely, - * or some spurious Device Notification Events - * might screw things here. - */ - xhci_writel(&hcor->or_dnctrl, 0x0); - - return 0; -} - -/** - * Give the input control context for the passed container context - * - * @param ctx pointer to the context - * @return pointer to the Input control context data - */ -struct xhci_input_control_ctx - *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx) -{ - BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT); - return (struct xhci_input_control_ctx *)ctx->bytes; -} - -/** - * Give the slot context for the passed container context - * - * @param ctrl Host controller data structure - * @param ctx pointer to the context - * @return pointer to the slot control context data - */ -struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx) -{ - if (ctx->type == XHCI_CTX_TYPE_DEVICE) - return (struct xhci_slot_ctx *)ctx->bytes; - - return (struct xhci_slot_ctx *) - (ctx->bytes + CTX_SIZE(readl(&ctrl->hccr->cr_hccparams))); -} - -/** - * Gets the EP context from based on the ep_index - * - * @param ctrl Host controller data structure - * @param ctx context container - * @param ep_index index of the endpoint - * @return pointer to the End point context - */ -struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx, - unsigned int ep_index) -{ - /* increment ep index by offset of start of ep ctx array */ - ep_index++; - if (ctx->type == XHCI_CTX_TYPE_INPUT) - ep_index++; - - return (struct xhci_ep_ctx *) - (ctx->bytes + - (ep_index * CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)))); -} - -/** - * Copy output xhci_ep_ctx to the input xhci_ep_ctx copy. - * Useful when you want to change one particular aspect of the endpoint - * and then issue a configure endpoint command. - * - * @param ctrl Host controller data structure - * @param in_ctx contains the input context - * @param out_ctx contains the input context - * @param ep_index index of the end point - * @return none - */ -void xhci_endpoint_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index) -{ - struct xhci_ep_ctx *out_ep_ctx; - struct xhci_ep_ctx *in_ep_ctx; - - out_ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index); - in_ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - - in_ep_ctx->ep_info = out_ep_ctx->ep_info; - in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2; - in_ep_ctx->deq = out_ep_ctx->deq; - in_ep_ctx->tx_info = out_ep_ctx->tx_info; -} - -/** - * Copy output xhci_slot_ctx to the input xhci_slot_ctx. - * Useful when you want to change one particular aspect of the endpoint - * and then issue a configure endpoint command. - * Only the context entries field matters, but - * we'll copy the whole thing anyway. - * - * @param ctrl Host controller data structure - * @param in_ctx contains the inpout context - * @param out_ctx contains the inpout context - * @return none - */ -void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx) -{ - struct xhci_slot_ctx *in_slot_ctx; - struct xhci_slot_ctx *out_slot_ctx; - - in_slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - out_slot_ctx = xhci_get_slot_ctx(ctrl, out_ctx); - - in_slot_ctx->dev_info = out_slot_ctx->dev_info; - in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2; - in_slot_ctx->tt_info = out_slot_ctx->tt_info; - in_slot_ctx->dev_state = out_slot_ctx->dev_state; -} - -/** - * Setup an xHCI virtual device for a Set Address command - * - * @param udev pointer to the Device Data Structure - * @return returns negative value on failure else 0 on success - */ -void xhci_setup_addressable_virt_dev(struct usb_device *udev) -{ - struct usb_device *hop = udev; - struct xhci_virt_device *virt_dev; - struct xhci_ep_ctx *ep0_ctx; - struct xhci_slot_ctx *slot_ctx; - u32 port_num = 0; - u64 trb_64 = 0; - struct xhci_ctrl *ctrl = udev->controller; - - virt_dev = ctrl->devs[udev->slot_id]; - - BUG_ON(!virt_dev); - - /* Extract the EP0 and Slot Ctrl */ - ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0); - slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); - - /* Only the control endpoint is valid - one endpoint context */ - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0); - - switch (udev->speed) { - case USB_SPEED_SUPER: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); - break; - case USB_SPEED_HIGH: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); - break; - case USB_SPEED_FULL: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); - break; - case USB_SPEED_LOW: - slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); - break; - default: - /* Speed was set earlier, this shouldn't happen. */ - BUG(); - } - - /* Extract the root hub port number */ - if (hop->parent) - while (hop->parent->parent) - hop = hop->parent; - port_num = hop->portnr; - debug("port_num = %d\n", port_num); - - slot_ctx->dev_info2 |= - cpu_to_le32(((port_num & ROOT_HUB_PORT_MASK) << - ROOT_HUB_PORT_SHIFT)); - - /* Step 4 - ring already allocated */ - /* Step 5 */ - ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); - debug("SPEED = %d\n", udev->speed); - - switch (udev->speed) { - case USB_SPEED_SUPER: - ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 512bytes\n"); - break; - case USB_SPEED_HIGH: - /* USB core guesses at a 64-byte max packet first for FS devices */ - case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 64bytes\n"); - break; - case USB_SPEED_LOW: - ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); - debug("Setting Packet size = 8bytes\n"); - break; - default: - /* New speed? */ - BUG(); - } - - /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ - ep0_ctx->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); - - trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; - ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); - - /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ - - xhci_flush_cache((uint32_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); - xhci_flush_cache((uint32_t)slot_ctx, sizeof(struct xhci_slot_ctx)); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c b/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c deleted file mode 100644 index e667810bb..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-omap.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * OMAP USB HOST xHCI Controller - * - * (C) Copyright 2013 - * Texas Instruments, <www.ti.com> - * - * Author: Dan Murphy <dmurphy@ti.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <usb.h> -#include <asm-generic/errno.h> -#include <asm/omap_common.h> -#include <asm/arch/cpu.h> -#include <asm/arch/sys_proto.h> - -#include <linux/compat.h> -#include <linux/usb/dwc3.h> -#include <linux/usb/xhci-omap.h> - -#include "xhci.h" - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -static struct omap_xhci omap; - -inline int __board_usb_init(int index, enum usb_init_type init) -{ - return 0; -} -int board_usb_init(int index, enum usb_init_type init) - __attribute__((weak, alias("__board_usb_init"))); - -static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) -{ - clrsetbits_le32(&dwc3_reg->g_ctl, - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), - DWC3_GCTL_PRTCAPDIR(mode)); -} - -static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) -{ - /* Before Resetting PHY, put Core in Reset */ - setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); - - omap_reset_usb_phy(dwc3_reg); - - /* After PHYs are stable we can take Core out of reset state */ - clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); -} - -static int dwc3_core_init(struct dwc3 *dwc3_reg) -{ - u32 reg; - u32 revision; - unsigned int dwc3_hwparams1; - - revision = readl(&dwc3_reg->g_snpsid); - /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { - puts("this is not a DesignWare USB3 DRD Core\n"); - return -1; - } - - dwc3_core_soft_reset(dwc3_reg); - - dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); - - reg = readl(&dwc3_reg->g_ctl); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { - case DWC3_GHWPARAMS1_EN_PWROPT_CLK: - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - break; - default: - debug("No power optimization available\n"); - } - - /* - * WORKAROUND: DWC3 revisions <1.90a have a bug - * where the device can fail to connect at SuperSpeed - * and falls back to high-speed mode which causes - * the device to enter a Connect/Disconnect loop - */ - if ((revision & DWC3_REVISION_MASK) < 0x190a) - reg |= DWC3_GCTL_U2RSTECN; - - writel(reg, &dwc3_reg->g_ctl); - - return 0; -} - -static int omap_xhci_core_init(struct omap_xhci *omap) -{ - int ret = 0; - - omap_enable_phy(omap); - - ret = dwc3_core_init(omap->dwc3_reg); - if (ret) { - debug("%s:failed to initialize core\n", __func__); - return ret; - } - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(omap->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return ret; -} - -static void omap_xhci_core_exit(struct omap_xhci *omap) -{ - usb_phy_power(0); -} - -int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) -{ - struct omap_xhci *ctx = &omap; - int ret = 0; - - ctx->hcd = (struct xhci_hccr *)OMAP_XHCI_BASE; - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - ctx->usb3_phy = (struct omap_usb3_phy *)OMAP_OCP1_SCP_BASE; - ctx->otg_wrapper = (struct omap_dwc_wrapper *)OMAP_OTG_WRAPPER_BASE; - - ret = board_usb_init(index, USB_INIT_HOST); - if (ret != 0) { - puts("Failed to initialize board for USB\n"); - return ret; - } - - ret = omap_xhci_core_init(ctx); - if (ret < 0) { - puts("Failed to initialize xhci\n"); - return ret; - } - - *hccr = (struct xhci_hccr *)(OMAP_XHCI_BASE); - *hcor = (struct xhci_hcor *)((uint32_t) *hccr - + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - debug("omap-xhci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); - - return ret; -} - -void xhci_hcd_stop(int index) -{ - struct omap_xhci *ctx = &omap; - - omap_xhci_core_exit(ctx); -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c b/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c deleted file mode 100644 index 19c3ec621..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci-ring.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <asm/unaligned.h> -#include <asm-generic/errno.h> - -#include "xhci.h" - -/** - * Is this TRB a link TRB or was the last TRB the last TRB in this event ring - * segment? I.e. would the updated event TRB pointer step off the end of the - * event seg ? - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param seg poniter to the segment to which TRB belongs - * @param trb poniter to the ring trb - * @return 1 if this TRB a link TRB else 0 - */ -static int last_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring, - struct xhci_segment *seg, union xhci_trb *trb) -{ - if (ring == ctrl->event_ring) - return trb == &seg->trbs[TRBS_PER_SEGMENT]; - else - return TRB_TYPE_LINK_LE32(trb->link.control); -} - -/** - * Does this link TRB point to the first segment in a ring, - * or was the previous TRB the last TRB on the last segment in the ERST? - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param seg poniter to the segment to which TRB belongs - * @param trb poniter to the ring trb - * @return 1 if this TRB is the last TRB on the last segment else 0 - */ -static bool last_trb_on_last_seg(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - struct xhci_segment *seg, - union xhci_trb *trb) -{ - if (ring == ctrl->event_ring) - return ((trb == &seg->trbs[TRBS_PER_SEGMENT]) && - (seg->next == ring->first_seg)); - else - return le32_to_cpu(trb->link.control) & LINK_TOGGLE; -} - -/** - * See Cycle bit rules. SW is the consumer for the event ring only. - * Don't make a ring full of link TRBs. That would be dumb and this would loop. - * - * If we've just enqueued a TRB that is in the middle of a TD (meaning the - * chain bit is set), then set the chain bit in all the following link TRBs. - * If we've enqueued the last TRB in a TD, make sure the following link TRBs - * have their chain bit cleared (so that each Link TRB is a separate TD). - * - * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit - * set, but other sections talk about dealing with the chain bit set. This was - * fixed in the 0.96 specification errata, but we have to assume that all 0.95 - * xHCI hardware can't handle the chain bit being cleared on a link TRB. - * - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param more_trbs_coming flag to indicate whether more trbs - * are expected or NOT. - * Will you enqueue more TRBs before calling - * prepare_ring()? - * @return none - */ -static void inc_enq(struct xhci_ctrl *ctrl, struct xhci_ring *ring, - bool more_trbs_coming) -{ - u32 chain; - union xhci_trb *next; - - chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN; - next = ++(ring->enqueue); - - /* - * Update the dequeue pointer further if that was a link TRB or we're at - * the end of an event ring segment (which doesn't have link TRBS) - */ - while (last_trb(ctrl, ring, ring->enq_seg, next)) { - if (ring != ctrl->event_ring) { - /* - * If the caller doesn't plan on enqueueing more - * TDs before ringing the doorbell, then we - * don't want to give the link TRB to the - * hardware just yet. We'll give the link TRB - * back in prepare_ring() just before we enqueue - * the TD at the top of the ring. - */ - if (!chain && !more_trbs_coming) - break; - - /* - * If we're not dealing with 0.95 hardware or - * isoc rings on AMD 0.96 host, - * carry over the chain bit of the previous TRB - * (which may mean the chain bit is cleared). - */ - next->link.control &= cpu_to_le32(~TRB_CHAIN); - next->link.control |= cpu_to_le32(chain); - - next->link.control ^= cpu_to_le32(TRB_CYCLE); - xhci_flush_cache((uint32_t)next, - sizeof(union xhci_trb)); - } - /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(ctrl, ring, - ring->enq_seg, next)) - ring->cycle_state = (ring->cycle_state ? 0 : 1); - - ring->enq_seg = ring->enq_seg->next; - ring->enqueue = ring->enq_seg->trbs; - next = ring->enqueue; - } -} - -/** - * See Cycle bit rules. SW is the consumer for the event ring only. - * Don't make a ring full of link TRBs. That would be dumb and this would loop. - * - * @param ctrl Host controller data structure - * @param ring Ring whose Dequeue TRB pointer needs to be incremented. - * return none - */ -static void inc_deq(struct xhci_ctrl *ctrl, struct xhci_ring *ring) -{ - do { - /* - * Update the dequeue pointer further if that was a link TRB or - * we're at the end of an event ring segment (which doesn't have - * link TRBS) - */ - if (last_trb(ctrl, ring, ring->deq_seg, ring->dequeue)) { - if (ring == ctrl->event_ring && - last_trb_on_last_seg(ctrl, ring, - ring->deq_seg, ring->dequeue)) { - ring->cycle_state = (ring->cycle_state ? 0 : 1); - } - ring->deq_seg = ring->deq_seg->next; - ring->dequeue = ring->deq_seg->trbs; - } else { - ring->dequeue++; - } - } while (last_trb(ctrl, ring, ring->deq_seg, ring->dequeue)); -} - -/** - * Generic function for queueing a TRB on a ring. - * The caller must have checked to make sure there's room on the ring. - * - * @param more_trbs_coming: Will you enqueue more TRBs before calling - * prepare_ring()? - * @param ctrl Host controller data structure - * @param ring pointer to the ring - * @param more_trbs_coming flag to indicate whether more trbs - * @param trb_fields pointer to trb field array containing TRB contents - * @return pointer to the enqueued trb - */ -static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - bool more_trbs_coming, - unsigned int *trb_fields) -{ - struct xhci_generic_trb *trb; - int i; - - trb = &ring->enqueue->generic; - - for (i = 0; i < 4; i++) - trb->field[i] = cpu_to_le32(trb_fields[i]); - - xhci_flush_cache((uint32_t)trb, sizeof(struct xhci_generic_trb)); - - inc_enq(ctrl, ring, more_trbs_coming); - - return trb; -} - -/** - * Does various checks on the endpoint ring, and makes it ready - * to queue num_trbs. - * - * @param ctrl Host controller data structure - * @param ep_ring pointer to the EP Transfer Ring - * @param ep_state State of the End Point - * @return error code in case of invalid ep_state, 0 on success - */ -static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring, - u32 ep_state) -{ - union xhci_trb *next = ep_ring->enqueue; - - /* Make sure the endpoint has been added to xHC schedule */ - switch (ep_state) { - case EP_STATE_DISABLED: - /* - * USB core changed config/interfaces without notifying us, - * or hardware is reporting the wrong state. - */ - puts("WARN urb submitted to disabled ep\n"); - return -ENOENT; - case EP_STATE_ERROR: - puts("WARN waiting for error on ep to be cleared\n"); - return -EINVAL; - case EP_STATE_HALTED: - puts("WARN halted endpoint, queueing URB anyway.\n"); - case EP_STATE_STOPPED: - case EP_STATE_RUNNING: - debug("EP STATE RUNNING.\n"); - break; - default: - puts("ERROR unknown endpoint state for ep\n"); - return -EINVAL; - } - - while (last_trb(ctrl, ep_ring, ep_ring->enq_seg, next)) { - /* - * If we're not dealing with 0.95 hardware or isoc rings - * on AMD 0.96 host, clear the chain bit. - */ - next->link.control &= cpu_to_le32(~TRB_CHAIN); - - next->link.control ^= cpu_to_le32(TRB_CYCLE); - - xhci_flush_cache((uint32_t)next, sizeof(union xhci_trb)); - - /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(ctrl, ep_ring, - ep_ring->enq_seg, next)) - ep_ring->cycle_state = (ep_ring->cycle_state ? 0 : 1); - ep_ring->enq_seg = ep_ring->enq_seg->next; - ep_ring->enqueue = ep_ring->enq_seg->trbs; - next = ep_ring->enqueue; - } - - return 0; -} - -/** - * Generic function for queueing a command TRB on the command ring. - * Check to make sure there's room on the command ring for one command TRB. - * - * @param ctrl Host controller data structure - * @param ptr Pointer address to write in the first two fields (opt.) - * @param slot_id Slot ID to encode in the flags field (opt.) - * @param ep_index Endpoint index to encode in the flags field (opt.) - * @param cmd Command type to enqueue - * @return none - */ -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, - u32 ep_index, trb_type cmd) -{ - u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; - - BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); - - fields[0] = lower_32_bits(val_64); - fields[1] = upper_32_bits(val_64); - fields[2] = 0; - fields[3] = TRB_TYPE(cmd) | EP_ID_FOR_TRB(ep_index) | - SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; - - queue_trb(ctrl, ctrl->cmd_ring, false, fields); - - /* Ring the command ring doorbell */ - xhci_writel(&ctrl->dba->doorbell[0], DB_VALUE_HOST); -} - -/** - * The TD size is the number of bytes remaining in the TD (including this TRB), - * right shifted by 10. - * It must fit in bits 21:17, so it can't be bigger than 31. - * - * @param remainder remaining packets to be sent - * @return remainder if remainder is less than max else max - */ -static u32 xhci_td_remainder(unsigned int remainder) -{ - u32 max = (1 << (21 - 17 + 1)) - 1; - - if ((remainder >> 10) >= max) - return max << 17; - else - return (remainder >> 10) << 17; -} - -/** - * Finds out the remanining packets to be sent - * - * @param running_total total size sent so far - * @param trb_buff_len length of the TRB Buffer - * @param total_packet_count total packet count - * @param maxpacketsize max packet size of current pipe - * @param num_trbs_left number of TRBs left to be processed - * @return 0 if running_total or trb_buff_len is 0, else remainder - */ -static u32 xhci_v1_0_td_remainder(int running_total, - int trb_buff_len, - unsigned int total_packet_count, - int maxpacketsize, - unsigned int num_trbs_left) -{ - int packets_transferred; - - /* One TRB with a zero-length data packet. */ - if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0)) - return 0; - - /* - * All the TRB queueing functions don't count the current TRB in - * running_total. - */ - packets_transferred = (running_total + trb_buff_len) / maxpacketsize; - - if ((total_packet_count - packets_transferred) > 31) - return 31 << 17; - return (total_packet_count - packets_transferred) << 17; -} - -/** - * Ring the doorbell of the End Point - * - * @param udev pointer to the USB device structure - * @param ep_index index of the endpoint - * @param start_cycle cycle flag of the first TRB - * @param start_trb pionter to the first TRB - * @return none - */ -static void giveback_first_trb(struct usb_device *udev, int ep_index, - int start_cycle, - struct xhci_generic_trb *start_trb) -{ - struct xhci_ctrl *ctrl = udev->controller; - - /* - * Pass all the TRBs to the hardware at once and make sure this write - * isn't reordered. - */ - if (start_cycle) - start_trb->field[3] |= cpu_to_le32(start_cycle); - else - start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); - - xhci_flush_cache((uint32_t)start_trb, sizeof(struct xhci_generic_trb)); - - /* Ringing EP doorbell here */ - xhci_writel(&ctrl->dba->doorbell[udev->slot_id], - DB_VALUE(ep_index, 0)); - - return; -} - -/**** POLLING mechanism for XHCI ****/ - -/** - * Finalizes a handled event TRB by advancing our dequeue pointer and giving - * the TRB back to the hardware for recycling. Must call this exactly once at - * the end of each event handler, and not touch the TRB again afterwards. - * - * @param ctrl Host controller data structure - * @return none - */ -void xhci_acknowledge_event(struct xhci_ctrl *ctrl) -{ - /* Advance our dequeue pointer to the next event */ - inc_deq(ctrl, ctrl->event_ring); - - /* Inform the hardware */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); -} - -/** - * Checks if there is a new event to handle on the event ring. - * - * @param ctrl Host controller data structure - * @return 0 if failure else 1 on success - */ -static int event_ready(struct xhci_ctrl *ctrl) -{ - union xhci_trb *event; - - xhci_inval_cache((uint32_t)ctrl->event_ring->dequeue, - sizeof(union xhci_trb)); - - event = ctrl->event_ring->dequeue; - - /* Does the HC or OS own the TRB? */ - if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) != - ctrl->event_ring->cycle_state) - return 0; - - return 1; -} - -/** - * Waits for a specific type of event and returns it. Discards unexpected - * events. Caller *must* call xhci_acknowledge_event() after it is finished - * processing the event, and must not access the returned pointer afterwards. - * - * @param ctrl Host controller data structure - * @param expected TRB type expected from Event TRB - * @return pointer to event trb - */ -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) -{ - trb_type type; - unsigned long ts = get_timer(0); - - do { - union xhci_trb *event = ctrl->event_ring->dequeue; - - if (!event_ready(ctrl)) - continue; - - type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); - if (type == expected) - return event; - - if (type == TRB_PORT_STATUS) - /* TODO: remove this once enumeration has been reworked */ - /* - * Port status change events always have a - * successful completion code - */ - BUG_ON(GET_COMP_CODE( - le32_to_cpu(event->generic.field[2])) != - COMP_SUCCESS); - else - printf("Unexpected XHCI event TRB, skipping... " - "(%08x %08x %08x %08x)\n", - le32_to_cpu(event->generic.field[0]), - le32_to_cpu(event->generic.field[1]), - le32_to_cpu(event->generic.field[2]), - le32_to_cpu(event->generic.field[3])); - - xhci_acknowledge_event(ctrl); - } while (get_timer(ts) < XHCI_TIMEOUT); - - if (expected == TRB_TRANSFER) - return NULL; - - printf("XHCI timeout on event type %d... cannot recover.\n", expected); - BUG(); -} - -/* - * Stops transfer processing for an endpoint and throws away all unprocessed - * TRBs by setting the xHC's dequeue pointer to our enqueue pointer. The next - * xhci_bulk_tx/xhci_ctrl_tx on this enpoint will add new transfers there and - * ring the doorbell, causing this endpoint to start working again. - * (Careful: This will BUG() when there was no transfer in progress. Shouldn't - * happen in practice for current uses and is too complicated to fix right now.) - */ -static void abort_td(struct usb_device *udev, int ep_index) -{ - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; - union xhci_trb *event; - u32 field; - - xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len - != COMP_STOP))); - xhci_acknowledge_event(ctrl); - - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); - xhci_acknowledge_event(ctrl); - - xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue | - ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); - xhci_acknowledge_event(ctrl); -} - -static void record_transfer_result(struct usb_device *udev, - union xhci_trb *event, int length) -{ - udev->act_len = min(length, length - - EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len))); - - switch (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))) { - case COMP_SUCCESS: - BUG_ON(udev->act_len != length); - /* fallthrough */ - case COMP_SHORT_TX: - udev->status = 0; - break; - case COMP_STALL: - udev->status = USB_ST_STALLED; - break; - case COMP_DB_ERR: - case COMP_TRB_ERR: - udev->status = USB_ST_BUF_ERR; - break; - case COMP_BABBLE: - udev->status = USB_ST_BABBLE_DET; - break; - default: - udev->status = 0x80; /* USB_ST_TOO_LAZY_TO_MAKE_A_NEW_MACRO */ - } -} - -/**** Bulk and Control transfer methods ****/ -/** - * Queues up the BULK Request - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param length length of the buffer - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else -1 on failure - */ -int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer) -{ - int num_trbs = 0; - struct xhci_generic_trb *start_trb; - bool first_trb = 0; - int start_cycle; - u32 field = 0; - u32 length_field = 0; - struct xhci_ctrl *ctrl = udev->controller; - int slot_id = udev->slot_id; - int ep_index; - struct xhci_virt_device *virt_dev; - struct xhci_ep_ctx *ep_ctx; - struct xhci_ring *ring; /* EP transfer ring */ - union xhci_trb *event; - - int running_total, trb_buff_len; - unsigned int total_packet_count; - int maxpacketsize; - u64 addr; - int ret; - u32 trb_fields[4]; - u64 val_64 = (uintptr_t)buffer; - - debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n", - udev, pipe, buffer, length); - - ep_index = usb_pipe_ep_index(pipe); - virt_dev = ctrl->devs[slot_id]; - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - - ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); - - ring = virt_dev->eps[ep_index].ring; - /* - * How much data is (potentially) left before the 64KB boundary? - * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) - * that the buffer should not span 64KB boundary. if so - * we send request in more than 1 TRB by chaining them. - */ - running_total = TRB_MAX_BUFF_SIZE - - (lower_32_bits(val_64) & (TRB_MAX_BUFF_SIZE - 1)); - trb_buff_len = running_total; - running_total &= TRB_MAX_BUFF_SIZE - 1; - - /* - * If there's some data on this 64KB chunk, or we have to send a - * zero-length transfer, we need at least one TRB - */ - if (running_total != 0 || length == 0) - num_trbs++; - - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < length) { - num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; - } - - /* - * XXX: Calling routine prepare_ring() called in place of - * prepare_trasfer() as there in 'Linux' since we are not - * maintaining multiple TDs/transfer at the same time. - */ - ret = prepare_ring(ctrl, ring, - le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - if (ret < 0) - return ret; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ring->enqueue->generic; - start_cycle = ring->cycle_state; - - running_total = 0; - maxpacketsize = usb_maxpacket(udev, pipe); - - total_packet_count = DIV_ROUND_UP(length, maxpacketsize); - - /* How much data is in the first TRB? */ - /* - * How much data is (potentially) left before the 64KB boundary? - * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) - * that the buffer should not span 64KB boundary. if so - * we send request in more than 1 TRB by chaining them. - */ - addr = val_64; - - if (trb_buff_len > length) - trb_buff_len = length; - - first_trb = true; - - /* flush the buffer before use */ - xhci_flush_cache((uint32_t)buffer, length); - - /* Queue the first TRB, even if it's zero-length */ - do { - u32 remainder = 0; - field = 0; - /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) { - first_trb = false; - if (start_cycle == 0) - field |= TRB_CYCLE; - } else { - field |= ring->cycle_state; - } - - /* - * Chain all the TRBs together; clear the chain bit in the last - * TRB to indicate it's the last TRB in the chain. - */ - if (num_trbs > 1) - field |= TRB_CHAIN; - else - field |= TRB_IOC; - - /* Only set interrupt on short packet for IN endpoints */ - if (usb_pipein(pipe)) - field |= TRB_ISP; - - /* Set the TRB length, TD size, and interrupter fields. */ - if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) < 0x100) - remainder = xhci_td_remainder(length - running_total); - else - remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, - total_packet_count, - maxpacketsize, - num_trbs - 1); - - length_field = ((trb_buff_len & TRB_LEN_MASK) | - remainder | - ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); - - trb_fields[0] = lower_32_bits(addr); - trb_fields[1] = upper_32_bits(addr); - trb_fields[2] = length_field; - trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT); - - queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); - - --num_trbs; - - running_total += trb_buff_len; - - /* Calculate length for next transfer */ - addr += trb_buff_len; - trb_buff_len = min((length - running_total), TRB_MAX_BUFF_SIZE); - } while (running_total < length); - - giveback_first_trb(udev, ep_index, start_cycle, start_trb); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) { - debug("XHCI bulk transfer timed out, aborting...\n"); - abort_td(udev, ep_index); - udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ - udev->act_len = 0; - return -ETIMEDOUT; - } - field = le32_to_cpu(event->trans_event.flags); - - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(*(void **)(uintptr_t)le64_to_cpu(event->trans_event.buffer) - - buffer > (size_t)length); - - record_transfer_result(udev, event, length); - xhci_acknowledge_event(ctrl); - xhci_inval_cache((uint32_t)buffer, length); - - return (udev->status != USB_ST_NOT_PROC) ? 0 : -1; -} - -/** - * Queues up the Control Transfer Request - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param req request type - * @param length length of the buffer - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else error code on failure - */ -int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, - void *buffer) -{ - int ret; - int start_cycle; - int num_trbs; - u32 field; - u32 length_field; - u64 buf_64 = 0; - struct xhci_generic_trb *start_trb; - struct xhci_ctrl *ctrl = udev->controller; - int slot_id = udev->slot_id; - int ep_index; - u32 trb_fields[4]; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct xhci_ring *ep_ring; - union xhci_trb *event; - - debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", - req->request, req->request, - req->requesttype, req->requesttype, - le16_to_cpu(req->value), le16_to_cpu(req->value), - le16_to_cpu(req->index)); - - ep_index = usb_pipe_ep_index(pipe); - - ep_ring = virt_dev->eps[ep_index].ring; - - /* - * Check to see if the max packet size for the default control - * endpoint changed during FS device enumeration - */ - if (udev->speed == USB_SPEED_FULL) { - ret = xhci_check_maxpacket(udev); - if (ret < 0) - return ret; - } - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - - struct xhci_ep_ctx *ep_ctx = NULL; - ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); - - /* 1 TRB for setup, 1 for status */ - num_trbs = 2; - /* - * Don't need to check if we need additional event data and normal TRBs, - * since data in control transfers will never get bigger than 16MB - * XXX: can we get a buffer that crosses 64KB boundaries? - */ - - if (length > 0) - num_trbs++; - /* - * XXX: Calling routine prepare_ring() called in place of - * prepare_trasfer() as there in 'Linux' since we are not - * maintaining multiple TDs/transfer at the same time. - */ - ret = prepare_ring(ctrl, ep_ring, - le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - - if (ret < 0) - return ret; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - start_cycle = ep_ring->cycle_state; - - debug("start_trb %p, start_cycle %d\n", start_trb, start_cycle); - - /* Queue setup TRB - see section 6.4.1.2.1 */ - /* FIXME better way to translate setup_packet into two u32 fields? */ - field = 0; - field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT); - if (start_cycle == 0) - field |= 0x1; - - /* xHCI 1.0 6.4.1.2.1: Transfer Type field */ - if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) == 0x100) { - if (length > 0) { - if (req->requesttype & USB_DIR_IN) - field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT); - else - field |= (TRB_DATA_OUT << TRB_TX_TYPE_SHIFT); - } - } - - debug("req->requesttype = %d, req->request = %d," - "le16_to_cpu(req->value) = %d," - "le16_to_cpu(req->index) = %d," - "le16_to_cpu(req->length) = %d\n", - req->requesttype, req->request, le16_to_cpu(req->value), - le16_to_cpu(req->index), le16_to_cpu(req->length)); - - trb_fields[0] = req->requesttype | req->request << 8 | - le16_to_cpu(req->value) << 16; - trb_fields[1] = le16_to_cpu(req->index) | - le16_to_cpu(req->length) << 16; - /* TRB_LEN | (TRB_INTR_TARGET) */ - trb_fields[2] = (8 | ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); - /* Immediate data in pointer */ - trb_fields[3] = field; - queue_trb(ctrl, ep_ring, true, trb_fields); - - /* Re-initializing field to zero */ - field = 0; - /* If there's data, queue data TRBs */ - /* Only set interrupt on short packet for IN endpoints */ - if (usb_pipein(pipe)) - field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT); - else - field = (TRB_DATA << TRB_TYPE_SHIFT); - - length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) | - ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); - debug("length_field = %d, length = %d," - "xhci_td_remainder(length) = %d , TRB_INTR_TARGET(0) = %d\n", - length_field, (length & TRB_LEN_MASK), - xhci_td_remainder(length), 0); - - if (length > 0) { - if (req->requesttype & USB_DIR_IN) - field |= TRB_DIR_IN; - buf_64 = (uintptr_t)buffer; - - trb_fields[0] = lower_32_bits(buf_64); - trb_fields[1] = upper_32_bits(buf_64); - trb_fields[2] = length_field; - trb_fields[3] = field | ep_ring->cycle_state; - - xhci_flush_cache((uint32_t)buffer, length); - queue_trb(ctrl, ep_ring, true, trb_fields); - } - - /* - * Queue status TRB - - * see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 - */ - - /* If the device sent data, the status stage is an OUT transfer */ - field = 0; - if (length > 0 && req->requesttype & USB_DIR_IN) - field = 0; - else - field = TRB_DIR_IN; - - trb_fields[0] = 0; - trb_fields[1] = 0; - trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); - /* Event on completion */ - trb_fields[3] = field | TRB_IOC | - (TRB_STATUS << TRB_TYPE_SHIFT) | - ep_ring->cycle_state; - - queue_trb(ctrl, ep_ring, false, trb_fields); - - giveback_first_trb(udev, ep_index, start_cycle, start_trb); - - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) - goto abort; - field = le32_to_cpu(event->trans_event.flags); - - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - - record_transfer_result(udev, event, length); - xhci_acknowledge_event(ctrl); - - /* Invalidate buffer to make it available to usb-core */ - if (length > 0) - xhci_inval_cache((uint32_t)buffer, length); - - if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)) - == COMP_SHORT_TX) { - /* Short data stage, clear up additional status stage event */ - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - if (!event) - goto abort; - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - xhci_acknowledge_event(ctrl); - } - - return (udev->status != USB_ST_NOT_PROC) ? 0 : -1; - -abort: - debug("XHCI control transfer timed out, aborting...\n"); - abort_td(udev, ep_index); - udev->status = USB_ST_NAK_REC; - udev->act_len = 0; - return -ETIMEDOUT; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci.c b/qemu/roms/u-boot/drivers/usb/host/xhci.c deleted file mode 100644 index d1c2e5c45..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * USB HOST XHCI Controller stack - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/** - * This file gives the xhci stack for usb3.0 looking into - * xhci specification Rev1.0 (5/21/10). - * The quirk devices support hasn't been given yet. - */ - -#include <common.h> -#include <asm/byteorder.h> -#include <usb.h> -#include <malloc.h> -#include <watchdog.h> -#include <asm/cache.h> -#include <asm/unaligned.h> -#include <asm-generic/errno.h> -#include "xhci.h" - -#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#endif - -static struct descriptor { - struct usb_hub_descriptor hub; - struct usb_device_descriptor device; - struct usb_config_descriptor config; - struct usb_interface_descriptor interface; - struct usb_endpoint_descriptor endpoint; - struct usb_ss_ep_comp_descriptor ep_companion; -} __attribute__ ((packed)) descriptor = { - { - 0xc, /* bDescLength */ - 0x2a, /* bDescriptorType: hub descriptor */ - 2, /* bNrPorts -- runtime modified */ - cpu_to_le16(0x8), /* wHubCharacteristics */ - 10, /* bPwrOn2PwrGood */ - 0, /* bHubCntrCurrent */ - {}, /* Device removable */ - {} /* at most 7 ports! XXX */ - }, - { - 0x12, /* bLength */ - 1, /* bDescriptorType: UDESC_DEVICE */ - cpu_to_le16(0x0300), /* bcdUSB: v3.0 */ - 9, /* bDeviceClass: UDCLASS_HUB */ - 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ - 3, /* bDeviceProtocol: UDPROTO_SSHUBSTT */ - 9, /* bMaxPacketSize: 512 bytes 2^9 */ - 0x0000, /* idVendor */ - 0x0000, /* idProduct */ - cpu_to_le16(0x0100), /* bcdDevice */ - 1, /* iManufacturer */ - 2, /* iProduct */ - 0, /* iSerialNumber */ - 1 /* bNumConfigurations: 1 */ - }, - { - 0x9, - 2, /* bDescriptorType: UDESC_CONFIG */ - cpu_to_le16(0x1f), /* includes SS endpoint descriptor */ - 1, /* bNumInterface */ - 1, /* bConfigurationValue */ - 0, /* iConfiguration */ - 0x40, /* bmAttributes: UC_SELF_POWER */ - 0 /* bMaxPower */ - }, - { - 0x9, /* bLength */ - 4, /* bDescriptorType: UDESC_INTERFACE */ - 0, /* bInterfaceNumber */ - 0, /* bAlternateSetting */ - 1, /* bNumEndpoints */ - 9, /* bInterfaceClass: UICLASS_HUB */ - 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ - 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ - 0 /* iInterface */ - }, - { - 0x7, /* bLength */ - 5, /* bDescriptorType: UDESC_ENDPOINT */ - 0x81, /* bEndpointAddress: IN endpoint 1 */ - 3, /* bmAttributes: UE_INTERRUPT */ - 8, /* wMaxPacketSize */ - 255 /* bInterval */ - }, - { - 0x06, /* ss_bLength */ - 0x30, /* ss_bDescriptorType: SS EP Companion */ - 0x00, /* ss_bMaxBurst: allows 1 TX between ACKs */ - /* ss_bmAttributes: 1 packet per service interval */ - 0x00, - /* ss_wBytesPerInterval: 15 bits for max 15 ports */ - cpu_to_le16(0x02), - }, -}; - -static struct xhci_ctrl xhcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; - -/** - * Waits for as per specified amount of time - * for the "result" to match with "done" - * - * @param ptr pointer to the register to be read - * @param mask mask for the value read - * @param done value to be campared with result - * @param usec time to wait till - * @return 0 if handshake is success else < 0 on failure - */ -static int handshake(uint32_t volatile *ptr, uint32_t mask, - uint32_t done, int usec) -{ - uint32_t result; - - do { - result = xhci_readl(ptr); - if (result == ~(uint32_t)0) - return -ENODEV; - result &= mask; - if (result == done) - return 0; - usec--; - udelay(1); - } while (usec > 0); - - return -ETIMEDOUT; -} - -/** - * Set the run bit and wait for the host to be running. - * - * @param hcor pointer to host controller operation registers - * @return status of the Handshake - */ -static int xhci_start(struct xhci_hcor *hcor) -{ - u32 temp; - int ret; - - puts("Starting the controller\n"); - temp = xhci_readl(&hcor->or_usbcmd); - temp |= (CMD_RUN); - xhci_writel(&hcor->or_usbcmd, temp); - - /* - * Wait for the HCHalted Status bit to be 0 to indicate the host is - * running. - */ - ret = handshake(&hcor->or_usbsts, STS_HALT, 0, XHCI_MAX_HALT_USEC); - if (ret) - debug("Host took too long to start, " - "waited %u microseconds.\n", - XHCI_MAX_HALT_USEC); - return ret; -} - -/** - * Resets the XHCI Controller - * - * @param hcor pointer to host controller operation registers - * @return -EBUSY if XHCI Controller is not halted else status of handshake - */ -int xhci_reset(struct xhci_hcor *hcor) -{ - u32 cmd; - u32 state; - int ret; - - /* Halting the Host first */ - debug("// Halt the HC\n"); - state = xhci_readl(&hcor->or_usbsts) & STS_HALT; - if (!state) { - cmd = xhci_readl(&hcor->or_usbcmd); - cmd &= ~CMD_RUN; - xhci_writel(&hcor->or_usbcmd, cmd); - } - - ret = handshake(&hcor->or_usbsts, - STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (ret) { - printf("Host not halted after %u microseconds.\n", - XHCI_MAX_HALT_USEC); - return -EBUSY; - } - - debug("// Reset the HC\n"); - cmd = xhci_readl(&hcor->or_usbcmd); - cmd |= CMD_RESET; - xhci_writel(&hcor->or_usbcmd, cmd); - - ret = handshake(&hcor->or_usbcmd, CMD_RESET, 0, XHCI_MAX_RESET_USEC); - if (ret) - return ret; - - /* - * xHCI cannot write to any doorbells or operational registers other - * than status until the "Controller Not Ready" flag is cleared. - */ - return handshake(&hcor->or_usbsts, STS_CNR, 0, XHCI_MAX_RESET_USEC); -} - -/** - * Used for passing endpoint bitmasks between the core and HCDs. - * Find the index for an endpoint given its descriptor. - * Use the return value to right shift 1 for the bitmask. - * - * Index = (epnum * 2) + direction - 1, - * where direction = 0 for OUT, 1 for IN. - * For control endpoints, the IN index is used (OUT index is unused), so - * index = (epnum * 2) + direction - 1 = (epnum * 2) + 1 - 1 = (epnum * 2) - * - * @param desc USB enpdoint Descriptor - * @return index of the Endpoint - */ -static unsigned int xhci_get_ep_index(struct usb_endpoint_descriptor *desc) -{ - unsigned int index; - - if (usb_endpoint_xfer_control(desc)) - index = (unsigned int)(usb_endpoint_num(desc) * 2); - else - index = (unsigned int)((usb_endpoint_num(desc) * 2) - - (usb_endpoint_dir_in(desc) ? 0 : 1)); - - return index; -} - -/** - * Issue a configure endpoint command or evaluate context command - * and wait for it to finish. - * - * @param udev pointer to the Device Data Structure - * @param ctx_change flag to indicate the Context has changed or NOT - * @return 0 on success, -1 on failure - */ -static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_virt_device *virt_dev; - struct xhci_ctrl *ctrl = udev->controller; - union xhci_trb *event; - - virt_dev = ctrl->devs[udev->slot_id]; - in_ctx = virt_dev->in_ctx; - - xhci_flush_cache((uint32_t)in_ctx->bytes, in_ctx->size); - xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0, - ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id); - - switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { - case COMP_SUCCESS: - debug("Successful %s command\n", - ctx_change ? "Evaluate Context" : "Configure Endpoint"); - break; - default: - printf("ERROR: %s command returned completion code %d.\n", - ctx_change ? "Evaluate Context" : "Configure Endpoint", - GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))); - return -EINVAL; - } - - xhci_acknowledge_event(ctrl); - - return 0; -} - -/** - * Configure the endpoint, programming the device contexts. - * - * @param udev pointer to the USB device structure - * @return returns the status of the xhci_configure_endpoints - */ -static int xhci_set_configuration(struct usb_device *udev) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; - struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; - int cur_ep; - int max_ep_flag = 0; - int ep_index; - unsigned int dir; - unsigned int ep_type; - struct xhci_ctrl *ctrl = udev->controller; - int num_of_ep; - int ep_flag = 0; - u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; - - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = &udev->config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Zero the input context control */ - ctrl_ctx->add_flags = 0; - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(LAST_CTX_MASK); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - struct usb_endpoint_descriptor *endpt_desc = NULL; - - endpt_desc = &ifdesc->ep_desc[cur_ep]; - trb_64 = 0; - - ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - - /* Allocate the ep rings */ - virt_dev->eps[ep_index].ring = xhci_ring_alloc(1, true); - if (!virt_dev->eps[ep_index].ring) - return -ENOMEM; - - /*NOTE: ep_desc[0] actually represents EP1 and so on */ - dir = (((endpt_desc->bEndpointAddress) & (0x80)) >> 7); - ep_type = (((endpt_desc->bmAttributes) & (0x3)) | (dir << 2)); - ep_ctx[ep_index]->ep_info2 = - cpu_to_le32(ep_type << EP_TYPE_SHIFT); - ep_ctx[ep_index]->ep_info2 |= - cpu_to_le32(MAX_PACKET - (get_unaligned(&endpt_desc->wMaxPacketSize))); - - ep_ctx[ep_index]->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); - - trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; - ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | - virt_dev->eps[ep_index].ring->cycle_state); - } - - return xhci_configure_endpoints(udev, false); -} - -/** - * Issue an Address Device command (which will issue a SetAddress request to - * the device). - * - * @param udev pointer to the Device Data Structure - * @return 0 if successful else error code on failure - */ -static int xhci_address_device(struct usb_device *udev) -{ - int ret = 0; - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_slot_ctx *slot_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_virt_device *virt_dev; - int slot_id = udev->slot_id; - union xhci_trb *event; - - virt_dev = ctrl->devs[slot_id]; - - /* - * This is the first Set Address since device plug-in - * so setting up the slot context. - */ - debug("Setting up addressable devices\n"); - xhci_setup_addressable_virt_dev(udev); - - ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); - ctrl_ctx->drop_flags = 0; - - xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id); - - switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { - case COMP_CTX_STATE: - case COMP_EBADSLT: - printf("Setup ERROR: address device command for slot %d.\n", - slot_id); - ret = -EINVAL; - break; - case COMP_TX_ERR: - puts("Device not responding to set address.\n"); - ret = -EPROTO; - break; - case COMP_DEV_ERR: - puts("ERROR: Incompatible device" - "for address device command.\n"); - ret = -ENODEV; - break; - case COMP_SUCCESS: - debug("Successful Address Device command\n"); - udev->status = 0; - break; - default: - printf("ERROR: unexpected command completion code 0x%x.\n", - GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))); - ret = -EINVAL; - break; - } - - xhci_acknowledge_event(ctrl); - - if (ret < 0) - /* - * TODO: Unsuccessful Address Device command shall leave the - * slot in default state. So, issue Disable Slot command now. - */ - return ret; - - xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes, - virt_dev->out_ctx->size); - slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->out_ctx); - - debug("xHC internal address is: %d\n", - le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK); - - return 0; -} - -/** - * Issue Enable slot command to the controller to allocate - * device slot and assign the slot id. It fails if the xHC - * ran out of device slots, the Enable Slot command timed out, - * or allocating memory failed. - * - * @param udev pointer to the Device Data Structure - * @return Returns 0 on succes else return error code on failure - */ -int usb_alloc_device(struct usb_device *udev) -{ - union xhci_trb *event; - struct xhci_ctrl *ctrl = udev->controller; - int ret; - - /* - * Root hub will be first device to be initailized. - * If this device is root-hub, don't do any xHC related - * stuff. - */ - if (ctrl->rootdev == 0) { - udev->speed = USB_SPEED_SUPER; - return 0; - } - - xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)) - != COMP_SUCCESS); - - udev->slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)); - - xhci_acknowledge_event(ctrl); - - ret = xhci_alloc_virt_device(udev); - if (ret < 0) { - /* - * TODO: Unsuccessful Address Device command shall leave - * the slot in default. So, issue Disable Slot command now. - */ - puts("Could not allocate xHCI USB device data structures\n"); - return ret; - } - - return 0; -} - -/* - * Full speed devices may have a max packet size greater than 8 bytes, but the - * USB core doesn't know that until it reads the first 8 bytes of the - * descriptor. If the usb_device's max packet size changes after that point, - * we need to issue an evaluate context command and wait on it. - * - * @param udev pointer to the Device Data Structure - * @return returns the status of the xhci_configure_endpoints - */ -int xhci_check_maxpacket(struct usb_device *udev) -{ - struct xhci_ctrl *ctrl = udev->controller; - unsigned int slot_id = udev->slot_id; - int ep_index = 0; /* control endpoint */ - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_ep_ctx *ep_ctx; - int max_packet_size; - int hw_max_packet_size; - int ret = 0; - struct usb_interface *ifdesc; - - ifdesc = &udev->config.if_desc[0]; - - out_ctx = ctrl->devs[slot_id]->out_ctx; - xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size); - - ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index); - hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); - max_packet_size = usb_endpoint_maxp(&ifdesc->ep_desc[0]); - if (hw_max_packet_size != max_packet_size) { - debug("Max Packet Size for ep 0 changed.\n"); - debug("Max packet size in usb_device = %d\n", max_packet_size); - debug("Max packet size in xHCI HW = %d\n", hw_max_packet_size); - debug("Issuing evaluate context command.\n"); - - /* Set up the modified control endpoint 0 */ - xhci_endpoint_copy(ctrl, ctrl->devs[slot_id]->in_ctx, - ctrl->devs[slot_id]->out_ctx, ep_index); - in_ctx = ctrl->devs[slot_id]->in_ctx; - ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); - - /* - * Set up the input context flags for the command - * FIXME: This won't work if a non-default control endpoint - * changes max packet sizes. - */ - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); - ctrl_ctx->drop_flags = 0; - - ret = xhci_configure_endpoints(udev, true); - } - return ret; -} - -/** - * Clears the Change bits of the Port Status Register - * - * @param wValue request value - * @param wIndex request index - * @param addr address of posrt status register - * @param port_status state of port status register - * @return none - */ -static void xhci_clear_port_change_bit(u16 wValue, - u16 wIndex, volatile uint32_t *addr, u32 port_status) -{ - char *port_change_bit; - u32 status; - - switch (wValue) { - case USB_PORT_FEAT_C_RESET: - status = PORT_RC; - port_change_bit = "reset"; - break; - case USB_PORT_FEAT_C_CONNECTION: - status = PORT_CSC; - port_change_bit = "connect"; - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - status = PORT_OCC; - port_change_bit = "over-current"; - break; - case USB_PORT_FEAT_C_ENABLE: - status = PORT_PEC; - port_change_bit = "enable/disable"; - break; - case USB_PORT_FEAT_C_SUSPEND: - status = PORT_PLC; - port_change_bit = "suspend/resume"; - break; - default: - /* Should never happen */ - return; - } - - /* Change bits are all write 1 to clear */ - xhci_writel(addr, port_status | status); - - port_status = xhci_readl(addr); - debug("clear port %s change, actual port %d status = 0x%x\n", - port_change_bit, wIndex, port_status); -} - -/** - * Save Read Only (RO) bits and save read/write bits where - * writing a 0 clears the bit and writing a 1 sets the bit (RWS). - * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect. - * - * @param state state of the Port Status and Control Regsiter - * @return a value that would result in the port being in the - * same state, if the value was written to the port - * status control register. - */ -static u32 xhci_port_state_to_neutral(u32 state) -{ - /* Save read-only status and port state */ - return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); -} - -/** - * Submits the Requests to the XHCI Host Controller - * - * @param udev pointer to the USB device structure - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @return returns 0 if successful else -1 on failure - */ -static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, - void *buffer, struct devrequest *req) -{ - uint8_t tmpbuf[4]; - u16 typeReq; - void *srcptr = NULL; - int len, srclen; - uint32_t reg; - volatile uint32_t *status_reg; - struct xhci_ctrl *ctrl = udev->controller; - struct xhci_hcor *hcor = ctrl->hcor; - - if (((req->requesttype & USB_RT_PORT) && - le16_to_cpu(req->index)) > CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); - return -EINVAL; - } - - status_reg = (volatile uint32_t *) - (&hcor->portregs[le16_to_cpu(req->index) - 1].or_portsc); - srclen = 0; - - typeReq = req->request | req->requesttype << 8; - - switch (typeReq) { - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_DEVICE: - debug("USB_DT_DEVICE request\n"); - srcptr = &descriptor.device; - srclen = 0x12; - break; - case USB_DT_CONFIG: - debug("USB_DT_CONFIG config\n"); - srcptr = &descriptor.config; - srclen = 0x19; - break; - case USB_DT_STRING: - debug("USB_DT_STRING config\n"); - switch (le16_to_cpu(req->value) & 0xff) { - case 0: /* Language */ - srcptr = "\4\3\11\4"; - srclen = 4; - break; - case 1: /* Vendor String */ - srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; - srclen = 14; - break; - case 2: /* Product Name */ - srcptr = "\52\3X\0H\0C\0I\0 " - "\0H\0o\0s\0t\0 " - "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; - srclen = 42; - break; - default: - printf("unknown value DT_STRING %x\n", - le16_to_cpu(req->value)); - goto unknown; - } - break; - default: - printf("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): - switch (le16_to_cpu(req->value) >> 8) { - case USB_DT_HUB: - debug("USB_DT_HUB config\n"); - srcptr = &descriptor.hub; - srclen = 0x8; - break; - default: - printf("unknown value %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): - debug("USB_REQ_SET_ADDRESS\n"); - ctrl->rootdev = le16_to_cpu(req->value); - break; - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - /* Do nothing */ - break; - case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): - tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ - tmpbuf[1] = 0; - srcptr = tmpbuf; - srclen = 2; - break; - case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): - memset(tmpbuf, 0, 4); - reg = xhci_readl(status_reg); - if (reg & PORT_CONNECT) { - tmpbuf[0] |= USB_PORT_STAT_CONNECTION; - switch (reg & DEV_SPEED_MASK) { - case XDEV_FS: - debug("SPEED = FULLSPEED\n"); - break; - case XDEV_LS: - debug("SPEED = LOWSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case XDEV_HS: - debug("SPEED = HIGHSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - case XDEV_SS: - debug("SPEED = SUPERSPEED\n"); - tmpbuf[1] |= USB_PORT_STAT_SUPER_SPEED >> 8; - break; - } - } - if (reg & PORT_PE) - tmpbuf[0] |= USB_PORT_STAT_ENABLE; - if ((reg & PORT_PLS_MASK) == XDEV_U3) - tmpbuf[0] |= USB_PORT_STAT_SUSPEND; - if (reg & PORT_OC) - tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; - if (reg & PORT_RESET) - tmpbuf[0] |= USB_PORT_STAT_RESET; - if (reg & PORT_POWER) - /* - * XXX: This Port power bit (for USB 3.0 hub) - * we are faking in USB 2.0 hub port status; - * since there's a change in bit positions in - * two: - * USB 2.0 port status PP is at position[8] - * USB 3.0 port status PP is at position[9] - * So, we are still keeping it at position [8] - */ - tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - if (reg & PORT_CSC) - tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; - if (reg & PORT_PEC) - tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; - if (reg & PORT_OCC) - tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; - if (reg & PORT_RC) - tmpbuf[2] |= USB_PORT_STAT_C_RESET; - - srcptr = tmpbuf; - srclen = 4; - break; - case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = xhci_readl(status_reg); - reg = xhci_port_state_to_neutral(reg); - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg |= PORT_PE; - xhci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_POWER: - reg |= PORT_POWER; - xhci_writel(status_reg, reg); - break; - case USB_PORT_FEAT_RESET: - reg |= PORT_RESET; - xhci_writel(status_reg, reg); - break; - default: - printf("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - break; - case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): - reg = xhci_readl(status_reg); - reg = xhci_port_state_to_neutral(reg); - switch (le16_to_cpu(req->value)) { - case USB_PORT_FEAT_ENABLE: - reg &= ~PORT_PE; - break; - case USB_PORT_FEAT_POWER: - reg &= ~PORT_POWER; - break; - case USB_PORT_FEAT_C_RESET: - case USB_PORT_FEAT_C_CONNECTION: - case USB_PORT_FEAT_C_OVER_CURRENT: - case USB_PORT_FEAT_C_ENABLE: - xhci_clear_port_change_bit((le16_to_cpu(req->value)), - le16_to_cpu(req->index), - status_reg, reg); - break; - default: - printf("unknown feature %x\n", le16_to_cpu(req->value)); - goto unknown; - } - xhci_writel(status_reg, reg); - break; - default: - puts("Unknown request\n"); - goto unknown; - } - - debug("scrlen = %d\n req->length = %d\n", - srclen, le16_to_cpu(req->length)); - - len = min(srclen, le16_to_cpu(req->length)); - - if (srcptr != NULL && len > 0) - memcpy(buffer, srcptr, len); - else - debug("Len is 0\n"); - - udev->act_len = len; - udev->status = 0; - - return 0; - -unknown: - udev->act_len = 0; - udev->status = USB_ST_STALLED; - - return -ENODEV; -} - -/** - * Submits the INT request to XHCI Host cotroller - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @param interval interval of the interrupt - * @return 0 - */ -int -submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, int interval) -{ - /* - * TODO: Not addressing any interrupt type transfer requests - * Add support for it later. - */ - return -EINVAL; -} - -/** - * submit the BULK type of request to the USB Device - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @return returns 0 if successful else -1 on failure - */ -int -submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length) -{ - if (usb_pipetype(pipe) != PIPE_BULK) { - printf("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); - return -EINVAL; - } - - return xhci_bulk_tx(udev, pipe, length, buffer); -} - -/** - * submit the control type of request to the Root hub/Device based on the devnum - * - * @param udev pointer to the USB device - * @param pipe contains the DIR_IN or OUT , devnum - * @param buffer buffer to be read/written based on the request - * @param length length of the buffer - * @param setup Request type - * @return returns 0 if successful else -1 on failure - */ -int -submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) -{ - struct xhci_ctrl *ctrl = udev->controller; - int ret = 0; - - if (usb_pipetype(pipe) != PIPE_CONTROL) { - printf("non-control pipe (type=%lu)", usb_pipetype(pipe)); - return -EINVAL; - } - - if (usb_pipedevice(pipe) == ctrl->rootdev) - return xhci_submit_root(udev, pipe, buffer, setup); - - if (setup->request == USB_REQ_SET_ADDRESS) - return xhci_address_device(udev); - - if (setup->request == USB_REQ_SET_CONFIGURATION) { - ret = xhci_set_configuration(udev); - if (ret) { - puts("Failed to configure xHCI endpoint\n"); - return ret; - } - } - - return xhci_ctrl_tx(udev, pipe, setup, length, buffer); -} - -/** - * Intialises the XHCI host controller - * and allocates the necessary data structures - * - * @param index index to the host controller data structure - * @return pointer to the intialised controller - */ -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) -{ - uint32_t val; - uint32_t val2; - uint32_t reg; - struct xhci_hccr *hccr; - struct xhci_hcor *hcor; - struct xhci_ctrl *ctrl; - - if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0) - return -ENODEV; - - if (xhci_reset(hcor) != 0) - return -ENODEV; - - ctrl = &xhcic[index]; - - ctrl->hccr = hccr; - ctrl->hcor = hcor; - - /* - * Program the Number of Device Slots Enabled field in the CONFIG - * register with the max value of slots the HC can handle. - */ - val = (xhci_readl(&hccr->cr_hcsparams1) & HCS_SLOTS_MASK); - val2 = xhci_readl(&hcor->or_config); - val |= (val2 & ~HCS_SLOTS_MASK); - xhci_writel(&hcor->or_config, val); - - /* initializing xhci data structures */ - if (xhci_mem_init(ctrl, hccr, hcor) < 0) - return -ENOMEM; - - reg = xhci_readl(&hccr->cr_hcsparams1); - descriptor.hub.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> - HCS_MAX_PORTS_SHIFT); - printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); - - /* Port Indicators */ - reg = xhci_readl(&hccr->cr_hccparams); - if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); - - /* Port Power Control */ - if (HCC_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); - - if (xhci_start(hcor)) { - xhci_reset(hcor); - return -ENODEV; - } - - /* Zero'ing IRQ control register and IRQ pending register */ - xhci_writel(&ctrl->ir_set->irq_control, 0x0); - xhci_writel(&ctrl->ir_set->irq_pending, 0x0); - - reg = HC_VERSION(xhci_readl(&hccr->cr_capbase)); - printf("USB XHCI %x.%02x\n", reg >> 8, reg & 0xff); - - *controller = &xhcic[index]; - - return 0; -} - -/** - * Stops the XHCI host controller - * and cleans up all the related data structures - * - * @param index index to the host controller data structure - * @return none - */ -int usb_lowlevel_stop(int index) -{ - struct xhci_ctrl *ctrl = (xhcic + index); - u32 temp; - - xhci_reset(ctrl->hcor); - - debug("// Disabling event ring interrupts\n"); - temp = xhci_readl(&ctrl->hcor->or_usbsts); - xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT); - temp = xhci_readl(&ctrl->ir_set->irq_pending); - xhci_writel(&ctrl->ir_set->irq_pending, ER_IRQ_DISABLE(temp)); - - xhci_hcd_stop(index); - - xhci_cleanup(ctrl); - - return 0; -} diff --git a/qemu/roms/u-boot/drivers/usb/host/xhci.h b/qemu/roms/u-boot/drivers/usb/host/xhci.h deleted file mode 100644 index ceb1573d8..000000000 --- a/qemu/roms/u-boot/drivers/usb/host/xhci.h +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * USB HOST XHCI Controller - * - * Based on xHCI host controller driver in linux-kernel - * by Sarah Sharp. - * - * Copyright (C) 2008 Intel Corp. - * Author: Sarah Sharp - * - * Copyright (C) 2013 Samsung Electronics Co.Ltd - * Authors: Vivek Gautam <gautam.vivek@samsung.com> - * Vikas Sajjan <vikas.sajjan@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef HOST_XHCI_H_ -#define HOST_XHCI_H_ - -#include <asm/cache.h> -#include <asm/io.h> -#include <linux/list.h> - -#define upper_32_bits(n) (u32)((n) >> 32) -#define lower_32_bits(n) (u32)(n) - -#define MAX_EP_CTX_NUM 31 -#define XHCI_ALIGNMENT 64 -/* Generic timeout for XHCI events */ -#define XHCI_TIMEOUT 5000 -/* Max number of USB devices for any host controller - limit in section 6.1 */ -#define MAX_HC_SLOTS 256 -/* Section 5.3.3 - MaxPorts */ -#define MAX_HC_PORTS 127 - -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) - -#define XHCI_MAX_RESET_USEC (250*1000) - -/* - * These bits are Read Only (RO) and should be saved and written to the - * registers: 0, 3, 10:13, 30 - * connect status, over-current status, port speed, and device removable. - * connect status and port speed are also sticky - meaning they're in - * the AUX well and they aren't changed by a hot, warm, or cold reset. - */ -#define XHCI_PORT_RO ((1 << 0) | (1 << 3) | (0xf << 10) | (1 << 30)) -/* - * These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit: - * bits 5:8, 9, 14:15, 25:27 - * link state, port power, port indicator state, "wake on" enable state - */ -#define XHCI_PORT_RWS ((0xf << 5) | (1 << 9) | (0x3 << 14) | (0x7 << 25)) -/* - * These bits are RW; writing a 1 sets the bit, writing a 0 has no effect: - * bit 4 (port reset) - */ -#define XHCI_PORT_RW1S ((1 << 4)) -/* - * These bits are RW; writing a 1 clears the bit, writing a 0 has no effect: - * bits 1, 17, 18, 19, 20, 21, 22, 23 - * port enable/disable, and - * change bits: connect, PED, - * warm port reset changed (reserved zero for USB 2.0 ports), - * over-current, reset, link state, and L1 change - */ -#define XHCI_PORT_RW1CS ((1 << 1) | (0x7f << 17)) -/* - * Bit 16 is RW, and writing a '1' to it causes the link state control to be - * latched in - */ -#define XHCI_PORT_RW ((1 << 16)) -/* - * These bits are Reserved Zero (RsvdZ) and zero should be written to them: - * bits 2, 24, 28:31 - */ -#define XHCI_PORT_RZ ((1 << 2) | (1 << 24) | (0xf << 28)) - -/* - * XHCI Register Space. - */ -struct xhci_hccr { - uint32_t cr_capbase; - uint32_t cr_hcsparams1; - uint32_t cr_hcsparams2; - uint32_t cr_hcsparams3; - uint32_t cr_hccparams; - uint32_t cr_dboff; - uint32_t cr_rtsoff; - -/* hc_capbase bitmasks */ -/* bits 7:0 - how long is the Capabilities register */ -#define HC_LENGTH(p) XHCI_HC_LENGTH(p) -/* bits 31:16 */ -#define HC_VERSION(p) (((p) >> 16) & 0xffff) - -/* HCSPARAMS1 - hcs_params1 - bitmasks */ -/* bits 0:7, Max Device Slots */ -#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff) -#define HCS_SLOTS_MASK 0xff -/* bits 8:18, Max Interrupters */ -#define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff) -/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */ -#define HCS_MAX_PORTS_SHIFT 24 -#define HCS_MAX_PORTS_MASK (0x7f << HCS_MAX_PORTS_SHIFT) -#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) - -/* HCSPARAMS2 - hcs_params2 - bitmasks */ -/* bits 0:3, frames or uframes that SW needs to queue transactions - * ahead of the HW to meet periodic deadlines */ -#define HCS_IST(p) (((p) >> 0) & 0xf) -/* bits 4:7, max number of Event Ring segments */ -#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) -/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ -/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ -#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) - -/* HCSPARAMS3 - hcs_params3 - bitmasks */ -/* bits 0:7, Max U1 to U0 latency for the roothub ports */ -#define HCS_U1_LATENCY(p) (((p) >> 0) & 0xff) -/* bits 16:31, Max U2 to U0 latency for the roothub ports */ -#define HCS_U2_LATENCY(p) (((p) >> 16) & 0xffff) - -/* HCCPARAMS - hcc_params - bitmasks */ -/* true: HC can use 64-bit address pointers */ -#define HCC_64BIT_ADDR(p) ((p) & (1 << 0)) -/* true: HC can do bandwidth negotiation */ -#define HCC_BANDWIDTH_NEG(p) ((p) & (1 << 1)) -/* true: HC uses 64-byte Device Context structures - * FIXME 64-byte context structures aren't supported yet. - */ -#define HCC_64BYTE_CONTEXT(p) ((p) & (1 << 2)) -/* true: HC has port power switches */ -#define HCC_PPC(p) ((p) & (1 << 3)) -/* true: HC has port indicators */ -#define HCS_INDICATOR(p) ((p) & (1 << 4)) -/* true: HC has Light HC Reset Capability */ -#define HCC_LIGHT_RESET(p) ((p) & (1 << 5)) -/* true: HC supports latency tolerance messaging */ -#define HCC_LTC(p) ((p) & (1 << 6)) -/* true: no secondary Stream ID Support */ -#define HCC_NSS(p) ((p) & (1 << 7)) -/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */ -#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1)) -/* Extended Capabilities pointer from PCI base - section 5.3.6 */ -#define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p) - -/* db_off bitmask - bits 0:1 reserved */ -#define DBOFF_MASK (~0x3) - -/* run_regs_off bitmask - bits 0:4 reserved */ -#define RTSOFF_MASK (~0x1f) - -}; - -struct xhci_hcor_port_regs { - volatile uint32_t or_portsc; - volatile uint32_t or_portpmsc; - volatile uint32_t or_portli; - volatile uint32_t reserved_3; -}; - -struct xhci_hcor { - volatile uint32_t or_usbcmd; - volatile uint32_t or_usbsts; - volatile uint32_t or_pagesize; - volatile uint32_t reserved_0[2]; - volatile uint32_t or_dnctrl; - volatile uint64_t or_crcr; - volatile uint32_t reserved_1[4]; - volatile uint64_t or_dcbaap; - volatile uint32_t or_config; - volatile uint32_t reserved_2[241]; - struct xhci_hcor_port_regs portregs[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS]; - - uint32_t reserved_4[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS * 254]; -}; - -/* USBCMD - USB command - command bitmasks */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define CMD_RUN XHCI_CMD_RUN -/* Reset HC - resets internal HC state machine and all registers (except - * PCI config regs). HC does NOT drive a USB reset on the downstream ports. - * The xHCI driver must reinitialize the xHC after setting this bit. - */ -#define CMD_RESET (1 << 1) -/* Event Interrupt Enable - a '1' allows interrupts from the host controller */ -#define CMD_EIE XHCI_CMD_EIE -/* Host System Error Interrupt Enable - get out-of-band signal for HC errors */ -#define CMD_HSEIE XHCI_CMD_HSEIE -/* bits 4:6 are reserved (and should be preserved on writes). */ -/* light reset (port status stays unchanged) - reset completed when this is 0 */ -#define CMD_LRESET (1 << 7) -/* host controller save/restore state. */ -#define CMD_CSS (1 << 8) -#define CMD_CRS (1 << 9) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define CMD_EWE XHCI_CMD_EWE -/* MFINDEX power management - '1' means xHC can stop MFINDEX counter if all root - * hubs are in U3 (selective suspend), disconnect, disabled, or powered-off. - * '0' means the xHC can power it off if all ports are in the disconnect, - * disabled, or powered-off state. - */ -#define CMD_PM_INDEX (1 << 11) -/* bits 12:31 are reserved (and should be preserved on writes). */ - -/* USBSTS - USB status - status bitmasks */ -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define STS_HALT XHCI_STS_HALT -/* serious error, e.g. PCI parity error. The HC will clear the run/stop bit. */ -#define STS_FATAL (1 << 2) -/* event interrupt - clear this prior to clearing any IP flags in IR set*/ -#define STS_EINT (1 << 3) -/* port change detect */ -#define STS_PORT (1 << 4) -/* bits 5:7 reserved and zeroed */ -/* save state status - '1' means xHC is saving state */ -#define STS_SAVE (1 << 8) -/* restore state status - '1' means xHC is restoring state */ -#define STS_RESTORE (1 << 9) -/* true: save or restore error */ -#define STS_SRE (1 << 10) -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define STS_CNR XHCI_STS_CNR -/* true: internal Host Controller Error - SW needs to reset and reinitialize */ -#define STS_HCE (1 << 12) -/* bits 13:31 reserved and should be preserved */ - -/* - * DNCTRL - Device Notification Control Register - dev_notification bitmasks - * Generate a device notification event when the HC sees a transaction with a - * notification type that matches a bit set in this bit field. - */ -#define DEV_NOTE_MASK (0xffff) -#define ENABLE_DEV_NOTE(x) (1 << (x)) -/* Most of the device notification types should only be used for debug. - * SW does need to pay attention to function wake notifications. - */ -#define DEV_NOTE_FWAKE ENABLE_DEV_NOTE(1) - -/* CRCR - Command Ring Control Register - cmd_ring bitmasks */ -/* bit 0 is the command ring cycle state */ -/* stop ring operation after completion of the currently executing command */ -#define CMD_RING_PAUSE (1 << 1) -/* stop ring immediately - abort the currently executing command */ -#define CMD_RING_ABORT (1 << 2) -/* true: command ring is running */ -#define CMD_RING_RUNNING (1 << 3) -/* bits 4:5 reserved and should be preserved */ -/* Command Ring pointer - bit mask for the lower 32 bits. */ -#define CMD_RING_RSVD_BITS (0x3f) - -/* CONFIG - Configure Register - config_reg bitmasks */ -/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ -#define MAX_DEVS(p) ((p) & 0xff) -/* bits 8:31 - reserved and should be preserved */ - -/* PORTSC - Port Status and Control Register - port_status_base bitmasks */ -/* true: device connected */ -#define PORT_CONNECT (1 << 0) -/* true: port enabled */ -#define PORT_PE (1 << 1) -/* bit 2 reserved and zeroed */ -/* true: port has an over-current condition */ -#define PORT_OC (1 << 3) -/* true: port reset signaling asserted */ -#define PORT_RESET (1 << 4) -/* Port Link State - bits 5:8 - * A read gives the current link PM state of the port, - * a write with Link State Write Strobe set sets the link state. - */ -#define PORT_PLS_MASK (0xf << 5) -#define XDEV_U0 (0x0 << 5) -#define XDEV_U2 (0x2 << 5) -#define XDEV_U3 (0x3 << 5) -#define XDEV_RESUME (0xf << 5) -/* true: port has power (see HCC_PPC) */ -#define PORT_POWER (1 << 9) -/* bits 10:13 indicate device speed: - * 0 - undefined speed - port hasn't be initialized by a reset yet - * 1 - full speed - * 2 - low speed - * 3 - high speed - * 4 - super speed - * 5-15 reserved - */ -#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) == 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) -#define PORT_LED_GREEN (2 << 14) -#define PORT_LED_MASK (3 << 14) -/* Port Link State Write Strobe - set this when changing link state */ -#define PORT_LINK_STROBE (1 << 16) -/* true: connect status change */ -#define PORT_CSC (1 << 17) -/* true: port enable change */ -#define PORT_PEC (1 << 18) -/* true: warm reset for a USB 3.0 device is done. A "hot" reset puts the port - * into an enabled state, and the device into the default state. A "warm" reset - * also resets the link, forcing the device through the link training sequence. - * SW can also look at the Port Reset register to see when warm reset is done. - */ -#define PORT_WRC (1 << 19) -/* true: over-current change */ -#define PORT_OCC (1 << 20) -/* true: reset change - 1 to 0 transition of PORT_RESET */ -#define PORT_RC (1 << 21) -/* port link status change - set on some port link state transitions: - * Transition Reason - * -------------------------------------------------------------------------- - * - U3 to Resume Wakeup signaling from a device - * - Resume to Recovery to U0 USB 3.0 device resume - * - Resume to U0 USB 2.0 device resume - * - U3 to Recovery to U0 Software resume of USB 3.0 device complete - * - U3 to U0 Software resume of USB 2.0 device complete - * - U2 to U0 L1 resume of USB 2.1 device complete - * - U0 to U0 (???) L1 entry rejection by USB 2.1 device - * - U0 to disabled L1 entry error with USB 2.1 device - * - Any state to inactive Error on USB 3.0 port - */ -#define PORT_PLC (1 << 22) -/* port configure error change - port failed to configure its link partner */ -#define PORT_CEC (1 << 23) -/* bit 24 reserved */ -/* wake on connect (enable) */ -#define PORT_WKCONN_E (1 << 25) -/* wake on disconnect (enable) */ -#define PORT_WKDISC_E (1 << 26) -/* wake on over-current (enable) */ -#define PORT_WKOC_E (1 << 27) -/* bits 28:29 reserved */ -/* true: device is removable - for USB 3.0 roothub emulation */ -#define PORT_DEV_REMOVE (1 << 30) -/* Initiate a warm port reset - complete when PORT_WRC is '1' */ -#define PORT_WR (1 << 31) - -/* We mark duplicate entries with -1 */ -#define DUPLICATE_ENTRY ((u8)(-1)) - -/* Port Power Management Status and Control - port_power_base bitmasks */ -/* Inactivity timer value for transitions into U1, in microseconds. - * Timeout can be up to 127us. 0xFF means an infinite timeout. - */ -#define PORT_U1_TIMEOUT(p) ((p) & 0xff) -/* Inactivity timer value for transitions into U2 */ -#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) -/* Bits 24:31 for port testing */ - -/* USB2 Protocol PORTSPMSC */ -#define PORT_L1S_MASK 7 -#define PORT_L1S_SUCCESS 1 -#define PORT_RWE (1 << 3) -#define PORT_HIRD(p) (((p) & 0xf) << 4) -#define PORT_HIRD_MASK (0xf << 4) -#define PORT_L1DS(p) (((p) & 0xff) << 8) -#define PORT_HLE (1 << 16) - -/** -* struct xhci_intr_reg - Interrupt Register Set -* @irq_pending: IMAN - Interrupt Management Register. Used to enable -* interrupts and check for pending interrupts. -* @irq_control: IMOD - Interrupt Moderation Register. -* Used to throttle interrupts. -* @erst_size: Number of segments in the - Event Ring Segment Table (ERST). -* @erst_base: ERST base address. -* @erst_dequeue: Event ring dequeue pointer. -* -* Each interrupter (defined by a MSI-X vector) has an event ring and an Event -* Ring Segment Table (ERST) associated with it. -* The event ring is comprised of multiple segments of the same size. -* The HC places events on the ring and "updates the Cycle bit in the TRBs to -* indicate to software the current position of the Enqueue Pointer." -* The HCD (Linux) processes those events and updates the dequeue pointer. -*/ -struct xhci_intr_reg { - volatile __le32 irq_pending; - volatile __le32 irq_control; - volatile __le32 erst_size; - volatile __le32 rsvd; - volatile __le64 erst_base; - volatile __le64 erst_dequeue; -}; - -/* irq_pending bitmasks */ -#define ER_IRQ_PENDING(p) ((p) & 0x1) -/* bits 2:31 need to be preserved */ -/* THIS IS BUGGY - FIXME - IP IS WRITE 1 TO CLEAR */ -#define ER_IRQ_CLEAR(p) ((p) & 0xfffffffe) -#define ER_IRQ_ENABLE(p) ((ER_IRQ_CLEAR(p)) | 0x2) -#define ER_IRQ_DISABLE(p) ((ER_IRQ_CLEAR(p)) & ~(0x2)) - -/* irq_control bitmasks */ -/* Minimum interval between interrupts (in 250ns intervals). The interval - * between interrupts will be longer if there are no events on the event ring. - * Default is 4000 (1 ms). - */ -#define ER_IRQ_INTERVAL_MASK (0xffff) -/* Counter used to count down the time to the next interrupt - HW use only */ -#define ER_IRQ_COUNTER_MASK (0xffff << 16) - -/* erst_size bitmasks */ -/* Preserve bits 16:31 of erst_size */ -#define ERST_SIZE_MASK (0xffff << 16) - -/* erst_dequeue bitmasks */ -/* Dequeue ERST Segment Index (DESI) - Segment number (or alias) - * where the current dequeue pointer lies. This is an optional HW hint. - */ -#define ERST_DESI_MASK (0x7) -/* Event Handler Busy (EHB) - is the event ring scheduled to be serviced by - * a work queue (or delayed service routine)? - */ -#define ERST_EHB (1 << 3) -#define ERST_PTR_MASK (0xf) - -/** - * struct xhci_run_regs - * @microframe_index: MFINDEX - current microframe number - * - * Section 5.5 Host Controller Runtime Registers: - * "Software should read and write these registers using only Dword (32 bit) - * or larger accesses" - */ -struct xhci_run_regs { - __le32 microframe_index; - __le32 rsvd[7]; - struct xhci_intr_reg ir_set[128]; -}; - -/** - * struct doorbell_array - * - * Bits 0 - 7: Endpoint target - * Bits 8 - 15: RsvdZ - * Bits 16 - 31: Stream ID - * - * Section 5.6 - */ -struct xhci_doorbell_array { - volatile __le32 doorbell[256]; -}; - -#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) -#define DB_VALUE_HOST 0x00000000 - -/** - * struct xhci_protocol_caps - * @revision: major revision, minor revision, capability ID, - * and next capability pointer. - * @name_string: Four ASCII characters to say which spec this xHC - * follows, typically "USB ". - * @port_info: Port offset, count, and protocol-defined information. - */ -struct xhci_protocol_caps { - u32 revision; - u32 name_string; - u32 port_info; -}; - -#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) -#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) -#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) - -/** - * struct xhci_container_ctx - * @type: Type of context. Used to calculated offsets to contained contexts. - * @size: Size of the context data - * @bytes: The raw context data given to HW - * @dma: dma address of the bytes - * - * Represents either a Device or Input context. Holds a pointer to the raw - * memory used for the context (bytes) and dma address of it (dma). - */ -struct xhci_container_ctx { - unsigned type; -#define XHCI_CTX_TYPE_DEVICE 0x1 -#define XHCI_CTX_TYPE_INPUT 0x2 - - int size; - u8 *bytes; -}; - -/** - * 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 { - __le32 dev_info; - __le32 dev_info2; - __le32 tt_info; - __le32 dev_state; - /* offset 0x10 to 0x1f reserved for HC internal use */ - __le32 reserved[4]; -}; - -/* 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_CTX_MASK (0x1f << 27) -#define LAST_CTX(p) ((p) << 27) -#define LAST_CTX_TO_EP_NUM(p) (((p) >> 27) - 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(p) (((p) & 0xff) << 16) -#define ROOT_HUB_PORT_MASK (0xff) -#define ROOT_HUB_PORT_SHIFT (16) -#define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) -/* Maximum number of ports under a hub device */ -#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) - -/* 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) -#define TT_THINK_TIME(p) (((p) & 0x3) << 16) - -/* dev_state bitmasks */ -/* USB device address - assigned by the HC */ -#define DEV_ADDR_MASK (0xff) -/* bits 8:26 reserved */ -/* Slot state */ -#define SLOT_STATE (0x1f << 27) -#define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) - -#define SLOT_STATE_DISABLED 0 -#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED -#define SLOT_STATE_DEFAULT 1 -#define SLOT_STATE_ADDRESSED 2 -#define SLOT_STATE_CONFIGURED 3 - -/** - * 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. - * @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 - * reserved at the end of the endpoint context for HC internal use. - */ -struct xhci_ep_ctx { - __le32 ep_info; - __le32 ep_info2; - __le64 deq; - __le32 tx_info; - /* offset 0x14 - 0x1f reserved for HC internal use */ - __le32 reserved[3]; -}; - -/* 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_MASK (0xf) -#define EP_STATE_DISABLED 0 -#define EP_STATE_RUNNING 1 -#define EP_STATE_HALTED 2 -#define EP_STATE_STOPPED 3 -#define EP_STATE_ERROR 4 -/* Mult - Max number of burtst within an interval, in EP companion desc. */ -#define EP_MULT(p) (((p) & 0x3) << 8) -#define CTX_TO_EP_MULT(p) (((p) >> 8) & 0x3) -/* 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(p) (((p) & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) -#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) -#define EP_MAXPSTREAMS_MASK (0x1f << 10) -#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) -/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ -#define EP_HAS_LSA (1 << 15) - -/* 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 ERROR_COUNT_SHIFT (1) -#define ERROR_COUNT_MASK (0x3) -#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) -#define EP_TYPE(p) ((p) << 3) -#define EP_TYPE_SHIFT (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_BURST_MASK (0xff) -#define MAX_BURST_SHIFT (8) -#define CTX_TO_MAX_BURST(p) (((p) >> 8) & 0xff) -#define MAX_PACKET(p) (((p)&0xffff) << 16) -#define MAX_PACKET_MASK (0xffff) -#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) -#define MAX_PACKET_SHIFT (16) - -/* Get max packet size from ep desc. Bit 10..0 specify the max packet size. - * USB2.0 spec 9.6.6. - */ -#define GET_MAX_PACKET(p) ((p) & 0x7ff) - -/* tx_info bitmasks */ -#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) -#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) -#define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) - -/* deq bitmasks */ -#define EP_CTX_CYCLE_MASK (1 << 0) - - -/** - * struct xhci_input_control_context - * Input control 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_input_control_ctx { - volatile __le32 drop_flags; - volatile __le32 add_flags; - __le32 rsvd2[6]; -}; - - -/** - * 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 */ - __le64 dev_context_ptrs[MAX_HC_SLOTS]; -}; -/* 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_transfer_event { - /* 64-bit buffer address, or immediate data */ - __le64 buffer; - __le32 transfer_len; - /* This field is interpreted differently based on the type of TRB */ - volatile __le32 flags; -}; - -/* Transfer event TRB length bit mask */ -/* bits 0:23 */ -#define EVENT_TRB_LEN(p) ((p) & 0xffffff) - -/** Transfer Event bit fields **/ -#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) - -/* Completion Code - only applicable for some types of TRBs */ -#define COMP_CODE_MASK (0xff << 24) -#define COMP_CODE_SHIFT (24) -#define GET_COMP_CODE(p) (((p) & COMP_CODE_MASK) >> 24) - -typedef enum { - COMP_SUCCESS = 1, - /* Data Buffer Error */ - COMP_DB_ERR, /* 2 */ - /* Babble Detected Error */ - COMP_BABBLE, /* 3 */ - /* USB Transaction Error */ - COMP_TX_ERR, /* 4 */ - /* TRB Error - some TRB field is invalid */ - COMP_TRB_ERR, /* 5 */ - /* Stall Error - USB device is stalled */ - COMP_STALL, /* 6 */ - /* Resource Error - HC doesn't have memory for that device configuration */ - COMP_ENOMEM, /* 7 */ - /* Bandwidth Error - not enough room in schedule for this dev config */ - COMP_BW_ERR, /* 8 */ - /* No Slots Available Error - HC ran out of device slots */ - COMP_ENOSLOTS, /* 9 */ - /* Invalid Stream Type Error */ - COMP_STREAM_ERR, /* 10 */ - /* Slot Not Enabled Error - doorbell rung for disabled device slot */ - COMP_EBADSLT, /* 11 */ - /* Endpoint Not Enabled Error */ - COMP_EBADEP,/* 12 */ - /* Short Packet */ - COMP_SHORT_TX, /* 13 */ - /* Ring Underrun - doorbell rung for an empty isoc OUT ep ring */ - COMP_UNDERRUN, /* 14 */ - /* Ring Overrun - isoc IN ep ring is empty when ep is scheduled to RX */ - COMP_OVERRUN, /* 15 */ - /* Virtual Function Event Ring Full Error */ - COMP_VF_FULL, /* 16 */ - /* Parameter Error - Context parameter is invalid */ - COMP_EINVAL, /* 17 */ - /* Bandwidth Overrun Error - isoc ep exceeded its allocated bandwidth */ - COMP_BW_OVER,/* 18 */ - /* Context State Error - illegal context state transition requested */ - COMP_CTX_STATE,/* 19 */ - /* No Ping Response Error - HC didn't get PING_RESPONSE in time to TX */ - COMP_PING_ERR,/* 20 */ - /* Event Ring is full */ - COMP_ER_FULL,/* 21 */ - /* Incompatible Device Error */ - COMP_DEV_ERR,/* 22 */ - /* Missed Service Error - HC couldn't service an isoc ep within interval */ - COMP_MISSED_INT,/* 23 */ - /* Successfully stopped command ring */ - COMP_CMD_STOP, /* 24 */ - /* Successfully aborted current command and stopped command ring */ - COMP_CMD_ABORT, /* 25 */ - /* Stopped - transfer was terminated by a stop endpoint command */ - COMP_STOP,/* 26 */ - /* Same as COMP_EP_STOPPED, but the transferred length in the event - * is invalid */ - COMP_STOP_INVAL, /* 27*/ - /* Control Abort Error - Debug Capability - control pipe aborted */ - COMP_DBG_ABORT, /* 28 */ - /* Max Exit Latency Too Large Error */ - COMP_MEL_ERR,/* 29 */ - /* TRB type 30 reserved */ - /* Isoc Buffer Overrun - an isoc IN ep sent more data than could fit in TD */ - COMP_BUFF_OVER = 31, - /* Event Lost Error - xHC has an "internal event overrun condition" */ - COMP_ISSUES, /* 32 */ - /* Undefined Error - reported when other error codes don't apply */ - COMP_UNKNOWN, /* 33 */ - /* Invalid Stream ID Error */ - COMP_STRID_ERR, /* 34 */ - /* Secondary Bandwidth Error - may be returned by a Configure Endpoint cmd */ - COMP_2ND_BW_ERR, /* 35 */ - /* Split Transaction Error */ - COMP_SPLIT_ERR /* 36 */ - -} xhci_comp_code; - -struct xhci_link_trb { - /* 64-bit segment pointer*/ - volatile __le64 segment_ptr; - volatile __le32 intr_target; - volatile __le32 control; -}; - -/* control bitfields */ -#define LINK_TOGGLE (0x1 << 1) - -/* Command completion event TRB */ -struct xhci_event_cmd { - /* Pointer to command TRB, or the value passed by the event data trb */ - volatile __le64 cmd_trb; - volatile __le32 status; - volatile __le32 flags; -}; - -/* 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 TRB_TO_SLOT_ID_SHIFT (24) -#define TRB_TO_SLOT_ID_MASK (0xff << TRB_TO_SLOT_ID_SHIFT) -#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) -#define SLOT_ID_FOR_TRB_MASK (0xff) -#define SLOT_ID_FOR_TRB_SHIFT (24) - -/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB */ -#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) -#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) - -#define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) -#define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23) -#define LAST_EP_INDEX 30 - -/* Set TR Dequeue Pointer command TRB fields */ -#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) -#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) - - -/* Port Status Change Event TRB fields */ -/* Port ID - bits 31:24 */ -#define GET_PORT_ID(p) (((p) & (0xff << 24)) >> 24) -#define PORT_ID_SHIFT (24) -#define PORT_ID_MASK (0xff << PORT_ID_SHIFT) - -/* Normal TRB fields */ -/* transfer_len bitmasks - bits 0:16 */ -#define TRB_LEN(p) ((p) & 0x1ffff) -#define TRB_LEN_MASK (0x1ffff) -/* Interrupter Target - which MSI-X vector to target the completion event at */ -#define TRB_INTR_TARGET_SHIFT (22) -#define TRB_INTR_TARGET_MASK (0x3ff) -#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) -#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) -#define TRB_TBC(p) (((p) & 0x3) << 7) -#define TRB_TLBPC(p) (((p) & 0xf) << 16) - -/* Cycle bit - indicates TRB ownership by HC or HCD */ -#define TRB_CYCLE (1<<0) -/* - * Force next event data TRB to be evaluated before task switch. - * Used to pass OS data back after a TD completes. - */ -#define TRB_ENT (1<<1) -/* Interrupt on short packet */ -#define TRB_ISP (1<<2) -/* Set PCIe no snoop attribute */ -#define TRB_NO_SNOOP (1<<3) -/* Chain multiple TRBs into a TD */ -#define TRB_CHAIN (1<<4) -/* Interrupt on completion */ -#define TRB_IOC (1<<5) -/* The buffer pointer contains immediate data */ -#define TRB_IDT (1<<6) - -/* Block Event Interrupt */ -#define TRB_BEI (1<<9) - -/* Control transfer TRB specific fields */ -#define TRB_DIR_IN (1<<16) -#define TRB_TX_TYPE(p) ((p) << 16) -#define TRB_TX_TYPE_SHIFT (16) -#define TRB_DATA_OUT 2 -#define TRB_DATA_IN 3 - -/* Isochronous TRB specific fields */ -#define TRB_SIA (1 << 31) - -struct xhci_generic_trb { - volatile __le32 field[4]; -}; - -union xhci_trb { - struct xhci_link_trb link; - struct xhci_transfer_event trans_event; - struct xhci_event_cmd event_cmd; - struct xhci_generic_trb generic; -}; - -/* TRB bit mask */ -#define TRB_TYPE_BITMASK (0xfc00) -#define TRB_TYPE(p) ((p) << 10) -#define TRB_TYPE_SHIFT (10) -#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) - -/* TRB type IDs */ -typedef enum { - /* bulk, interrupt, isoc scatter/gather, and control data stage */ - TRB_NORMAL = 1, - /* setup stage for control transfers */ - TRB_SETUP, /* 2 */ - /* data stage for control transfers */ - TRB_DATA, /* 3 */ - /* status stage for control transfers */ - TRB_STATUS, /* 4 */ - /* isoc transfers */ - TRB_ISOC, /* 5 */ - /* TRB for linking ring segments */ - TRB_LINK, /* 6 */ - /* TRB for EVENT DATA */ - TRB_EVENT_DATA, /* 7 */ - /* Transfer Ring No-op (not for the command ring) */ - TRB_TR_NOOP, /* 8 */ - /* Command TRBs */ - /* Enable Slot Command */ - TRB_ENABLE_SLOT, /* 9 */ - /* Disable Slot Command */ - TRB_DISABLE_SLOT, /* 10 */ - /* Address Device Command */ - TRB_ADDR_DEV, /* 11 */ - /* Configure Endpoint Command */ - TRB_CONFIG_EP, /* 12 */ - /* Evaluate Context Command */ - TRB_EVAL_CONTEXT, /* 13 */ - /* Reset Endpoint Command */ - TRB_RESET_EP, /* 14 */ - /* Stop Transfer Ring Command */ - TRB_STOP_RING, /* 15 */ - /* Set Transfer Ring Dequeue Pointer Command */ - TRB_SET_DEQ, /* 16 */ - /* Reset Device Command */ - TRB_RESET_DEV, /* 17 */ - /* Force Event Command (opt) */ - TRB_FORCE_EVENT, /* 18 */ - /* Negotiate Bandwidth Command (opt) */ - TRB_NEG_BANDWIDTH, /* 19 */ - /* Set Latency Tolerance Value Command (opt) */ - TRB_SET_LT, /* 20 */ - /* Get port bandwidth Command */ - TRB_GET_BW, /* 21 */ - /* Force Header Command - generate a transaction or link management packet */ - TRB_FORCE_HEADER, /* 22 */ - /* No-op Command - not for transfer rings */ - TRB_CMD_NOOP, /* 23 */ - /* TRB IDs 24-31 reserved */ - /* Event TRBS */ - /* Transfer Event */ - TRB_TRANSFER = 32, - /* Command Completion Event */ - TRB_COMPLETION, /* 33 */ - /* Port Status Change Event */ - TRB_PORT_STATUS, /* 34 */ - /* Bandwidth Request Event (opt) */ - TRB_BANDWIDTH_EVENT, /* 35 */ - /* Doorbell Event (opt) */ - TRB_DOORBELL, /* 36 */ - /* Host Controller Event */ - TRB_HC_EVENT, /* 37 */ - /* Device Notification Event - device sent function wake notification */ - TRB_DEV_NOTE, /* 38 */ - /* MFINDEX Wrap Event - microframe counter wrapped */ - TRB_MFINDEX_WRAP, /* 39 */ - /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ - /* Nec vendor-specific command completion event. */ - TRB_NEC_CMD_COMP = 48, /* 48 */ - /* Get NEC firmware revision. */ - TRB_NEC_GET_FW, /* 49 */ -} trb_type; - -#define TRB_TYPE_LINK(x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) -/* Above, but for __le32 types -- can avoid work by swapping constants: */ -#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ - cpu_to_le32(TRB_TYPE(TRB_LINK))) -#define TRB_TYPE_NOOP_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ - cpu_to_le32(TRB_TYPE(TRB_TR_NOOP))) - -/* - * TRBS_PER_SEGMENT must be a multiple of 4, - * since the command ring is 64-byte aligned. - * It must also be greater than 16. - */ -#define TRBS_PER_SEGMENT 64 -/* Allow two commands + a link TRB, along with any reserved command TRBs */ -#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) -#define SEGMENT_SIZE (TRBS_PER_SEGMENT*16) -/* SEGMENT_SHIFT should be log2(SEGMENT_SIZE). - * Change this if you change TRBS_PER_SEGMENT! - */ -#define SEGMENT_SHIFT 10 -/* TRB buffer pointers can't cross 64KB boundaries */ -#define TRB_MAX_BUFF_SHIFT 16 -#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) - -struct xhci_segment { - union xhci_trb *trbs; - /* private to HCD */ - struct xhci_segment *next; -}; - -struct xhci_ring { - struct xhci_segment *first_seg; - union xhci_trb *enqueue; - struct xhci_segment *enq_seg; - union xhci_trb *dequeue; - struct xhci_segment *deq_seg; - /* - * Write the cycle state into the TRB cycle field to give ownership of - * the TRB to the host controller (if we are the producer), or to check - * if we own the TRB (if we are the consumer). See section 4.9.1. - */ - volatile u32 cycle_state; - unsigned int num_segs; -}; - -struct xhci_erst_entry { - /* 64-bit event ring segment address */ - __le64 seg_addr; - __le32 seg_size; - /* Set to zero */ - __le32 rsvd; -}; - -struct xhci_erst { - struct xhci_erst_entry *entries; - unsigned int num_entries; - /* Num entries the ERST can contain */ - unsigned int erst_size; -}; - -/* - * Each segment table entry is 4*32bits long. 1K seems like an ok size: - * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, - * meaning 64 ring segments. - * Initial allocated size of the ERST, in number of entries */ -#define ERST_NUM_SEGS 3 -/* Initial number of event segment rings allocated */ -#define ERST_ENTRIES 3 -/* Initial allocated size of the ERST, in number of entries */ -#define ERST_SIZE 64 -/* Poll every 60 seconds */ -#define POLL_TIMEOUT 60 -/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ -#define XHCI_STOP_EP_CMD_TIMEOUT 5 -/* XXX: Make these module parameters */ - -struct xhci_virt_ep { - struct xhci_ring *ring; - unsigned int ep_state; -#define SET_DEQ_PENDING (1 << 0) -#define EP_HALTED (1 << 1) /* For stall handling */ -#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */ -/* Transitioning the endpoint to using streams, don't enqueue URBs */ -#define EP_GETTING_STREAMS (1 << 3) -#define EP_HAS_STREAMS (1 << 4) -/* Transitioning the endpoint to not using streams, don't enqueue URBs */ -#define EP_GETTING_NO_STREAMS (1 << 5) -}; - -#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) - -struct xhci_virt_device { - struct usb_device *udev; - /* - * 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_container_ctx *out_ctx; - /* Used for addressing devices and configuration changes */ - struct xhci_container_ctx *in_ctx; - /* Rings saved to ensure old alt settings can be re-instated */ -#define XHCI_MAX_RINGS_CACHED 31 - struct xhci_virt_ep eps[31]; -}; - -/* TODO: copied from ehci.h - can be refactored? */ -/* xHCI spec says all registers are little endian */ -static inline unsigned int xhci_readl(uint32_t volatile *regs) -{ - return readl(regs); -} - -static inline void xhci_writel(uint32_t volatile *regs, const unsigned int val) -{ - writel(val, regs); -} - -/* - * Registers should always be accessed with double word or quad word accesses. - * Some xHCI implementations may support 64-bit address pointers. Registers - * with 64-bit address pointers should be written to with dword accesses by - * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. - * xHCI implementations that do not support 64-bit address pointers will ignore - * the high dword, and write order is irrelevant. - */ -static inline u64 xhci_readq(__le64 volatile *regs) -{ - __u32 *ptr = (__u32 *)regs; - u64 val_lo = readl(ptr); - u64 val_hi = readl(ptr + 1); - return val_lo + (val_hi << 32); -} - -static inline void xhci_writeq(__le64 volatile *regs, const u64 val) -{ - __u32 *ptr = (__u32 *)regs; - u32 val_lo = lower_32_bits(val); - /* FIXME */ - u32 val_hi = 0; - writel(val_lo, ptr); - writel(val_hi, ptr + 1); -} - -int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr, - struct xhci_hcor **ret_hcor); -void xhci_hcd_stop(int index); - - -/************************************************************* - EXTENDED CAPABILITY DEFINITIONS -*************************************************************/ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define XHCI_STS_HALT (1 << 0) - -/* HCCPARAMS offset from PCI base address */ -#define XHCI_HCC_PARAMS_OFFSET 0x10 -/* HCCPARAMS contains the first extended capability pointer */ -#define XHCI_HCC_EXT_CAPS(p) (((p)>>16)&0xffff) - -/* Command and Status registers offset from the Operational Registers address */ -#define XHCI_CMD_OFFSET 0x00 -#define XHCI_STS_OFFSET 0x04 - -#define XHCI_MAX_EXT_CAPS 50 - -/* Capability Register */ -/* bits 7:0 - how long is the Capabilities register */ -#define XHCI_HC_LENGTH(p) (((p) >> 00) & 0x00ff) - -/* Extended capability register fields */ -#define XHCI_EXT_CAPS_ID(p) (((p) >> 0) & 0xff) -#define XHCI_EXT_CAPS_NEXT(p) (((p) >> 8) & 0xff) -#define XHCI_EXT_CAPS_VAL(p) ((p) >> 16) -/* Extended capability IDs - ID 0 reserved */ -#define XHCI_EXT_CAPS_LEGACY 1 -#define XHCI_EXT_CAPS_PROTOCOL 2 -#define XHCI_EXT_CAPS_PM 3 -#define XHCI_EXT_CAPS_VIRT 4 -#define XHCI_EXT_CAPS_ROUTE 5 -/* IDs 6-9 reserved */ -#define XHCI_EXT_CAPS_DEBUG 10 -/* USB Legacy Support Capability - section 7.1.1 */ -#define XHCI_HC_BIOS_OWNED (1 << 16) -#define XHCI_HC_OS_OWNED (1 << 24) - -/* USB Legacy Support Capability - section 7.1.1 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_SUPPORT_OFFSET (0x00) - -/* USB Legacy Support Control and Status Register - section 7.1.2 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_CONTROL_OFFSET (0x04) -/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) - -/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ -#define XHCI_L1C (1 << 16) - -/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ -#define XHCI_HLC (1 << 19) - -/* command register values to disable interrupts and halt the HC */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define XHCI_CMD_RUN (1 << 0) -/* Event Interrupt Enable - get irq when EINT bit is set in USBSTS register */ -#define XHCI_CMD_EIE (1 << 2) -/* Host System Error Interrupt Enable - get irq when HSEIE bit set in USBSTS */ -#define XHCI_CMD_HSEIE (1 << 3) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define XHCI_CMD_EWE (1 << 10) - -#define XHCI_IRQS (XHCI_CMD_EIE | XHCI_CMD_HSEIE | XHCI_CMD_EWE) - -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define XHCI_STS_CNR (1 << 11) - -struct xhci_ctrl { - struct xhci_hccr *hccr; /* R/O registers, not need for volatile */ - struct xhci_hcor *hcor; - struct xhci_doorbell_array *dba; - struct xhci_run_regs *run_regs; - struct xhci_device_context_array *dcbaa \ - __attribute__ ((aligned(ARCH_DMA_MINALIGN))); - struct xhci_ring *event_ring; - struct xhci_ring *cmd_ring; - struct xhci_ring *transfer_ring; - struct xhci_segment *seg; - struct xhci_intr_reg *ir_set; - struct xhci_erst erst; - struct xhci_erst_entry entry[ERST_NUM_SEGS]; - struct xhci_virt_device *devs[MAX_HC_SLOTS]; - int rootdev; -}; - -unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); -struct xhci_input_control_ctx - *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); -struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx); -struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *ctx, - unsigned int ep_index); -void xhci_endpoint_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index); -void xhci_slot_copy(struct xhci_ctrl *ctrl, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx); -void xhci_setup_addressable_virt_dev(struct usb_device *udev); -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, - u32 slot_id, u32 ep_index, trb_type cmd); -void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); -int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); -int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, void *buffer); -int xhci_check_maxpacket(struct usb_device *udev); -void xhci_flush_cache(uint32_t addr, u32 type_len); -void xhci_inval_cache(uint32_t addr, u32 type_len); -void xhci_cleanup(struct xhci_ctrl *ctrl); -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs); -int xhci_alloc_virt_device(struct usb_device *udev); -int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, - struct xhci_hcor *hcor); - -#endif /* HOST_XHCI_H_ */ |