summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig4
-rw-r--r--drivers/usb/common/Makefile7
-rw-r--r--drivers/usb/common/fsl-dt-fixup.c202
-rw-r--r--drivers/usb/eth/asix88179.c2
-rw-r--r--drivers/usb/eth/smsc95xx.c4
-rw-r--r--drivers/usb/gadget/Kconfig35
-rw-r--r--drivers/usb/gadget/bcm_udc_otg_phy.c4
-rw-r--r--drivers/usb/gadget/f_fastboot.c12
-rw-r--r--drivers/usb/host/Kconfig11
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-fsl.c197
-rw-r--r--drivers/usb/host/ehci-hcd.c6
-rw-r--r--drivers/usb/host/ehci-mpc512x.c6
-rw-r--r--drivers/usb/host/ehci-msm.c178
-rw-r--r--drivers/usb/host/ehci-mx5.c2
-rw-r--r--drivers/usb/host/ehci-mx6.c2
-rw-r--r--drivers/usb/host/ehci-mxc.c2
-rw-r--r--drivers/usb/host/ehci-sunxi.c24
-rw-r--r--drivers/usb/host/ehci-vf.c2
-rw-r--r--drivers/usb/host/ehci-zynq.c2
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/ohci-sunxi.c26
-rw-r--r--drivers/usb/host/xhci.c6
-rw-r--r--drivers/usb/musb-new/Kconfig7
-rw-r--r--drivers/usb/musb-new/Makefile1
-rw-r--r--drivers/usb/musb-new/linux-compat.h7
-rw-r--r--drivers/usb/musb-new/musb_core.c2
-rw-r--r--drivers/usb/musb-new/musb_regs.h2
-rw-r--r--drivers/usb/musb-new/musb_uboot.c4
-rw-r--r--drivers/usb/musb-new/pic32.c288
-rw-r--r--drivers/usb/musb-new/sunxi.c11
-rw-r--r--drivers/usb/ulpi/Kconfig33
-rw-r--r--drivers/usb/ulpi/ulpi-viewport.c5
33 files changed, 858 insertions, 238 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index abb06fcfe5..bccf43e4cf 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -53,6 +53,8 @@ source "drivers/usb/musb-new/Kconfig"
source "drivers/usb/emul/Kconfig"
+source "drivers/usb/ulpi/Kconfig"
+
comment "USB peripherals"
config USB_STORAGE
@@ -88,4 +90,6 @@ endchoice
endif
+source "drivers/usb/gadget/Kconfig"
+
endif
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
new file mode 100644
index 0000000000..2f3d43d939
--- /dev/null
+++ b/drivers/usb/common/Makefile
@@ -0,0 +1,7 @@
+# (C) Copyright 2016 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o
+obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o
diff --git a/drivers/usb/common/fsl-dt-fixup.c b/drivers/usb/common/fsl-dt-fixup.c
new file mode 100644
index 0000000000..6f31932c37
--- /dev/null
+++ b/drivers/usb/common/fsl-dt-fixup.c
@@ -0,0 +1,202 @@
+/*
+ * (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 <usb.h>
+#include <asm/io.h>
+#include <hwconfig.h>
+#include <fsl_usb.h>
+#include <fdt_support.h>
+
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
+
+static const char * const compat_usb_fsl[] = {
+ "fsl-usb2-mph",
+ "fsl-usb2-dr",
+ "snps,dwc3",
+ NULL
+};
+
+static int fdt_usb_get_node_type(void *blob, int start_offset,
+ int *node_offset, const char **node_type)
+{
+ int i;
+ int ret = -ENOENT;
+
+ for (i = 0; compat_usb_fsl[i]; i++) {
+ *node_offset = fdt_node_offset_by_compatible
+ (blob, start_offset,
+ compat_usb_fsl[i]);
+ if (*node_offset >= 0) {
+ *node_type = compat_usb_fsl[i];
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
+ const char *phy_type, int start_offset)
+{
+ const char *prop_mode = "dr_mode";
+ const char *prop_type = "phy_type";
+ const char *node_type = NULL;
+ int node_offset;
+ int err;
+
+ err = fdt_usb_get_node_type(blob, start_offset,
+ &node_offset, &node_type);
+ if (err < 0)
+ return err;
+
+ if (mode) {
+ err = fdt_setprop(blob, node_offset, prop_mode, mode,
+ strlen(mode) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_mode, node_type, fdt_strerror(err));
+ }
+
+ if (phy_type) {
+ err = fdt_setprop(blob, node_offset, prop_type, phy_type,
+ strlen(phy_type) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_type, node_type, fdt_strerror(err));
+ }
+
+ return node_offset;
+}
+
+static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
+ int start_offset)
+{
+ int node_offset, err;
+ const char *node_type = NULL;
+
+ err = fdt_usb_get_node_type(blob, start_offset,
+ &node_offset, &node_type);
+ if (err < 0)
+ return err;
+
+ err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0);
+ if (err < 0) {
+ printf("ERROR: could not set %s for %s: %s.\n",
+ prop_erratum, node_type, fdt_strerror(err));
+ }
+
+ return node_offset;
+}
+
+void fdt_fixup_dr_usb(void *blob, bd_t *bd)
+{
+ static const char * const modes[] = { "host", "peripheral", "otg" };
+ static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" };
+ int usb_erratum_a006261_off = -1;
+ int usb_erratum_a007075_off = -1;
+ int usb_erratum_a007792_off = -1;
+ int usb_erratum_a005697_off = -1;
+ int usb_mode_off = -1;
+ int usb_phy_off = -1;
+ char str[5];
+ int i, j;
+
+ for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
+ const char *dr_mode_type = NULL;
+ const char *dr_phy_type = NULL;
+ int mode_idx = -1, phy_idx = -1;
+
+ snprintf(str, 5, "%s%d", "usb", i);
+ if (hwconfig(str)) {
+ for (j = 0; j < ARRAY_SIZE(modes); j++) {
+ if (hwconfig_subarg_cmp(str, "dr_mode",
+ modes[j])) {
+ mode_idx = j;
+ break;
+ }
+ }
+
+ for (j = 0; j < ARRAY_SIZE(phys); j++) {
+ if (hwconfig_subarg_cmp(str, "phy_type",
+ phys[j])) {
+ phy_idx = j;
+ break;
+ }
+ }
+
+ if (mode_idx < 0 && phy_idx < 0) {
+ printf("WARNING: invalid phy or mode\n");
+ return;
+ }
+
+ if (mode_idx > -1)
+ dr_mode_type = modes[mode_idx];
+
+ if (phy_idx > -1)
+ dr_phy_type = phys[phy_idx];
+ }
+
+ if (has_dual_phy())
+ dr_phy_type = phys[2];
+
+ usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
+ dr_mode_type, NULL,
+ usb_mode_off);
+
+ if (usb_mode_off < 0)
+ return;
+
+ usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
+ NULL, dr_phy_type,
+ usb_phy_off);
+
+ if (usb_phy_off < 0)
+ return;
+
+ if (has_erratum_a006261()) {
+ usb_erratum_a006261_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a006261",
+ usb_erratum_a006261_off);
+ if (usb_erratum_a006261_off < 0)
+ return;
+ }
+
+ if (has_erratum_a007075()) {
+ usb_erratum_a007075_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a007075",
+ usb_erratum_a007075_off);
+ if (usb_erratum_a007075_off < 0)
+ return;
+ }
+
+ if (has_erratum_a007792()) {
+ usb_erratum_a007792_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a007792",
+ usb_erratum_a007792_off);
+ if (usb_erratum_a007792_off < 0)
+ return;
+ }
+ if (has_erratum_a005697()) {
+ usb_erratum_a005697_off = fdt_fixup_usb_erratum
+ (blob,
+ "fsl,usb-erratum-a005697",
+ usb_erratum_a005697_off);
+ if (usb_erratum_a005697_off < 0)
+ return;
+ }
+ }
+}
diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c
index cf4085d765..5e1ea8693b 100644
--- a/drivers/usb/eth/asix88179.c
+++ b/drivers/usb/eth/asix88179.c
@@ -497,7 +497,7 @@ static int asix_send(struct eth_device *eth, void *packet, int length)
length + sizeof(packet_len) + sizeof(tx_hdr2),
&actual_len,
USB_BULK_SEND_TIMEOUT);
- debug("Tx: len = %u, actual = %u, err = %d\n",
+ debug("Tx: len = %zu, actual = %u, err = %d\n",
length + sizeof(packet_len), actual_len, err);
return err;
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 3099bf4fd4..08eaed5c2e 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -188,10 +188,10 @@ static int smsc95xx_read_reg(struct usb_device *udev, u32 index, u32 *data)
len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
USB_VENDOR_REQUEST_READ_REGISTER,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, index, tmpbuf, sizeof(data),
+ 0, index, tmpbuf, sizeof(*data),
USB_CTRL_GET_TIMEOUT);
*data = tmpbuf[0];
- if (len != sizeof(data)) {
+ if (len != sizeof(*data)) {
debug("smsc95xx_read_reg failed: index=%d, len=%d",
index, len);
return -EIO;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
new file mode 100644
index 0000000000..f4698f469e
--- /dev/null
+++ b/drivers/usb/gadget/Kconfig
@@ -0,0 +1,35 @@
+#
+# USB Gadget support on a system involves
+# (a) a peripheral controller, and
+# (b) the gadget driver using it.
+#
+# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+# - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+menuconfig USB_GADGET
+ bool "USB Gadget Support"
+ help
+ USB is a master/slave protocol, organized with one master
+ host (such as a PC) controlling up to 127 peripheral devices.
+ The USB hardware is asymmetric, which makes it easier to set up:
+ you can't connect a "to-the-host" connector to a peripheral.
+
+ U-Boot can run in the host, or in the peripheral. In both cases
+ you need a low level bus controller driver, and some software
+ talking to it. Peripheral controllers are often discrete silicon,
+ or are integrated with the CPU in a microcontroller. The more
+ familiar host side controllers have names like "EHCI", "OHCI",
+ or "UHCI", and are usually integrated into southbridges on PC
+ motherboards.
+
+ Enable this configuration option if you want to run U-Boot inside
+ a USB peripheral device. Configure one hardware driver for your
+ peripheral/device side bus controller, and a "gadget driver" for
+ your peripheral protocol.
diff --git a/drivers/usb/gadget/bcm_udc_otg_phy.c b/drivers/usb/gadget/bcm_udc_otg_phy.c
index 10b2e132eb..877f162630 100644
--- a/drivers/usb/gadget/bcm_udc_otg_phy.c
+++ b/drivers/usb/gadget/bcm_udc_otg_phy.c
@@ -8,12 +8,16 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
#include "dwc2_udc_otg_priv.h"
#include "bcm_udc_otg.h"
void otg_phy_init(struct dwc2_udc *dev)
{
+ /* turn on the USB OTG clocks */
+ clk_usb_otg_enable((void *)HSOTG_BASE_ADDR);
+
/* set Phy to driving mode */
wfld_clear(HSOTG_CTRL_BASE_ADDR + HSOTG_CTRL_PHY_P1CTL_OFFSET,
HSOTG_CTRL_PHY_P1CTL_NON_DRIVING_MASK);
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index a54b4eebcc..2e87feeece 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -413,8 +413,16 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
else
strcpy(response, "FAILValue not set");
} else {
- printf("WARNING: unknown variable: %s\n", cmd);
- strcpy(response, "FAILVariable not implemented");
+ char envstr[32];
+
+ snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd);
+ s = getenv(envstr);
+ if (s) {
+ strncat(response, s, chars_left);
+ } else {
+ printf("WARNING: unknown variable: %s\n", cmd);
+ strcpy(response, "FAILVariable not implemented");
+ }
}
fastboot_tx_write_str(response);
}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 9332374193..d2363c8067 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -74,6 +74,17 @@ config USB_EHCI_MX6
---help---
Enables support for the on-chip EHCI controller on i.MX6 SoCs.
+config USB_EHCI_MSM
+ bool "Support for Qualcomm on-chip EHCI USB controller"
+ depends on DM_USB
+ select USB_ULPI_VIEWPORT
+ default n
+ ---help---
+ Enables support for the on-chip EHCI controller on Qualcomm
+ Snapdragon SoCs.
+ This driver supports combination of Chipidea USB controller
+ and Synapsys USB PHY in host mode only.
+
config USB_EHCI_GENERIC
bool "Support for generic EHCI USB controller"
depends on OF_CONTROL
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 9a87d2bf62..507519ea72 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,6 +43,7 @@ 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
obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o
obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 97b7f14542..a43d37de0b 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -12,7 +12,7 @@
#include <pci.h>
#include <usb.h>
#include <asm/io.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include <hwconfig.h>
#include <fsl_usb.h>
#include <fdt_support.h>
@@ -173,198 +173,3 @@ static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
cmd |= TXFIFO_THRESH(txfifo_thresh);
ehci_writel(&ehci->txfilltuning, cmd);
}
-
-#if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB)
-static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
- const char *phy_type, int start_offset)
-{
- const char *compat_dr = "fsl-usb2-dr";
- const char *compat_mph = "fsl-usb2-mph";
- const char *prop_mode = "dr_mode";
- const char *prop_type = "phy_type";
- const char *node_type = NULL;
- int node_offset;
- int err;
-
- node_offset = fdt_node_offset_by_compatible(blob,
- start_offset, compat_mph);
- if (node_offset < 0) {
- node_offset = fdt_node_offset_by_compatible(blob,
- start_offset,
- compat_dr);
- if (node_offset < 0) {
- printf("WARNING: could not find compatible node: %s",
- fdt_strerror(node_offset));
- return -1;
- }
- node_type = compat_dr;
- } else {
- node_type = compat_mph;
- }
-
- if (mode) {
- err = fdt_setprop(blob, node_offset, prop_mode, mode,
- strlen(mode) + 1);
- if (err < 0)
- printf("WARNING: could not set %s for %s: %s.\n",
- prop_mode, node_type, fdt_strerror(err));
- }
-
- if (phy_type) {
- err = fdt_setprop(blob, node_offset, prop_type, phy_type,
- strlen(phy_type) + 1);
- if (err < 0)
- printf("WARNING: could not set %s for %s: %s.\n",
- prop_type, node_type, fdt_strerror(err));
- }
-
- return node_offset;
-}
-
-static const char *fdt_usb_get_node_type(void *blob, int start_offset,
- int *node_offset)
-{
- const char *compat_dr = "fsl-usb2-dr";
- const char *compat_mph = "fsl-usb2-mph";
- const char *node_type = NULL;
-
- *node_offset = fdt_node_offset_by_compatible(blob, start_offset,
- compat_mph);
- if (*node_offset < 0) {
- *node_offset = fdt_node_offset_by_compatible(blob,
- start_offset,
- compat_dr);
- if (*node_offset < 0) {
- printf("ERROR: could not find compatible node: %s\n",
- fdt_strerror(*node_offset));
- } else {
- node_type = compat_dr;
- }
- } else {
- node_type = compat_mph;
- }
-
- return node_type;
-}
-
-static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
- int start_offset)
-{
- int node_offset, err;
- const char *node_type = NULL;
-
- node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset);
- if (!node_type)
- return -1;
-
- err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0);
- if (err < 0) {
- printf("ERROR: could not set %s for %s: %s.\n",
- prop_erratum, node_type, fdt_strerror(err));
- }
-
- return node_offset;
-}
-
-void fdt_fixup_dr_usb(void *blob, bd_t *bd)
-{
- static const char * const modes[] = { "host", "peripheral", "otg" };
- static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" };
- int usb_erratum_a006261_off = -1;
- int usb_erratum_a007075_off = -1;
- int usb_erratum_a007792_off = -1;
- int usb_erratum_a005697_off = -1;
- int usb_mode_off = -1;
- int usb_phy_off = -1;
- char str[5];
- int i, j;
-
- for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
- const char *dr_mode_type = NULL;
- const char *dr_phy_type = NULL;
- int mode_idx = -1, phy_idx = -1;
-
- snprintf(str, 5, "%s%d", "usb", i);
- if (hwconfig(str)) {
- for (j = 0; j < ARRAY_SIZE(modes); j++) {
- if (hwconfig_subarg_cmp(str, "dr_mode",
- modes[j])) {
- mode_idx = j;
- break;
- }
- }
-
- for (j = 0; j < ARRAY_SIZE(phys); j++) {
- if (hwconfig_subarg_cmp(str, "phy_type",
- phys[j])) {
- phy_idx = j;
- break;
- }
- }
-
- if (mode_idx < 0 && phy_idx < 0) {
- printf("WARNING: invalid phy or mode\n");
- return;
- }
-
- if (mode_idx > -1)
- dr_mode_type = modes[mode_idx];
-
- if (phy_idx > -1)
- dr_phy_type = phys[phy_idx];
- }
-
- if (has_dual_phy())
- dr_phy_type = phys[2];
-
- usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
- dr_mode_type, NULL,
- usb_mode_off);
-
- if (usb_mode_off < 0)
- return;
-
- usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
- NULL, dr_phy_type,
- usb_phy_off);
-
- if (usb_phy_off < 0)
- return;
-
- if (has_erratum_a006261()) {
- usb_erratum_a006261_off = fdt_fixup_usb_erratum
- (blob,
- "fsl,usb-erratum-a006261",
- usb_erratum_a006261_off);
- if (usb_erratum_a006261_off < 0)
- return;
- }
-
- if (has_erratum_a007075()) {
- usb_erratum_a007075_off = fdt_fixup_usb_erratum
- (blob,
- "fsl,usb-erratum-a007075",
- usb_erratum_a007075_off);
- if (usb_erratum_a007075_off < 0)
- return;
- }
-
- if (has_erratum_a007792()) {
- usb_erratum_a007792_off = fdt_fixup_usb_erratum
- (blob,
- "fsl,usb-erratum-a007792",
- usb_erratum_a007792_off);
- if (usb_erratum_a007792_off < 0)
- return;
- }
- if (has_erratum_a005697()) {
- usb_erratum_a005697_off = fdt_fixup_usb_erratum
- (blob,
- "fsl,usb-erratum-a005697",
- usb_erratum_a005697_off);
- if (usb_erratum_a005697_off < 0)
- return;
- }
- }
-}
-#endif
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0113c6c11c..fa5d584b82 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1615,6 +1615,12 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
if (ret)
goto err;
+ if (ctrl->ops.init_after_reset) {
+ ret = ctrl->ops.init_after_reset(ctrl);
+ if (ret)
+ goto err;
+ }
+
ret = ehci_common_init(ctrl, tweaks);
if (ret)
goto err;
diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c
index b320c4a4e2..bb4f461613 100644
--- a/drivers/usb/host/ehci-mpc512x.c
+++ b/drivers/usb/host/ehci-mpc512x.c
@@ -17,7 +17,7 @@
#include <pci.h>
#include <usb.h>
#include <asm/io.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include "ehci.h"
@@ -93,7 +93,7 @@ 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);
+ out_be32(&(ehci->usbcmd), CMD_RESET);
/* Wait for the reset process to finish */
for (i = 65535 ; i > 0 ; i--) {
@@ -101,7 +101,7 @@ static int reset_usb_controller(volatile struct usb_ehci *ehci)
* The host will set this bit to zero once the
* reset process is complete
*/
- if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0)
+ if ((in_be32(&(ehci->usbcmd)) & CMD_RESET) == 0)
return 0;
}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
new file mode 100644
index 0000000000..6484c1c334
--- /dev/null
+++ b/drivers/usb/host/ehci-msm.c
@@ -0,0 +1,178 @@
+/*
+ * Qualcomm EHCI driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on Linux driver
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <usb.h>
+#include <usb/ehci-ci.h>
+#include <usb/ulpi.h>
+#include <wait_bit.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <linux/compat.h>
+#include "ehci.h"
+
+/* PHY viewport regs */
+#define ULPI_MISC_A_READ 0x96
+#define ULPI_MISC_A_SET 0x97
+#define ULPI_MISC_A_CLEAR 0x98
+#define ULPI_MISC_A_VBUSVLDEXTSEL (1 << 1)
+#define ULPI_MISC_A_VBUSVLDEXT (1 << 0)
+
+#define GEN2_SESS_VLD_CTRL_EN (1 << 7)
+
+#define SESS_VLD_CTRL (1 << 25)
+
+struct msm_ehci_priv {
+ struct ehci_ctrl ctrl; /* Needed by EHCI */
+ struct usb_ehci *ehci; /* Start of IP core*/
+ struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
+};
+
+int __weak board_prepare_usb(enum usb_init_type type)
+{
+ return 0;
+}
+
+static void setup_usb_phy(struct msm_ehci_priv *priv)
+{
+ /* Select and enable external configuration with USB PHY */
+ ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_SET,
+ ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+}
+
+static void reset_usb_phy(struct msm_ehci_priv *priv)
+{
+ /* Disable VBUS mimicing in the controller. */
+ ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
+ ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+}
+
+
+static int msm_init_after_reset(struct ehci_ctrl *dev)
+{
+ struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl);
+ struct usb_ehci *ehci = p->ehci;
+
+ /* select ULPI phy */
+ writel(PORT_PTS_ULPI, &ehci->portsc);
+ setup_usb_phy(p);
+
+ /* Enable sess_vld */
+ setbits_le32(&ehci->genconfig2, GEN2_SESS_VLD_CTRL_EN);
+
+ /* Enable external vbus configuration in the LINK */
+ setbits_le32(&ehci->usbcmd, SESS_VLD_CTRL);
+
+ /* USB_OTG_HS_AHB_BURST */
+ writel(0x0, &ehci->sbuscfg);
+
+ /* USB_OTG_HS_AHB_MODE: HPROT_MODE */
+ /* Bus access related config. */
+ writel(0x08, &ehci->sbusmode);
+
+ /* set mode to host controller */
+ writel(CM_HOST, &ehci->usbmode);
+
+ return 0;
+}
+
+static const struct ehci_ops msm_ehci_ops = {
+ .init_after_reset = msm_init_after_reset
+};
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+ struct msm_ehci_priv *p = dev_get_priv(dev);
+ struct usb_ehci *ehci = p->ehci;
+ struct ehci_hccr *hccr;
+ struct ehci_hcor *hcor;
+ int ret;
+
+ hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength);
+ hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
+ HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
+
+ ret = board_prepare_usb(USB_INIT_HOST);
+ if (ret < 0)
+ return ret;
+
+ return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0, USB_INIT_HOST);
+}
+
+static int ehci_usb_remove(struct udevice *dev)
+{
+ struct msm_ehci_priv *p = dev_get_priv(dev);
+ struct usb_ehci *ehci = p->ehci;
+ int ret;
+
+ ret = ehci_deregister(dev);
+ if (ret)
+ return ret;
+
+ /* Stop controller. */
+ clrbits_le32(&ehci->usbcmd, CMD_RUN);
+
+ reset_usb_phy(p);
+
+ ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */
+ if (ret < 0)
+ return ret;
+
+ /* Reset controller */
+ setbits_le32(&ehci->usbcmd, CMD_RESET);
+
+ /* Wait for reset */
+ if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
+ false)) {
+ printf("Stuck on USB reset.\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+ struct msm_ehci_priv *priv = dev_get_priv(dev);
+
+ priv->ulpi_vp.port_num = 0;
+ priv->ehci = (void *)dev_get_addr(dev);
+
+ if (priv->ehci == (void *)FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ /* Warning: this will not work if viewport address is > 64 bit due to
+ * ULPI design.
+ */
+ priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
+
+ return 0;
+}
+
+static const struct udevice_id ehci_usb_ids[] = {
+ { .compatible = "qcom,ehci-host", },
+ { }
+};
+
+U_BOOT_DRIVER(usb_ehci) = {
+ .name = "ehci_msm",
+ .id = UCLASS_USB,
+ .of_match = ehci_usb_ids,
+ .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+ .probe = ehci_usb_probe,
+ .remove = ehci_usb_remove,
+ .ops = &ehci_usb_ops,
+ .priv_auto_alloc_size = sizeof(struct msm_ehci_priv),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c
index d3199622eb..2b36cebdb3 100644
--- a/drivers/usb/host/ehci-mx5.c
+++ b/drivers/usb/host/ehci-mx5.c
@@ -9,7 +9,7 @@
#include <usb.h>
#include <errno.h>
#include <linux/compiler.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index e1c67f77d7..a981b50fda 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -10,7 +10,7 @@
#include <errno.h>
#include <wait_bit.h>
#include <linux/compiler.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index f09c75a9b6..f8324eef76 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -9,7 +9,7 @@
#include <usb.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include <errno.h>
#include "ehci.h"
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
index cf3dcc4327..f2d83e34bc 100644
--- a/drivers/usb/host/ehci-sunxi.c
+++ b/drivers/usb/host/ehci-sunxi.c
@@ -17,6 +17,14 @@
#include <dm.h>
#include "ehci.h"
+#ifdef CONFIG_SUNXI_GEN_SUN4I
+#define BASE_DIST 0x8000
+#define AHB_CLK_DIST 2
+#else
+#define BASE_DIST 0x1000
+#define AHB_CLK_DIST 1
+#endif
+
struct ehci_sunxi_priv {
struct ehci_ctrl ehci;
int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
@@ -30,6 +38,7 @@ static int ehci_usb_probe(struct udevice *dev)
struct ehci_sunxi_priv *priv = dev_get_priv(dev);
struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev);
struct ehci_hcor *hcor;
+ int extra_ahb_gate_mask = 0;
/*
* This should go away once we've moved to the driver model for
@@ -37,14 +46,18 @@ static int ehci_usb_probe(struct udevice *dev)
*/
priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
#ifdef CONFIG_MACH_SUN8I_H3
- priv->ahb_gate_mask |= 1 << AHB_GATE_OFFSET_USB_OHCI0;
+ extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
#endif
- priv->phy_index = ((u32)hccr - SUNXI_USB1_BASE) / 0x1000 + 1;
- priv->ahb_gate_mask <<= priv->phy_index - 1;
+ priv->phy_index = ((u32)hccr - SUNXI_USB1_BASE) / BASE_DIST;
+ priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
+ extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
+ priv->phy_index++; /* Non otg phys start at 1 */
- setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
+ setbits_le32(&ccm->ahb_gate0,
+ priv->ahb_gate_mask | extra_ahb_gate_mask);
#ifdef CONFIG_SUNXI_GEN_SUN6I
- setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
+ setbits_le32(&ccm->ahb_reset0_cfg,
+ priv->ahb_gate_mask | extra_ahb_gate_mask);
#endif
sunxi_usb_phy_init(priv->phy_index);
@@ -82,6 +95,7 @@ static const struct udevice_id ehci_usb_ids[] = {
{ .compatible = "allwinner,sun6i-a31-ehci", },
{ .compatible = "allwinner,sun7i-a20-ehci", },
{ .compatible = "allwinner,sun8i-a23-ehci", },
+ { .compatible = "allwinner,sun8i-a83t-ehci", },
{ .compatible = "allwinner,sun8i-h3-ehci", },
{ .compatible = "allwinner,sun9i-a80-ehci", },
{ }
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 335e303c2a..61789dddc3 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -17,7 +17,7 @@
#include <asm/arch/crm_regs.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/imx-common/regs-usbphy.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include "ehci.h"
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c
index 7770d05646..37a7935b43 100644
--- a/drivers/usb/host/ehci-zynq.c
+++ b/drivers/usb/host/ehci-zynq.c
@@ -11,7 +11,7 @@
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <usb.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
#include <usb/ulpi.h>
#include "ehci.h"
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 826b3fe580..734d7f0362 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -240,6 +240,7 @@ struct ehci_ops {
void (*powerup_fixup)(struct ehci_ctrl *ctrl, uint32_t *status_reg,
uint32_t *reg);
uint32_t *(*get_portsc_register)(struct ehci_ctrl *ctrl, int port);
+ int (*init_after_reset)(struct ehci_ctrl *ctrl);
};
struct ehci_ctrl {
diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c
index 1b1f651697..2a1e8bf1e8 100644
--- a/drivers/usb/host/ohci-sunxi.c
+++ b/drivers/usb/host/ohci-sunxi.c
@@ -17,6 +17,14 @@
#include <usb.h>
#include "ohci.h"
+#ifdef CONFIG_SUNXI_GEN_SUN4I
+#define BASE_DIST 0x8000
+#define AHB_CLK_DIST 2
+#else
+#define BASE_DIST 0x1000
+#define AHB_CLK_DIST 1
+#endif
+
struct ohci_sunxi_priv {
ohci_t ohci;
int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
@@ -30,6 +38,7 @@ static int ohci_usb_probe(struct udevice *dev)
struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
struct ohci_sunxi_priv *priv = dev_get_priv(dev);
struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
+ int extra_ahb_gate_mask = 0;
bus_priv->companion = true;
@@ -39,17 +48,21 @@ static int ohci_usb_probe(struct udevice *dev)
*/
priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
#ifdef CONFIG_MACH_SUN8I_H3
- priv->ahb_gate_mask |= 1 << AHB_GATE_OFFSET_USB_EHCI0;
+ extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
#endif
priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
- priv->phy_index = ((u32)regs - (SUNXI_USB1_BASE + 0x400)) / 0x1000 + 1;
- priv->ahb_gate_mask <<= priv->phy_index - 1;
- priv->usb_gate_mask <<= priv->phy_index - 1;
+ priv->phy_index = ((u32)regs - (SUNXI_USB1_BASE + 0x400)) / BASE_DIST;
+ priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
+ extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
+ priv->usb_gate_mask <<= priv->phy_index;
+ priv->phy_index++; /* Non otg phys start at 1 */
- setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
+ setbits_le32(&ccm->ahb_gate0,
+ priv->ahb_gate_mask | extra_ahb_gate_mask);
setbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask);
#ifdef CONFIG_SUNXI_GEN_SUN6I
- setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
+ setbits_le32(&ccm->ahb_reset0_cfg,
+ priv->ahb_gate_mask | extra_ahb_gate_mask);
#endif
sunxi_usb_phy_init(priv->phy_index);
@@ -85,6 +98,7 @@ static const struct udevice_id ohci_usb_ids[] = {
{ .compatible = "allwinner,sun6i-a31-ohci", },
{ .compatible = "allwinner,sun7i-a20-ohci", },
{ .compatible = "allwinner,sun8i-a23-ohci", },
+ { .compatible = "allwinner,sun8i-a83t-ohci", },
{ .compatible = "allwinner,sun8i-h3-ohci", },
{ .compatible = "allwinner,sun9i-a80-ohci", },
{ }
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ca598aa5e6..cb8a04b793 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -941,10 +941,12 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
if (usb_pipedevice(pipe) == ctrl->rootdev)
return xhci_submit_root(udev, pipe, buffer, setup);
- if (setup->request == USB_REQ_SET_ADDRESS)
+ if (setup->request == USB_REQ_SET_ADDRESS &&
+ (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD)
return xhci_address_device(udev, root_portnr);
- if (setup->request == USB_REQ_SET_CONFIGURATION) {
+ if (setup->request == USB_REQ_SET_CONFIGURATION &&
+ (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
ret = xhci_set_configuration(udev);
if (ret) {
puts("Failed to configure xHCI endpoint\n");
diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig
index 6a6cb93b4c..4e8a5432ef 100644
--- a/drivers/usb/musb-new/Kconfig
+++ b/drivers/usb/musb-new/Kconfig
@@ -15,6 +15,13 @@ config USB_MUSB_GADGET
if USB_MUSB_HOST || USB_MUSB_GADGET
+config USB_MUSB_PIC32
+ bool "Enable Microchip PIC32 DRC USB controller"
+ depends on DM_USB && MACH_PIC32
+ help
+ Say y to enable PIC32 USB DRC controller support
+ if it is available on your Microchip PIC32 platform.
+
config USB_MUSB_SUNXI
bool "Enable sunxi OTG / DRC USB controller"
depends on ARCH_SUNXI
diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile
index 072d516a03..df1c3c8a45 100644
--- a/drivers/usb/musb-new/Makefile
+++ b/drivers/usb/musb-new/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_MUSB_HOST) += musb_host.o musb_core.o musb_uboot.o
obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o
obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o
obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
+obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o
obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
ccflags-y := $(call cc-option,-Wno-unused-variable) \
diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h
index 1fc9391b8e..9244977579 100644
--- a/drivers/usb/musb-new/linux-compat.h
+++ b/drivers/usb/musb-new/linux-compat.h
@@ -13,13 +13,6 @@
printf(fmt, ##args); \
ret_warn; })
-#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s)
-#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s)
-#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s)
-#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s)
-#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s)
-#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s)
-
#define device_init_wakeup(dev, a) do {} while (0)
#define platform_data device_data
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index a6d6af60e7..dd0443c02e 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -259,7 +259,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
}
}
-#if !defined(CONFIG_USB_MUSB_AM35X)
+#if !defined(CONFIG_USB_MUSB_AM35X) && !defined(CONFIG_USB_MUSB_PIC32)
/*
* Unload an endpoint's FIFO
*/
diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h
index 4dc9abbe02..0f18dd7f7e 100644
--- a/drivers/usb/musb-new/musb_regs.h
+++ b/drivers/usb/musb-new/musb_regs.h
@@ -434,7 +434,7 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
static inline u8 musb_read_configdata(void __iomem *mbase)
{
-#ifdef CONFIG_MACH_SUN8I_A33
+#if defined CONFIG_MACH_SUN8I_A33 || defined CONFIG_MACH_SUN8I_A83T
/* <Sigh> allwinner saves a reg, and we need to hardcode this */
return 0xde;
#else
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 233a0e4a5e..6ce528c81e 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -237,8 +237,10 @@ int musb_lowlevel_init(struct musb_host_data *host)
if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
break;
} while (get_timer(0) < timeout);
- if (get_timer(0) >= timeout)
+ if (get_timer(0) >= timeout) {
+ musb_stop(host->host);
return -ENODEV;
+ }
_musb_reset_root_port(host, NULL);
host->host->is_active = 1;
diff --git a/drivers/usb/musb-new/pic32.c b/drivers/usb/musb-new/pic32.c
new file mode 100644
index 0000000000..c888c645fa
--- /dev/null
+++ b/drivers/usb/musb-new/pic32.c
@@ -0,0 +1,288 @@
+/*
+ * Microchip PIC32 MUSB "glue layer"
+ *
+ * Copyright (C) 2015, Microchip Technology Inc.
+ * Cristian Birsan <cristian.birsan@microchip.com>
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Based on the dsps "glue layer" code.
+ */
+
+#include <common.h>
+#include <linux/usb/musb.h>
+#include "linux-compat.h"
+#include "musb_core.h"
+#include "musb_uboot.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PIC32_TX_EP_MASK 0x0f /* EP0 + 7 Tx EPs */
+#define PIC32_RX_EP_MASK 0x0e /* 7 Rx EPs */
+
+#define MUSB_SOFTRST 0x7f
+#define MUSB_SOFTRST_NRST BIT(0)
+#define MUSB_SOFTRST_NRSTX BIT(1)
+
+#define USBCRCON 0
+#define USBCRCON_USBWKUPEN BIT(0) /* Enable Wakeup Interrupt */
+#define USBCRCON_USBRIE BIT(1) /* Enable Remote resume Interrupt */
+#define USBCRCON_USBIE BIT(2) /* Enable USB General interrupt */
+#define USBCRCON_SENDMONEN BIT(3) /* Enable Session End VBUS monitoring */
+#define USBCRCON_BSVALMONEN BIT(4) /* Enable B-Device VBUS monitoring */
+#define USBCRCON_ASVALMONEN BIT(5) /* Enable A-Device VBUS monitoring */
+#define USBCRCON_VBUSMONEN BIT(6) /* Enable VBUS monitoring */
+#define USBCRCON_PHYIDEN BIT(7) /* PHY ID monitoring enable */
+#define USBCRCON_USBIDVAL BIT(8) /* USB ID value */
+#define USBCRCON_USBIDOVEN BIT(9) /* USB ID override enable */
+#define USBCRCON_USBWK BIT(24) /* USB Wakeup Status */
+#define USBCRCON_USBRF BIT(25) /* USB Resume Status */
+#define USBCRCON_USBIF BIT(26) /* USB General Interrupt Status */
+
+/* PIC32 controller data */
+struct pic32_musb_data {
+ struct musb_host_data mdata;
+ struct device dev;
+ void __iomem *musb_glue;
+};
+
+#define to_pic32_musb_data(d) \
+ container_of(d, struct pic32_musb_data, dev)
+
+static void pic32_musb_disable(struct musb *musb)
+{
+ /* no way to shut the controller */
+}
+
+static int pic32_musb_enable(struct musb *musb)
+{
+ /* soft reset by NRSTx */
+ musb_writeb(musb->mregs, MUSB_SOFTRST, MUSB_SOFTRST_NRSTX);
+ /* set mode */
+ musb_platform_set_mode(musb, musb->board_mode);
+
+ return 0;
+}
+
+static irqreturn_t pic32_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr;
+
+ /* ack usb core interrupts */
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ if (musb->int_usb)
+ musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
+
+ /* ack endpoint interrupts */
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) & PIC32_RX_EP_MASK;
+ if (musb->int_rx)
+ musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);
+
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) & PIC32_TX_EP_MASK;
+ if (musb->int_tx)
+ musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
+
+ /* drop spurious RX and TX if device is disconnected */
+ if (musb->int_usb & MUSB_INTR_DISCONNECT) {
+ musb->int_tx = 0;
+ musb->int_rx = 0;
+ }
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb)
+ ret = musb_interrupt(musb);
+
+ return ret;
+}
+
+static int pic32_musb_set_mode(struct musb *musb, u8 mode)
+{
+ struct device *dev = musb->controller;
+ struct pic32_musb_data *pdata = to_pic32_musb_data(dev);
+
+ switch (mode) {
+ case MUSB_HOST:
+ clrsetbits_le32(pdata->musb_glue + USBCRCON,
+ USBCRCON_USBIDVAL, USBCRCON_USBIDOVEN);
+ break;
+ case MUSB_PERIPHERAL:
+ setbits_le32(pdata->musb_glue + USBCRCON,
+ USBCRCON_USBIDVAL | USBCRCON_USBIDOVEN);
+ break;
+ case MUSB_OTG:
+ dev_err(dev, "support for OTG is unimplemented\n");
+ break;
+ default:
+ dev_err(dev, "unsupported mode %d\n", mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pic32_musb_init(struct musb *musb)
+{
+ struct pic32_musb_data *pdata = to_pic32_musb_data(musb->controller);
+ u32 ctrl, hwvers;
+ u8 power;
+
+ /* Returns zero if not clocked */
+ hwvers = musb_read_hwvers(musb->mregs);
+ if (!hwvers)
+ return -ENODEV;
+
+ /* Reset the musb */
+ power = musb_readb(musb->mregs, MUSB_POWER);
+ power = power | MUSB_POWER_RESET;
+ musb_writeb(musb->mregs, MUSB_POWER, power);
+ mdelay(100);
+
+ /* Start the on-chip PHY and its PLL. */
+ power = power & ~MUSB_POWER_RESET;
+ musb_writeb(musb->mregs, MUSB_POWER, power);
+
+ musb->isr = pic32_interrupt;
+
+ ctrl = USBCRCON_USBIF | USBCRCON_USBRF |
+ USBCRCON_USBWK | USBCRCON_USBIDOVEN |
+ USBCRCON_PHYIDEN | USBCRCON_USBIE |
+ USBCRCON_USBRIE | USBCRCON_USBWKUPEN |
+ USBCRCON_VBUSMONEN;
+ writel(ctrl, pdata->musb_glue + USBCRCON);
+
+ return 0;
+}
+
+/* PIC32 supports only 32bit read operation */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+ void __iomem *fifo = hw_ep->fifo;
+ u32 val, rem = len % 4;
+
+ /* USB stack ensures dst is always 32bit aligned. */
+ readsl(fifo, dst, len / 4);
+ if (rem) {
+ dst += len & ~0x03;
+ val = musb_readl(fifo, 0);
+ memcpy(dst, &val, rem);
+ }
+}
+
+const struct musb_platform_ops pic32_musb_ops = {
+ .init = pic32_musb_init,
+ .set_mode = pic32_musb_set_mode,
+ .disable = pic32_musb_disable,
+ .enable = pic32_musb_enable,
+};
+
+/* PIC32 default FIFO config - fits in 8KB */
+static struct musb_fifo_cfg pic32_musb_fifo_config[] = {
+ { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, },
+ { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, },
+ { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, },
+};
+
+static struct musb_hdrc_config pic32_musb_config = {
+ .fifo_cfg = pic32_musb_fifo_config,
+ .fifo_cfg_size = ARRAY_SIZE(pic32_musb_fifo_config),
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 8,
+ .ram_bits = 11,
+};
+
+/* PIC32 has one MUSB controller which can be host or gadget */
+static struct musb_hdrc_platform_data pic32_musb_plat = {
+ .mode = MUSB_HOST,
+ .config = &pic32_musb_config,
+ .power = 250, /* 500mA */
+ .platform_ops = &pic32_musb_ops,
+};
+
+static int musb_usb_probe(struct udevice *dev)
+{
+ struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+ struct pic32_musb_data *pdata = dev_get_priv(dev);
+ struct musb_host_data *mdata = &pdata->mdata;
+ struct fdt_resource mc, glue;
+ void *fdt = (void *)gd->fdt_blob;
+ int node = dev->of_offset;
+ void __iomem *mregs;
+ int ret;
+
+ priv->desc_before_addr = true;
+
+ ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+ "mc", &mc);
+ if (ret < 0) {
+ printf("pic32-musb: resource \"mc\" not found\n");
+ return ret;
+ }
+
+ ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+ "control", &glue);
+ if (ret < 0) {
+ printf("pic32-musb: resource \"control\" not found\n");
+ return ret;
+ }
+
+ mregs = ioremap(mc.start, fdt_resource_size(&mc));
+ pdata->musb_glue = ioremap(glue.start, fdt_resource_size(&glue));
+
+ /* init controller */
+#ifdef CONFIG_USB_MUSB_HOST
+ mdata->host = musb_init_controller(&pic32_musb_plat,
+ &pdata->dev, mregs);
+ if (!mdata->host)
+ return -EIO;
+
+ ret = musb_lowlevel_init(mdata);
+#else
+ pic32_musb_plat.mode = MUSB_PERIPHERAL;
+ ret = musb_register(&pic32_musb_plat, &pdata->dev, mregs);
+#endif
+ if (ret == 0)
+ printf("PIC32 MUSB OTG\n");
+
+ return ret;
+}
+
+static int musb_usb_remove(struct udevice *dev)
+{
+ struct pic32_musb_data *pdata = dev_get_priv(dev);
+
+ musb_stop(pdata->mdata.host);
+
+ return 0;
+}
+
+static const struct udevice_id pic32_musb_ids[] = {
+ { .compatible = "microchip,pic32mzda-usb" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_musb) = {
+ .name = "pic32-musb",
+ .id = UCLASS_USB,
+ .of_match = pic32_musb_ids,
+ .probe = musb_usb_probe,
+ .remove = musb_usb_remove,
+#ifdef CONFIG_USB_MUSB_HOST
+ .ops = &musb_usb_ops,
+#endif
+ .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+ .priv_auto_alloc_size = sizeof(struct pic32_musb_data),
+};
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index be1d2ec8e4..3081afca0e 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -201,6 +201,7 @@ static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
/* musb_core does not call enable / disable in a balanced manner <sigh> */
static bool enabled = false;
+static struct musb *sunxi_musb;
static int sunxi_musb_enable(struct musb *musb)
{
@@ -320,13 +321,15 @@ int musb_usb_probe(struct udevice *dev)
priv->desc_before_addr = true;
- if (!host->host) {
- host->host = musb_init_controller(&musb_plat, NULL,
+ if (!sunxi_musb) {
+ sunxi_musb = musb_init_controller(&musb_plat, NULL,
(void *)SUNXI_USB0_BASE);
- if (!host->host)
- return -EIO;
}
+ host->host = sunxi_musb;
+ if (!host->host)
+ return -EIO;
+
ret = musb_lowlevel_init(host);
if (ret == 0)
printf("MUSB OTG\n");
diff --git a/drivers/usb/ulpi/Kconfig b/drivers/usb/ulpi/Kconfig
new file mode 100644
index 0000000000..329d2df3ed
--- /dev/null
+++ b/drivers/usb/ulpi/Kconfig
@@ -0,0 +1,33 @@
+comment "ULPI drivers"
+
+choice
+ prompt "ULPI Viewport type"
+ optional
+ default n
+ help
+ Select ULPI viewport (SoC-side interface to ULPI) implementation
+ appropriate for the device if you want to communicate with
+ UTMI (USB PHY) via ULPI interface.
+
+config USB_ULPI_VIEWPORT
+ bool "Generic ULPI Viewport"
+ help
+ Support generic ULPI Viewport implementation that is used on
+ some Tegra and Snapdragon devices.
+
+config USB_ULPI_VIEWPORT_OMAP
+ bool "OMAP ULPI Viewport"
+ help
+ Support ULPI Viewport implementation that is used on OMAP devices.
+
+endchoice
+
+config USB_ULPI
+ bool "ULPI support"
+ depends on (USB_ULPI_VIEWPORT || USB_ULPI_VIEWPORT_OMAP)
+ help
+ Select to commnicate with USB PHY via ULPI interface.
+ ULPI is wrapper on UTMI+ core that is used as
+ PHY Transreceiver for USB controllers.
+
+ This driver uses ULPI viewports that are specific for each SoC.
diff --git a/drivers/usb/ulpi/ulpi-viewport.c b/drivers/usb/ulpi/ulpi-viewport.c
index 72a06de910..d111680472 100644
--- a/drivers/usb/ulpi/ulpi-viewport.c
+++ b/drivers/usb/ulpi/ulpi-viewport.c
@@ -92,7 +92,8 @@ static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value)
int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)
{
- u32 val = ULPI_RWRUN | ULPI_RWCTRL | ((u32)reg << 16) | (value & 0xff);
+ u32 addr = (uintptr_t)reg & 0xFF;
+ u32 val = ULPI_RWRUN | ULPI_RWCTRL | addr << 16 | (value & 0xff);
val |= (ulpi_vp->port_num & 0x7) << 24;
return ulpi_request(ulpi_vp, val);
@@ -101,7 +102,7 @@ int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)
u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg)
{
int err;
- u32 val = ULPI_RWRUN | ((u32)reg << 16);
+ u32 val = ULPI_RWRUN | ((uintptr_t)reg & 0xFF) << 16;
val |= (ulpi_vp->port_num & 0x7) << 24;
err = ulpi_request(ulpi_vp, val);