Merge git://git.denx.de/u-boot-usb

This commit is contained in:
Tom Rini 2018-03-19 20:10:15 -04:00
commit da773532cd
7 changed files with 255 additions and 128 deletions

View File

@ -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

View File

@ -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

View File

@ -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(&regs->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(&regs->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(&regs->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, &regs->grstctl);
ret = wait_for_bit_le32(&regs->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(&regs->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(&regs->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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}