summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/Kconfig8
-rw-r--r--drivers/usb/dwc3/Makefile1
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c456
-rw-r--r--drivers/usb/gadget/f_rockusb.c2
-rw-r--r--drivers/usb/host/Kconfig12
-rw-r--r--drivers/usb/host/ehci-fsl.c10
-rw-r--r--drivers/usb/host/ehci-mx5.c103
-rw-r--r--drivers/usb/host/ohci-da8xx.c139
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/musb/musb_hcd.c6
10 files changed, 728 insertions, 11 deletions
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index bbd8105c06..25e1a38aee 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -44,6 +44,14 @@ config USB_DWC3_GENERIC
Select this for Xilinx ZynqMP and similar Platforms.
This wrapper supports Host and Peripheral operation modes.
+config USB_DWC3_MESON_G12A
+ bool "Amlogic Meson G12A USB wrapper"
+ depends on DM_USB && USB_DWC3 && ARCH_MESON
+ imply PHY
+ help
+ Select this for Amlogic Meson G12A Platforms.
+ This wrapper supports Host and Peripheral operation modes.
+
config USB_DWC3_UNIPHIER
bool "DesignWare USB3 Host Support on UniPhier Platforms"
depends on ARCH_UNIPHIER && USB_XHCI_DWC3
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 60b5515a67..0b652a6f36 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -7,6 +7,7 @@ dwc3-y := core.o
obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o
obj-$(CONFIG_USB_DWC3_GENERIC) += dwc3-generic.o
obj-$(CONFIG_USB_DWC3_UNIPHIER) += dwc3-uniphier.o
obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
new file mode 100644
index 0000000000..832bcd70ff
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Amlogic G12A DWC3 Glue layer
+ *
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <asm-generic/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dwc3-uboot.h>
+#include <generic-phy.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <malloc.h>
+#include <regmap.h>
+#include <usb.h>
+#include "core.h"
+#include "gadget.h"
+#include <reset.h>
+#include <clk.h>
+#include <power/regulator.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+
+/* USB2 Ports Control Registers */
+
+#define U2P_REG_SIZE 0x20
+
+#define U2P_R0 0x0
+ #define U2P_R0_HOST_DEVICE BIT(0)
+ #define U2P_R0_POWER_OK BIT(1)
+ #define U2P_R0_HAST_MODE BIT(2)
+ #define U2P_R0_POWER_ON_RESET BIT(3)
+ #define U2P_R0_ID_PULLUP BIT(4)
+ #define U2P_R0_DRV_VBUS BIT(5)
+
+#define U2P_R1 0x4
+ #define U2P_R1_PHY_READY BIT(0)
+ #define U2P_R1_ID_DIG BIT(1)
+ #define U2P_R1_OTG_SESSION_VALID BIT(2)
+ #define U2P_R1_VBUS_VALID BIT(3)
+
+/* USB Glue Control Registers */
+
+#define USB_R0 0x80
+ #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17)
+ #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18)
+ #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19)
+ #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29)
+ #define USB_R0_U2D_ACT BIT(31)
+
+#define USB_R1 0x84
+ #define USB_R1_U3H_BIGENDIAN_GS BIT(0)
+ #define USB_R1_U3H_PME_ENABLE BIT(1)
+ #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(4, 2)
+ #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(9, 7)
+ #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(13, 12)
+ #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16)
+ #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17)
+ #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18)
+ #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19)
+ #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25)
+
+#define USB_R2 0x88
+ #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20)
+ #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26)
+
+#define USB_R3 0x8c
+ #define USB_R3_P30_SSC_ENABLE BIT(0)
+ #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1)
+ #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4)
+ #define USB_R3_P30_REF_SSP_EN BIT(13)
+
+#define USB_R4 0x90
+ #define USB_R4_P21_PORT_RESET_0 BIT(0)
+ #define USB_R4_P21_SLEEP_M0 BIT(1)
+ #define USB_R4_MEM_PD_MASK GENMASK(3, 2)
+ #define USB_R4_P21_ONLY BIT(4)
+
+#define USB_R5 0x94
+ #define USB_R5_ID_DIG_SYNC BIT(0)
+ #define USB_R5_ID_DIG_REG BIT(1)
+ #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2)
+ #define USB_R5_ID_DIG_EN_0 BIT(4)
+ #define USB_R5_ID_DIG_EN_1 BIT(5)
+ #define USB_R5_ID_DIG_CURR BIT(6)
+ #define USB_R5_ID_DIG_IRQ BIT(7)
+ #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8)
+ #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16)
+
+enum {
+ USB2_HOST_PHY = 0,
+ USB2_OTG_PHY,
+ USB3_HOST_PHY,
+ PHY_COUNT,
+};
+
+static const char *phy_names[PHY_COUNT] = {
+ "usb2-phy0", "usb2-phy1", "usb3-phy0",
+};
+
+struct dwc3_meson_g12a {
+ struct udevice *dev;
+ struct regmap *regmap;
+ struct clk clk;
+ struct reset_ctl reset;
+ struct phy phys[PHY_COUNT];
+ enum usb_dr_mode otg_mode;
+ enum usb_dr_mode otg_phy_mode;
+ unsigned int usb2_ports;
+ unsigned int usb3_ports;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ struct udevice *vbus_supply;
+#endif
+};
+
+#define U2P_REG_SIZE 0x20
+#define USB_REG_OFFSET 0x80
+
+static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
+ int i, enum usb_dr_mode mode)
+{
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ case USB_DR_MODE_OTG:
+ case USB_DR_MODE_UNKNOWN:
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_HOST_DEVICE,
+ U2P_R0_HOST_DEVICE);
+ break;
+
+ case USB_DR_MODE_PERIPHERAL:
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_HOST_DEVICE, 0);
+ break;
+ }
+}
+
+static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
+{
+ int i;
+
+ if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
+ priv->otg_phy_mode = USB_DR_MODE_PERIPHERAL;
+ else
+ priv->otg_phy_mode = USB_DR_MODE_HOST;
+
+ for (i = 0 ; i < USB3_HOST_PHY ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_POWER_ON_RESET,
+ U2P_R0_POWER_ON_RESET);
+
+ if (i == USB2_OTG_PHY) {
+ regmap_update_bits(priv->regmap,
+ U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
+ U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
+
+ dwc3_meson_g12a_usb2_set_mode(priv, i,
+ priv->otg_phy_mode);
+ } else
+ dwc3_meson_g12a_usb2_set_mode(priv, i,
+ USB_DR_MODE_HOST);
+
+ regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
+ U2P_R0_POWER_ON_RESET, 0);
+ }
+
+ return 0;
+}
+
+static void dwc3_meson_g12a_usb3_init(struct dwc3_meson_g12a *priv)
+{
+ regmap_update_bits(priv->regmap, USB_R3,
+ USB_R3_P30_SSC_RANGE_MASK |
+ USB_R3_P30_REF_SSP_EN,
+ USB_R3_P30_SSC_ENABLE |
+ FIELD_PREP(USB_R3_P30_SSC_RANGE_MASK, 2) |
+ USB_R3_P30_REF_SSP_EN);
+ udelay(2);
+
+ regmap_update_bits(priv->regmap, USB_R2,
+ USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK,
+ FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK, 0x15));
+
+ regmap_update_bits(priv->regmap, USB_R2,
+ USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK,
+ FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK, 0x20));
+
+ udelay(2);
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT,
+ USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT);
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_P30_PCS_TX_SWING_FULL_MASK,
+ FIELD_PREP(USB_R1_P30_PCS_TX_SWING_FULL_MASK, 127));
+}
+
+static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
+{
+ if (priv->otg_phy_mode == USB_DR_MODE_PERIPHERAL) {
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_ACT, USB_R0_U2D_ACT);
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
+ regmap_update_bits(priv->regmap, USB_R4,
+ USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
+ } else {
+ regmap_update_bits(priv->regmap, USB_R0,
+ USB_R0_U2D_ACT, 0);
+ regmap_update_bits(priv->regmap, USB_R4,
+ USB_R4_P21_SLEEP_M0, 0);
+ }
+}
+
+static int dwc3_meson_g12a_usb_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = dwc3_meson_g12a_usb2_init(priv);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(priv->regmap, USB_R1,
+ USB_R1_U3H_FLADJ_30MHZ_REG_MASK,
+ FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20));
+
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_EN_0,
+ USB_R5_ID_DIG_EN_0);
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_EN_1,
+ USB_R5_ID_DIG_EN_1);
+ regmap_update_bits(priv->regmap, USB_R5,
+ USB_R5_ID_DIG_TH_MASK,
+ FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff));
+
+ /* If we have an actual SuperSpeed port, initialize it */
+ if (priv->usb3_ports)
+ dwc3_meson_g12a_usb3_init(priv);
+
+ dwc3_meson_g12a_usb_init_mode(priv);
+
+ return 0;
+}
+
+int dwc3_meson_g12a_force_mode(struct udevice *dev, enum usb_dr_mode mode)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+
+ if (!priv)
+ return -EINVAL;
+
+ if (mode != USB_DR_MODE_HOST && mode != USB_DR_MODE_PERIPHERAL)
+ return -EINVAL;
+
+ if (!priv->phys[USB2_OTG_PHY].dev)
+ return -EINVAL;
+
+ if (mode == priv->otg_mode)
+ return 0;
+
+ if (mode == USB_DR_MODE_HOST)
+ debug("%s: switching to Host Mode\n", __func__);
+ else
+ debug("%s: switching to Device Mode\n", __func__);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->vbus_supply) {
+ int ret = regulator_set_enable(priv->vbus_supply,
+ (mode == USB_DR_MODE_PERIPHERAL));
+ if (ret)
+ return ret;
+ }
+#endif
+ priv->otg_phy_mode = mode;
+
+ dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
+
+ dwc3_meson_g12a_usb_init_mode(priv);
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
+{
+ int i, ret;
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+ &priv->phys[i]);
+ if (ret == -ENOENT)
+ continue;
+
+ if (ret)
+ return ret;
+
+ if (i == USB3_HOST_PHY)
+ priv->usb3_ports++;
+ else
+ priv->usb2_ports++;
+ }
+
+ debug("%s: usb2 ports: %d\n", __func__, priv->usb2_ports);
+ debug("%s: usb3 ports: %d\n", __func__, priv->usb3_ports);
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_reset_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = reset_get_by_index(priv->dev, 0, &priv->reset);
+ if (ret)
+ return ret;
+
+ ret = reset_assert(&priv->reset);
+ udelay(1);
+ ret |= reset_deassert(&priv->reset);
+ if (ret) {
+ reset_free(&priv->reset);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_clk_init(struct dwc3_meson_g12a *priv)
+{
+ int ret;
+
+ ret = clk_get_by_index(priv->dev, 0, &priv->clk);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable(&priv->clk);
+ if (ret) {
+ clk_free(&priv->clk);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int dwc3_meson_g12a_probe(struct udevice *dev)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+ int ret, i;
+
+ priv->dev = dev;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_clk_init(priv);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_reset_init(priv);
+ if (ret)
+ return ret;
+
+ ret = dwc3_meson_g12a_get_phys(priv);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret && ret != -ENOENT) {
+ pr_err("Failed to get PHY regulator\n");
+ return ret;
+ }
+
+ if (priv->vbus_supply) {
+ ret = regulator_set_enable(priv->vbus_supply, true);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ priv->otg_mode = usb_get_dr_mode(dev_of_offset(dev));
+
+ ret = dwc3_meson_g12a_usb_init(priv);
+ if (ret)
+ return ret;
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ ret = generic_phy_init(&priv->phys[i]);
+ if (ret)
+ goto err_phy_init;
+ }
+
+ return 0;
+
+err_phy_init:
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ generic_phy_exit(&priv->phys[i]);
+ }
+
+ return ret;
+}
+
+static int dwc3_meson_g12a_remove(struct udevice *dev)
+{
+ struct dwc3_meson_g12a *priv = dev_get_platdata(dev);
+ int i;
+
+ reset_release_all(&priv->reset, 1);
+
+ clk_release_all(&priv->clk, 1);
+
+ for (i = 0 ; i < PHY_COUNT ; ++i) {
+ if (!priv->phys[i].dev)
+ continue;
+
+ generic_phy_exit(&priv->phys[i]);
+ }
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_meson_g12a_ids[] = {
+ { .compatible = "amlogic,meson-g12a-usb-ctrl" },
+ { }
+};
+
+U_BOOT_DRIVER(dwc3_generic_wrapper) = {
+ .name = "dwc3-meson-g12a",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = dwc3_meson_g12a_ids,
+ .probe = dwc3_meson_g12a_probe,
+ .remove = dwc3_meson_g12a_remove,
+ .platdata_auto_alloc_size = sizeof(struct dwc3_meson_g12a),
+
+};
diff --git a/drivers/usb/gadget/f_rockusb.c b/drivers/usb/gadget/f_rockusb.c
index e81eb164b0..f3d24772cd 100644
--- a/drivers/usb/gadget/f_rockusb.c
+++ b/drivers/usb/gadget/f_rockusb.c
@@ -15,7 +15,7 @@
#include <linux/compiler.h>
#include <version.h>
#include <g_dnl.h>
-#include <asm/arch/f_rockusb.h>
+#include <asm/arch-rockchip/f_rockusb.h>
static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
{
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0fbc115801..b1188bcbf5 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -132,6 +132,13 @@ config USB_EHCI_MARVELL
---help---
Enables support for the on-chip EHCI controller on MVEBU SoCs.
+config USB_EHCI_MX5
+ bool "Support for i.MX5 on-chip EHCI USB controller"
+ depends on ARCH_MX5
+ default n
+ help
+ Enables support for the on-chip EHCI controller on i.MX5 SoCs.
+
config USB_EHCI_MX6
bool "Support for i.MX6 on-chip EHCI USB controller"
depends on ARCH_MX6
@@ -239,6 +246,11 @@ config USB_OHCI_GENERIC
---help---
Enables support for generic OHCI controller.
+config USB_OHCI_DA8XX
+ bool "Support for da850 OHCI USB controller"
+ help
+ Enable support for the da850 USB controller.
+
endif # USB_OHCI_HCD
config USB_UHCI_HCD
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 23e7e7125f..b8f8e7a794 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -75,8 +75,12 @@ static int ehci_fsl_init_after_reset(struct ehci_ctrl *ctrl)
struct usb_ehci *ehci = NULL;
struct ehci_fsl_priv *priv = container_of(ctrl, struct ehci_fsl_priv,
ehci);
-
+#ifdef CONFIG_PPC
+ ehci = (struct usb_ehci *)lower_32_bits(priv->hcd_base);
+#else
ehci = (struct usb_ehci *)priv->hcd_base;
+#endif
+
if (ehci_fsl_init(priv, ehci, priv->ehci.hccr, priv->ehci.hcor) < 0)
return -ENXIO;
@@ -103,7 +107,11 @@ static int ehci_fsl_probe(struct udevice *dev)
debug("Can't get the EHCI register base address\n");
return -ENXIO;
}
+#ifdef CONFIG_PPC
+ ehci = (struct usb_ehci *)lower_32_bits(priv->hcd_base);
+#else
ehci = (struct usb_ehci *)priv->hcd_base;
+#endif
hccr = (struct ehci_hccr *)(&ehci->caplength);
hcor = (struct ehci_hcor *)
((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c
index 60f1470860..0b32728c57 100644
--- a/drivers/usb/host/ehci-mx5.c
+++ b/drivers/usb/host/ehci-mx5.c
@@ -12,6 +12,8 @@
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <dm.h>
+#include <power/regulator.h>
#include "ehci.h"
@@ -223,6 +225,7 @@ __weak void mx5_ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
mdelay(50);
}
+#if !CONFIG_IS_ENABLED(DM_USB)
static const struct ehci_ops mx5_ehci_ops = {
.powerup_fixup = mx5_ehci_powerup_fixup,
};
@@ -267,3 +270,103 @@ int ehci_hcd_stop(int index)
{
return 0;
}
+#else /* CONFIG_IS_ENABLED(DM_USB) */
+struct ehci_mx5_priv_data {
+ struct ehci_ctrl ctrl;
+ struct usb_ehci *ehci;
+ struct udevice *vbus_supply;
+ enum usb_init_type init_type;
+ int portnr;
+};
+
+static const struct ehci_ops mx5_ehci_ops = {
+ .powerup_fixup = mx5_ehci_powerup_fixup,
+};
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+ struct usb_platdata *plat = dev_get_platdata(dev);
+ const char *mode;
+
+ mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "dr_mode", NULL);
+ if (mode) {
+ if (strcmp(mode, "peripheral") == 0)
+ plat->init_type = USB_INIT_DEVICE;
+ else if (strcmp(mode, "host") == 0)
+ plat->init_type = USB_INIT_HOST;
+ else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+ struct usb_platdata *plat = dev_get_platdata(dev);
+ struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev);
+ struct ehci_mx5_priv_data *priv = dev_get_priv(dev);
+ enum usb_init_type type = plat->init_type;
+ struct ehci_hccr *hccr;
+ struct ehci_hcor *hcor;
+ int ret;
+
+ set_usboh3_clk();
+ enable_usboh3_clk(true);
+ set_usb_phy_clk();
+ enable_usb_phy1_clk(true);
+ enable_usb_phy2_clk(true);
+ mdelay(1);
+
+ priv->ehci = ehci;
+ priv->portnr = dev->seq;
+ priv->init_type = type;
+
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret)
+ debug("%s: No vbus supply\n", dev->name);
+
+ if (!ret && priv->vbus_supply) {
+ ret = regulator_set_enable(priv->vbus_supply,
+ (type == USB_INIT_DEVICE) ?
+ false : true);
+ if (ret) {
+ puts("Error enabling VBUS supply\n");
+ return ret;
+ }
+ }
+
+ 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(priv->portnr, CONFIG_MXC_USB_FLAGS);
+ mdelay(10);
+
+ return ehci_register(dev, hccr, hcor, &mx5_ehci_ops, 0,
+ priv->init_type);
+}
+
+static const struct udevice_id mx5_usb_ids[] = {
+ { .compatible = "fsl,imx53-usb" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_mx5) = {
+ .name = "ehci_mx5",
+ .id = UCLASS_USB,
+ .of_match = mx5_usb_ids,
+ .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+ .probe = ehci_usb_probe,
+ .remove = ehci_deregister,
+ .ops = &ehci_usb_ops,
+ .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+ .priv_auto_alloc_size = sizeof(struct ehci_mx5_priv_data),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* !CONFIG_IS_ENABLED(DM_USB) */
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 47ad3f34d5..233df57b4d 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -4,9 +4,54 @@
*/
#include <common.h>
-
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/ofnode.h>
+#include <generic-phy.h>
+#include <reset.h>
+#include "ohci.h"
#include <asm/arch/da8xx-usb.h>
+struct da8xx_ohci {
+ ohci_t ohci;
+ struct clk *clocks; /* clock list */
+ struct phy phy;
+ int clock_count; /* number of clock in clock list */
+};
+
+static int usb_phy_on(void)
+{
+ unsigned long timeout;
+
+ clrsetbits_le32(&davinci_syscfg_regs->cfgchip2,
+ (CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN |
+ CFGCHIP2_OTGPWRDN | CFGCHIP2_OTGMODE |
+ CFGCHIP2_REFFREQ | CFGCHIP2_USB1PHYCLKMUX),
+ (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN |
+ CFGCHIP2_PHY_PLLON | CFGCHIP2_REFFREQ_24MHZ |
+ CFGCHIP2_USB2PHYCLKMUX | CFGCHIP2_USB1SUSPENDM));
+
+ /* wait until the usb phy pll locks */
+ timeout = get_timer(0);
+ while (get_timer(timeout) < 10) {
+ if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD)
+ return 1;
+ }
+
+ /* USB phy was not turned on */
+ return 0;
+}
+
+static void usb_phy_off(void)
+{
+ /* Power down the on-chip PHY. */
+ clrsetbits_le32(&davinci_syscfg_regs->cfgchip2,
+ CFGCHIP2_PHY_PLLON | CFGCHIP2_USB1SUSPENDM,
+ CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN |
+ CFGCHIP2_RESET);
+}
+
int usb_cpu_init(void)
{
/* enable psc for usb2.0 */
@@ -37,3 +82,95 @@ int usb_cpu_init_fail(void)
{
return usb_cpu_stop();
}
+
+#if CONFIG_IS_ENABLED(DM_USB)
+static int ohci_da8xx_probe(struct udevice *dev)
+{
+ struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
+ struct da8xx_ohci *priv = dev_get_priv(dev);
+ int i, err, ret, clock_nb;
+
+ err = 0;
+ priv->clock_count = 0;
+ clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+
+ if (clock_nb < 0)
+ return clock_nb;
+
+ if (clock_nb > 0) {
+ priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
+ GFP_KERNEL);
+ if (!priv->clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < clock_nb; i++) {
+ err = clk_get_by_index(dev, i, &priv->clocks[i]);
+ if (err < 0)
+ break;
+
+ err = clk_enable(&priv->clocks[i]);
+ if (err) {
+ dev_err(dev, "failed to enable clock %d\n", i);
+ clk_free(&priv->clocks[i]);
+ goto clk_err;
+ }
+ priv->clock_count++;
+ }
+ }
+
+ err = usb_cpu_init();
+
+ if (err)
+ goto clk_err;
+
+ err = ohci_register(dev, regs);
+ if (err)
+ goto phy_err;
+
+ return 0;
+
+phy_err:
+ ret = usb_cpu_stop();
+ if (ret)
+ dev_err(dev, "failed to shutdown usb phy\n");
+
+clk_err:
+ ret = clk_release_all(priv->clocks, priv->clock_count);
+ if (ret)
+ dev_err(dev, "failed to disable all clocks\n");
+
+ return err;
+}
+
+static int ohci_da8xx_remove(struct udevice *dev)
+{
+ struct da8xx_ohci *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = ohci_deregister(dev);
+ if (ret)
+ return ret;
+
+ ret = usb_cpu_stop();
+ if (ret)
+ return ret;
+
+ return clk_release_all(priv->clocks, priv->clock_count);
+}
+
+static const struct udevice_id da8xx_ohci_ids[] = {
+ { .compatible = "ti,da830-ohci" },
+ { }
+};
+
+U_BOOT_DRIVER(ohci_generic) = {
+ .name = "ohci-da8xx",
+ .id = UCLASS_USB,
+ .of_match = da8xx_ohci_ids,
+ .probe = ohci_da8xx_probe,
+ .remove = ohci_da8xx_remove,
+ .ops = &ohci_usb_ops,
+ .priv_auto_alloc_size = sizeof(struct da8xx_ohci),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
+};
+#endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 3b6f889f7b..2b0df88f49 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1545,10 +1545,8 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev,
return -1;
}
-#if 0
mdelay(10);
/* ohci_dump_status(ohci); */
-#endif
timeout = USB_TIMEOUT_MS(pipe);
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 2ee0f23b7e..1f2805270a 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -327,9 +327,7 @@ static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
csr = readw(&musbr->txcsr);
csr |= MUSB_CSR0_TXPKTRDY;
-#if !defined(CONFIG_SOC_DM365)
csr |= MUSB_CSR0_H_DIS_PING;
-#endif
writew(csr, &musbr->txcsr);
result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
if (result < 0)
@@ -352,9 +350,7 @@ static int ctrlreq_out_status_phase(struct usb_device *dev)
/* Set the StatusPkt bit */
csr = readw(&musbr->txcsr);
csr |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_H_STATUSPKT);
-#if !defined(CONFIG_SOC_DM365)
csr |= MUSB_CSR0_H_DIS_PING;
-#endif
writew(csr, &musbr->txcsr);
/* Wait until TXPKTRDY bit is cleared */
@@ -372,9 +368,7 @@ static int ctrlreq_in_status_phase(struct usb_device *dev)
/* Set the StatusPkt bit and ReqPkt bit */
csr = MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
-#if !defined(CONFIG_SOC_DM365)
csr |= MUSB_CSR0_H_DIS_PING;
-#endif
writew(csr, &musbr->txcsr);
result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);