diff options
author | Tom Rini <trini@konsulko.com> | 2018-03-19 20:10:15 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-03-19 20:10:15 -0400 |
commit | da773532cde226b5456b89096a1be446887c7a3e (patch) | |
tree | f9cc35b4bc236b336c250c4fe8f19c9775373029 /drivers/usb | |
parent | c17848a798489479bcc061f2101caf79cbfc0a20 (diff) | |
parent | ac6c796c3f5c7b7594cf4ecede8cd8fb8d2611ba (diff) |
Merge git://git.denx.de/u-boot-usb
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/Kconfig | 12 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/dwc2.c | 62 | ||||
-rw-r--r-- | drivers/usb/host/ehci-generic.c | 98 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ppc4xx.c | 35 | ||||
-rw-r--r-- | drivers/usb/host/ohci-generic.c | 95 | ||||
-rw-r--r-- | drivers/usb/host/xhci-dwc3.c | 80 |
7 files changed, 255 insertions, 128 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 90b2f78ec7..a7249b7511 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -245,3 +245,15 @@ config USB_DWC2 Hi-Speed (480 Mbps), Full-Speed (12 Mbps), and Low-Speed (1.5 Mbps) operation is compliant to the controller Supplement. If you want to enable this controller in host mode, say Y. + +if USB_DWC2 +config USB_DWC2_BUFFER_SIZE + int "Data buffer size in kB" + default 64 + ---help--- + By default 64 kB buffer is used but if amount of RAM avaialble on + the target is not enough to accommodate allocation of buffer of + that size it is possible to shrink it. Smaller sizes should be fine + because larger transactions could be split in smaller ones. + +endif # USB_DWC2 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 7f9ba24cfe..98194893b9 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o obj-$(CONFIG_USB_EHCI_MX7) += 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_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 0efe645044..4862ab0e7d 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -25,7 +25,7 @@ DECLARE_GLOBAL_DATA_PTR; #define DWC2_HC_CHANNEL 0 #define DWC2_STATUS_BUF_SIZE 64 -#define DWC2_DATA_BUF_SIZE (64 * 1024) +#define DWC2_DATA_BUF_SIZE (CONFIG_USB_DWC2_BUFFER_SIZE * 1024) #define MAX_DEVICE 16 #define MAX_ENDPOINT 16 @@ -34,6 +34,9 @@ struct dwc2_priv { #ifdef CONFIG_DM_USB uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); +#ifdef CONFIG_DM_REGULATOR + struct udevice *vbus_supply; +#endif #else uint8_t *aligned_buffer; uint8_t *status_buffer; @@ -111,7 +114,7 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num) ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_TXFFLSH, false, 1000, false); if (ret) - printf("%s: Timeout!\n", __func__); + dev_info(dev, "%s: Timeout!\n", __func__); /* Wait for 3 PHY Clocks */ udelay(1); @@ -130,7 +133,7 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs) ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_RXFFLSH, false, 1000, false); if (ret) - printf("%s: Timeout!\n", __func__); + dev_info(dev, "%s: Timeout!\n", __func__); /* Wait for 3 PHY Clocks */ udelay(1); @@ -148,14 +151,14 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs) ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_AHBIDLE, true, 1000, false); if (ret) - printf("%s: Timeout!\n", __func__); + dev_info(dev, "%s: Timeout!\n", __func__); /* Core Soft Reset */ writel(DWC2_GRSTCTL_CSFTRST, ®s->grstctl); ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_CSFTRST, false, 1000, false); if (ret) - printf("%s: Timeout!\n", __func__); + dev_info(dev, "%s: Timeout!\n", __func__); /* * Wait for core to come out of reset. @@ -168,28 +171,52 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs) #if defined(CONFIG_DM_USB) && defined(CONFIG_DM_REGULATOR) static int dwc_vbus_supply_init(struct udevice *dev) { - struct udevice *vbus_supply; + struct dwc2_priv *priv = dev_get_priv(dev); int ret; - ret = device_get_supply_regulator(dev, "vbus-supply", &vbus_supply); + ret = device_get_supply_regulator(dev, "vbus-supply", + &priv->vbus_supply); if (ret) { debug("%s: No vbus supply\n", dev->name); return 0; } - ret = regulator_set_enable(vbus_supply, true); + ret = regulator_set_enable(priv->vbus_supply, true); if (ret) { - pr_err("Error enabling vbus supply\n"); + dev_err(dev, "Error enabling vbus supply\n"); return ret; } return 0; } + +static int dwc_vbus_supply_exit(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + if (priv->vbus_supply) { + ret = regulator_set_enable(priv->vbus_supply, false); + if (ret) { + dev_err(dev, "Error disabling vbus supply\n"); + return ret; + } + } + + return 0; +} #else static int dwc_vbus_supply_init(struct udevice *dev) { return 0; } + +#if defined(CONFIG_DM_USB) +static int dwc_vbus_supply_exit(struct udevice *dev) +{ + return 0; +} +#endif #endif /* @@ -270,7 +297,7 @@ static void dwc_otg_core_host_init(struct udevice *dev, ret = wait_for_bit_le32(®s->hc_regs[i].hcchar, DWC2_HCCHAR_CHEN, false, 1000, false); if (ret) - printf("%s: Timeout!\n", __func__); + dev_info("%s: Timeout!\n", __func__); } /* Turn on the vbus power. */ @@ -784,7 +811,7 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle) uint32_t hcint, hctsiz; ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true, - 1000, false); + 2000, false); if (ret) return ret; @@ -1091,7 +1118,7 @@ int _submit_int_msg(struct dwc2_priv *priv, struct usb_device *dev, timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); for (;;) { if (get_timer(0) > timeout) { - printf("Timeout poll on interrupt endpoint\n"); + dev_err(dev, "Timeout poll on interrupt endpoint\n"); return -ETIMEDOUT; } ret = _submit_bulk_msg(priv, dev, pipe, buffer, len); @@ -1107,11 +1134,13 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) int i, j; snpsid = readl(®s->gsnpsid); - printf("Core Release: %x.%03x\n", snpsid >> 12 & 0xf, snpsid & 0xfff); + dev_info(dev, "Core Release: %x.%03x\n", + snpsid >> 12 & 0xf, snpsid & 0xfff); if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx && (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) { - printf("SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid); + dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n", + snpsid); return -ENODEV; } @@ -1269,6 +1298,11 @@ static int dwc2_usb_probe(struct udevice *dev) static int dwc2_usb_remove(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + ret = dwc_vbus_supply_exit(dev); + if (ret) + return ret; dwc2_uninit_common(priv->regs); diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 1cb92c0338..b012d8651f 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -27,6 +27,56 @@ struct generic_ehci { int reset_count; }; +static int ehci_setup_phy(struct udevice *dev, int index) +{ + struct generic_ehci *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_get_by_index(dev, index, &priv->phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + } else { + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_err(dev, "failed to power on usb phy\n"); + return generic_phy_exit(&priv->phy); + } + } + + return 0; +} + +static int ehci_shutdown_phy(struct udevice *dev) +{ + struct generic_ehci *priv = dev_get_priv(dev); + int ret = 0; + + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_power_off(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + + ret = generic_phy_exit(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + } + + return 0; +} + static int ehci_usb_probe(struct udevice *dev) { struct generic_ehci *priv = dev_get_priv(dev); @@ -51,7 +101,7 @@ static int ehci_usb_probe(struct udevice *dev) break; err = clk_enable(&priv->clocks[i]); if (err) { - pr_err("failed to enable clock %d\n", i); + dev_err(dev, "failed to enable clock %d\n", i); clk_free(&priv->clocks[i]); goto clk_err; } @@ -59,7 +109,8 @@ static int ehci_usb_probe(struct udevice *dev) } } else { if (clock_nb != -ENOENT) { - pr_err("failed to get clock phandle(%d)\n", clock_nb); + dev_err(dev, "failed to get clock phandle(%d)\n", + clock_nb); return clock_nb; } } @@ -80,7 +131,8 @@ static int ehci_usb_probe(struct udevice *dev) break; if (reset_deassert(&priv->resets[i])) { - pr_err("failed to deassert reset %d\n", i); + dev_err(dev, "failed to deassert reset %d\n", + i); reset_free(&priv->resets[i]); goto reset_err; } @@ -88,25 +140,15 @@ static int ehci_usb_probe(struct udevice *dev) } } else { if (reset_nb != -ENOENT) { - pr_err("failed to get reset phandle(%d)\n", reset_nb); + dev_err(dev, "failed to get reset phandle(%d)\n", + reset_nb); goto clk_err; } } - err = generic_phy_get_by_index(dev, 0, &priv->phy); - if (err) { - if (err != -ENOENT) { - pr_err("failed to get usb phy\n"); - goto reset_err; - } - } else { - - err = generic_phy_init(&priv->phy); - if (err) { - pr_err("failed to init usb phy\n"); - goto reset_err; - } - } + err = ehci_setup_phy(dev, 0); + if (err) + goto reset_err; hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + @@ -119,20 +161,18 @@ static int ehci_usb_probe(struct udevice *dev) return 0; phy_err: - if (generic_phy_valid(&priv->phy)) { - ret = generic_phy_exit(&priv->phy); - if (ret) - pr_err("failed to release phy\n"); - } + ret = ehci_shutdown_phy(dev); + if (ret) + dev_err(dev, "failed to shutdown usb phy\n"); reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) - pr_err("failed to assert all resets\n"); + dev_err(dev, "failed to assert all resets\n"); clk_err: ret = clk_release_all(priv->clocks, priv->clock_count); if (ret) - pr_err("failed to disable all clocks\n"); + dev_err(dev, "failed to disable all clocks\n"); return err; } @@ -146,11 +186,9 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret; - if (generic_phy_valid(&priv->phy)) { - ret = generic_phy_exit(&priv->phy); - if (ret) - return ret; - } + ret = ehci_shutdown_phy(dev); + if (ret) + return ret; ret = reset_release_all(priv->resets, priv->reset_count); if (ret) diff --git a/drivers/usb/host/ehci-ppc4xx.c b/drivers/usb/host/ehci-ppc4xx.c deleted file mode 100644 index 9d23577642..0000000000 --- a/drivers/usb/host/ehci-ppc4xx.c +++ /dev/null @@ -1,35 +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 <asm/io.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/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index bf55a71d66..5bdd7995b9 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -25,6 +25,56 @@ struct generic_ohci { int reset_count; /* number of reset in reset list */ }; +static int ohci_setup_phy(struct udevice *dev, int index) +{ + struct generic_ohci *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_get_by_index(dev, index, &priv->phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + } else { + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_err(dev, "failed to power on usb phy\n"); + return generic_phy_exit(&priv->phy); + } + } + + return 0; +} + +static int ohci_shutdown_phy(struct udevice *dev) +{ + struct generic_ohci *priv = dev_get_priv(dev); + int ret = 0; + + if (generic_phy_valid(&priv->phy)) { + ret = generic_phy_power_off(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + + ret = generic_phy_exit(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + } + + return 0; +} + static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); @@ -47,14 +97,14 @@ static int ohci_usb_probe(struct udevice *dev) err = clk_enable(&priv->clocks[i]); if (err) { - pr_err("failed to enable clock %d\n", i); + dev_err(dev, "failed to enable clock %d\n", i); clk_free(&priv->clocks[i]); goto clk_err; } priv->clock_count++; } } else if (clock_nb != -ENOENT) { - pr_err("failed to get clock phandle(%d)\n", clock_nb); + dev_err(dev, "failed to get clock phandle(%d)\n", clock_nb); return clock_nb; } @@ -74,31 +124,20 @@ static int ohci_usb_probe(struct udevice *dev) err = reset_deassert(&priv->resets[i]); if (err) { - pr_err("failed to deassert reset %d\n", i); + dev_err(dev, "failed to deassert reset %d\n", i); reset_free(&priv->resets[i]); goto reset_err; } priv->reset_count++; } } else if (reset_nb != -ENOENT) { - pr_err("failed to get reset phandle(%d)\n", reset_nb); + dev_err(dev, "failed to get reset phandle(%d)\n", reset_nb); goto clk_err; } - err = generic_phy_get_by_index(dev, 0, &priv->phy); - if (err) { - if (err != -ENOENT) { - pr_err("failed to get usb phy\n"); - goto reset_err; - } - } else { - - err = generic_phy_init(&priv->phy); - if (err) { - pr_err("failed to init usb phy\n"); - goto reset_err; - } - } + err = ohci_setup_phy(dev, 0); + if (err) + goto reset_err; err = ohci_register(dev, regs); if (err) @@ -107,20 +146,18 @@ static int ohci_usb_probe(struct udevice *dev) return 0; phy_err: - if (generic_phy_valid(&priv->phy)) { - ret = generic_phy_exit(&priv->phy); - if (ret) - pr_err("failed to release phy\n"); - } + ret = ohci_shutdown_phy(dev); + if (ret) + dev_err(dev, "failed to shutdown usb phy\n"); reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) - pr_err("failed to assert all resets\n"); + dev_err(dev, "failed to assert all resets\n"); clk_err: ret = clk_release_all(priv->clocks, priv->clock_count); if (ret) - pr_err("failed to disable all clocks\n"); + dev_err(dev, "failed to disable all clocks\n"); return err; } @@ -134,11 +171,9 @@ static int ohci_usb_remove(struct udevice *dev) if (ret) return ret; - if (generic_phy_valid(&priv->phy)) { - ret = generic_phy_exit(&priv->phy); - if (ret) - return ret; - } + ret = ohci_shutdown_phy(dev); + if (ret) + return ret; ret = reset_release_all(priv->resets, priv->reset_count); if (ret) diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 258d1cd00a..1022dd5512 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -23,6 +23,7 @@ DECLARE_GLOBAL_DATA_PTR; struct xhci_dwc3_platdata { struct phy usb_phy; + struct phy usb3_phy; }; void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) @@ -112,6 +113,50 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) } #ifdef CONFIG_DM_USB +static int xhci_dwc3_setup_phy(struct udevice *dev, int index, struct phy *phy) +{ + int ret = 0; + + ret = generic_phy_get_by_index(dev, index, phy); + if (ret) { + if (ret != -ENOENT) { + pr_err("Failed to get USB PHY for %s\n", dev->name); + return ret; + } + } else { + ret = generic_phy_init(phy); + if (ret) { + pr_err("Can't init USB PHY for %s\n", dev->name); + return ret; + } + ret = generic_phy_power_on(phy); + if (ret) { + pr_err("Can't power on USB PHY for %s\n", dev->name); + generic_phy_exit(phy); + return ret; + } + } + + return 0; +} + +static int xhci_dwc3_shutdown_phy(struct phy *phy) +{ + int ret = 0; + + if (generic_phy_valid(phy)) { + ret = generic_phy_power_off(phy); + if (ret) + return ret; + + ret = generic_phy_exit(phy); + if (ret) + return ret; + } + + return 0; +} + static int xhci_dwc3_probe(struct udevice *dev) { struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); @@ -125,18 +170,17 @@ static int xhci_dwc3_probe(struct udevice *dev) hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); - ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy); + ret = xhci_dwc3_setup_phy(dev, 0, &plat->usb_phy); if (ret) { - if (ret != -ENOENT) { - pr_err("Failed to get USB PHY for %s\n", dev->name); - return ret; - } - } else { - ret = generic_phy_init(&plat->usb_phy); - if (ret) { - pr_err("Can't init USB PHY for %s\n", dev->name); - return ret; - } + pr_err("Failed to setup USB PHY for %s\n", dev->name); + return ret; + } + + ret = xhci_dwc3_setup_phy(dev, 1, &plat->usb3_phy); + if (ret) { + pr_err("Failed to setup USB3 PHY for %s\n", dev->name); + xhci_dwc3_shutdown_phy(&plat->usb_phy); + return ret; } dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); @@ -158,13 +202,13 @@ static int xhci_dwc3_remove(struct udevice *dev) struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); int ret; - if (generic_phy_valid(&plat->usb_phy)) { - ret = generic_phy_exit(&plat->usb_phy); - if (ret) { - pr_err("Can't deinit USB PHY for %s\n", dev->name); - return ret; - } - } + ret = xhci_dwc3_shutdown_phy(&plat->usb_phy); + if (ret) + pr_err("Can't shutdown USB PHY for %s\n", dev->name); + + ret = xhci_dwc3_shutdown_phy(&plat->usb3_phy); + if (ret) + pr_err("Can't shutdown USB3 PHY for %s\n", dev->name); return xhci_deregister(dev); } |