summaryrefslogtreecommitdiffstats
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/eth/asix.c237
-rw-r--r--drivers/usb/eth/usb_ether.c131
-rw-r--r--drivers/usb/host/ehci-hcd.c17
-rw-r--r--drivers/usb/host/ehci-pci.c112
-rw-r--r--drivers/usb/host/ehci.h15
-rw-r--r--drivers/usb/host/r8a66597-hcd.c14
-rw-r--r--drivers/usb/host/r8a66597.h14
-rw-r--r--drivers/usb/host/usb-uclass.c79
-rw-r--r--drivers/usb/musb-new/am35x.c7
-rw-r--r--drivers/usb/musb-new/musb_core.c20
-rw-r--r--drivers/usb/musb-new/musb_core.h18
-rw-r--r--drivers/usb/musb-new/musb_dsps.c6
-rw-r--r--drivers/usb/musb-new/musb_gadget_ep0.c1
-rw-r--r--drivers/usb/musb-new/musb_host.c4
-rw-r--r--drivers/usb/musb-new/musb_uboot.c211
-rw-r--r--drivers/usb/musb-new/musb_uboot.h28
-rw-r--r--drivers/usb/musb-new/omap2430.c5
-rw-r--r--drivers/usb/musb-new/sunxi.c5
-rw-r--r--drivers/usb/musb-new/usb-compat.h70
20 files changed, 786 insertions, 212 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 637ef3d567..3fa5b2e37e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -46,8 +46,8 @@ config DM_USB
Much of the code is shared but with this option enabled the USB
uclass takes care of device enumeration. USB devices can be
- declared with the USB_DEVICE() macro and will be automatically
- probed when found on the bus.
+ declared with the U_BOOT_USB_DEVICE() macro and will be
+ automatically probed when found on the bus.
source "drivers/usb/host/Kconfig"
diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
index c8697ae78d..72ec41ea89 100644
--- a/drivers/usb/eth/asix.c
+++ b/drivers/usb/eth/asix.c
@@ -5,11 +5,11 @@
*/
#include <common.h>
+#include <dm.h>
#include <usb.h>
+#include <malloc.h>
#include <linux/mii.h>
#include "usb_ether.h"
-#include <malloc.h>
-
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
@@ -92,14 +92,20 @@
#define FLAG_TYPE_AX88772B (1U << 2)
#define FLAG_EEPROM_MAC (1U << 3) /* initial mac address in eeprom */
-/* local vars */
-static int curr_eth_dev; /* index for name of next device detected */
/* driver private */
struct asix_private {
int flags;
+#ifdef CONFIG_DM_ETH
+ struct ueth_data ueth;
+#endif
};
+#ifndef CONFIG_DM_ETH
+/* local vars */
+static int curr_eth_dev; /* index for name of next device detected */
+#endif
+
/*
* Asix infrastructure commands
*/
@@ -284,13 +290,12 @@ static int asix_write_gpio(struct ueth_data *dev, u16 value, int sleep)
return ret;
}
-static int asix_write_hwaddr(struct eth_device *eth)
+static int asix_write_hwaddr_common(struct ueth_data *dev, uint8_t *enetaddr)
{
- struct ueth_data *dev = (struct ueth_data *)eth->priv;
int ret;
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
- memcpy(buf, eth->enetaddr, ETH_ALEN);
+ memcpy(buf, enetaddr, ETH_ALEN);
ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, buf);
if (ret < 0)
@@ -325,12 +330,11 @@ static int mii_nway_restart(struct ueth_data *dev)
return r;
}
-static int asix_read_mac(struct eth_device *eth)
+static int asix_read_mac_common(struct ueth_data *dev,
+ struct asix_private *priv, uint8_t *enetaddr)
{
- struct ueth_data *dev = (struct ueth_data *)eth->priv;
- struct asix_private *priv = (struct asix_private *)dev->dev_priv;
- int i;
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
+ int i;
if (priv->flags & FLAG_EEPROM_MAC) {
for (i = 0; i < (ETH_ALEN >> 1); i++) {
@@ -339,7 +343,7 @@ static int asix_read_mac(struct eth_device *eth)
debug("Failed to read SROM address 04h.\n");
return -1;
}
- memcpy((eth->enetaddr + i * 2), buf, 2);
+ memcpy(enetaddr + i * 2, buf, 2);
}
} else {
if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)
@@ -347,7 +351,7 @@ static int asix_read_mac(struct eth_device *eth)
debug("Failed to read MAC address.\n");
return -1;
}
- memcpy(eth->enetaddr, buf, ETH_ALEN);
+ memcpy(enetaddr, buf, ETH_ALEN);
}
return 0;
@@ -414,12 +418,8 @@ static int asix_basic_reset(struct ueth_data *dev)
return 0;
}
-/*
- * Asix callbacks
- */
-static int asix_init(struct eth_device *eth, bd_t *bd)
+static int asix_init_common(struct ueth_data *dev)
{
- struct ueth_data *dev = (struct ueth_data *)eth->priv;
int timeout = 0;
#define TIMEOUT_RESOLUTION 50 /* ms */
int link_detected;
@@ -452,9 +452,8 @@ out_err:
return -1;
}
-static int asix_send(struct eth_device *eth, void *packet, int length)
+static int asix_send_common(struct ueth_data *dev, void *packet, int length)
{
- struct ueth_data *dev = (struct ueth_data *)eth->priv;
int err;
u32 packet_len;
int actual_len;
@@ -481,6 +480,24 @@ static int asix_send(struct eth_device *eth, void *packet, int length)
return err;
}
+#ifndef CONFIG_DM_ETH
+/*
+ * Asix callbacks
+ */
+static int asix_init(struct eth_device *eth, bd_t *bd)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+ return asix_init_common(dev);
+}
+
+static int asix_send(struct eth_device *eth, void *packet, int length)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+ return asix_send_common(dev, packet, length);
+}
+
static int asix_recv(struct eth_device *eth)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
@@ -552,6 +569,13 @@ static void asix_halt(struct eth_device *eth)
debug("** %s()\n", __func__);
}
+static int asix_write_hwaddr(struct eth_device *eth)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+ return asix_write_hwaddr_common(dev, eth->enetaddr);
+}
+
/*
* Asix probing functions
*/
@@ -694,9 +718,180 @@ int asix_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
return 0;
/* Get the MAC address */
- if (asix_read_mac(eth))
+ if (asix_read_mac_common(ss, priv, eth->enetaddr))
return 0;
debug("MAC %pM\n", eth->enetaddr);
return 1;
}
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int asix_eth_start(struct udevice *dev)
+{
+ struct asix_private *priv = dev_get_priv(dev);
+
+ return asix_init_common(&priv->ueth);
+}
+
+void asix_eth_stop(struct udevice *dev)
+{
+ debug("** %s()\n", __func__);
+}
+
+int asix_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct asix_private *priv = dev_get_priv(dev);
+
+ return asix_send_common(&priv->ueth, packet, length);
+}
+
+int asix_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct asix_private *priv = dev_get_priv(dev);
+ struct ueth_data *ueth = &priv->ueth;
+ uint8_t *ptr;
+ int ret, len;
+ u32 packet_len;
+
+ len = usb_ether_get_rx_bytes(ueth, &ptr);
+ debug("%s: first try, len=%d\n", __func__, len);
+ if (!len) {
+ if (!(flags & ETH_RECV_CHECK_DEVICE))
+ return -EAGAIN;
+ ret = usb_ether_receive(ueth, AX_RX_URB_SIZE);
+ if (ret == -EAGAIN)
+ return ret;
+
+ len = usb_ether_get_rx_bytes(ueth, &ptr);
+ debug("%s: second try, len=%d\n", __func__, len);
+ }
+
+ /*
+ * 1st 4 bytes contain the length of the actual data as two
+ * complementary 16-bit words. Extract the length of the data.
+ */
+ if (len < sizeof(packet_len)) {
+ debug("Rx: incomplete packet length\n");
+ goto err;
+ }
+ memcpy(&packet_len, ptr, sizeof(packet_len));
+ le32_to_cpus(&packet_len);
+ if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
+ debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
+ packet_len, (~packet_len >> 16) & 0x7ff,
+ packet_len & 0x7ff);
+ goto err;
+ }
+ packet_len = packet_len & 0x7ff;
+ if (packet_len > len - sizeof(packet_len)) {
+ debug("Rx: too large packet: %d\n", packet_len);
+ goto err;
+ }
+
+ *packetp = ptr + sizeof(packet_len);
+ return packet_len;
+
+err:
+ usb_ether_advance_rxbuf(ueth, -1);
+ return -EINVAL;
+}
+
+static int asix_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+ struct asix_private *priv = dev_get_priv(dev);
+
+ if (packet_len & 1)
+ packet_len++;
+ usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
+
+ return 0;
+}
+
+int asix_write_hwaddr(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct asix_private *priv = dev_get_priv(dev);
+
+ if (priv->flags & FLAG_TYPE_AX88172)
+ return -ENOSYS;
+
+ return asix_write_hwaddr_common(&priv->ueth, pdata->enetaddr);
+}
+
+static int asix_eth_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct asix_private *priv = dev_get_priv(dev);
+ struct ueth_data *ss = &priv->ueth;
+ int ret;
+
+ priv->flags = dev->driver_data;
+ ret = usb_ether_register(dev, ss, AX_RX_URB_SIZE);
+ if (ret)
+ return ret;
+
+ ret = asix_basic_reset(ss);
+ if (ret)
+ goto err;
+
+ /* Get the MAC address */
+ ret = asix_read_mac_common(ss, priv, pdata->enetaddr);
+ if (ret)
+ goto err;
+ debug("MAC %pM\n", pdata->enetaddr);
+
+ return 0;
+
+err:
+ return usb_ether_deregister(ss);
+}
+
+static const struct eth_ops asix_eth_ops = {
+ .start = asix_eth_start,
+ .send = asix_eth_send,
+ .recv = asix_eth_recv,
+ .free_pkt = asix_free_pkt,
+ .stop = asix_eth_stop,
+ .write_hwaddr = asix_write_hwaddr,
+};
+
+U_BOOT_DRIVER(asix_eth) = {
+ .name = "asix_eth",
+ .id = UCLASS_ETH,
+ .probe = asix_eth_probe,
+ .ops = &asix_eth_ops,
+ .priv_auto_alloc_size = sizeof(struct asix_private),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id asix_eth_id_table[] = {
+ /* Apple USB Ethernet Adapter */
+ { USB_DEVICE(0x05ac, 0x1402), .driver_info = FLAG_TYPE_AX88772 },
+ /* D-Link DUB-E100 H/W Ver B1 */
+ { USB_DEVICE(0x07d1, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
+ /* D-Link DUB-E100 H/W Ver C1 */
+ { USB_DEVICE(0x2001, 0x1a02), .driver_info = FLAG_TYPE_AX88772 },
+ /* Cables-to-Go USB Ethernet Adapter */
+ { USB_DEVICE(0x0b95, 0x772a), .driver_info = FLAG_TYPE_AX88772 },
+ /* Trendnet TU2-ET100 V3.0R */
+ { USB_DEVICE(0x0b95, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
+ /* SMC */
+ { USB_DEVICE(0x0b95, 0x1720), .driver_info = FLAG_TYPE_AX88172 },
+ /* MSI - ASIX 88772a */
+ { USB_DEVICE(0x0db0, 0xa877), .driver_info = FLAG_TYPE_AX88772 },
+ /* Linksys 200M v2.1 */
+ { USB_DEVICE(0x13b1, 0x0018), .driver_info = FLAG_TYPE_AX88172 },
+ /* 0Q0 cable ethernet */
+ { USB_DEVICE(0x1557, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
+ /* DLink DUB-E100 H/W Ver B1 Alternate */
+ { USB_DEVICE(0x2001, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
+ /* ASIX 88772B */
+ { USB_DEVICE(0x0b95, 0x772b),
+ .driver_info = FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
+ { USB_DEVICE(0x0b95, 0x7e2b), .driver_info = FLAG_TYPE_AX88772B },
+ { } /* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(asix_eth, asix_eth_id_table);
+#endif
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index c72b7e47c4..63785a9c59 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -6,11 +6,137 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <usb.h>
#include <dm/device-internal.h>
#include "usb_ether.h"
+#ifdef CONFIG_DM_ETH
+
+#define USB_BULK_RECV_TIMEOUT 500
+
+int usb_ether_register(struct udevice *dev, struct ueth_data *ueth, int rxsize)
+{
+ struct usb_device *udev = dev_get_parentdata(dev);
+ struct usb_interface_descriptor *iface_desc;
+ bool ep_in_found = false, ep_out_found = false;
+ struct usb_interface *iface;
+ const int ifnum = 0; /* Always use interface 0 */
+ int ret, i;
+
+ iface = &udev->config.if_desc[ifnum];
+ iface_desc = &udev->config.if_desc[ifnum].desc;
+
+ /* Initialize the ueth_data structure with some useful info */
+ ueth->ifnum = ifnum;
+ ueth->subclass = iface_desc->bInterfaceSubClass;
+ ueth->protocol = iface_desc->bInterfaceProtocol;
+
+ /*
+ * We are expecting a minimum of 3 endpoints - in, out (bulk), and int.
+ * We will ignore any others.
+ */
+ for (i = 0; i < iface_desc->bNumEndpoints; i++) {
+ int ep_addr = iface->ep_desc[i].bEndpointAddress;
+
+ /* is it an BULK endpoint? */
+ if ((iface->ep_desc[i].bmAttributes &
+ USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
+ if (ep_addr & USB_DIR_IN && !ep_in_found) {
+ ueth->ep_in = ep_addr &
+ USB_ENDPOINT_NUMBER_MASK;
+ ep_in_found = true;
+ } else if (!(ep_addr & USB_DIR_IN) && !ep_out_found) {
+ ueth->ep_out = ep_addr &
+ USB_ENDPOINT_NUMBER_MASK;
+ ep_out_found = true;
+ }
+ }
+
+ /* is it an interrupt endpoint? */
+ if ((iface->ep_desc[i].bmAttributes &
+ USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
+ ueth->ep_int = iface->ep_desc[i].bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ ueth->irqinterval = iface->ep_desc[i].bInterval;
+ }
+ }
+ debug("Endpoints In %d Out %d Int %d\n", ueth->ep_in, ueth->ep_out,
+ ueth->ep_int);
+
+ /* Do some basic sanity checks, and bail if we find a problem */
+ if (!ueth->ep_in || !ueth->ep_out || !ueth->ep_int) {
+ debug("%s: %s: Cannot find endpoints\n", __func__, dev->name);
+ return -ENXIO;
+ }
+
+ ueth->rxsize = rxsize;
+ ueth->rxbuf = memalign(rxsize, ARCH_DMA_MINALIGN);
+ if (!ueth->rxbuf)
+ return -ENOMEM;
+
+ ret = usb_set_interface(udev, iface_desc->bInterfaceNumber, ifnum);
+ if (ret) {
+ debug("%s: %s: Cannot set interface: %d\n", __func__, dev->name,
+ ret);
+ return ret;
+ }
+ ueth->pusb_dev = udev;
+
+ return 0;
+}
+
+int usb_ether_deregister(struct ueth_data *ueth)
+{
+ return 0;
+}
+
+int usb_ether_receive(struct ueth_data *ueth, int rxsize)
+{
+ int actual_len;
+ int ret;
+
+ if (rxsize > ueth->rxsize)
+ return -EINVAL;
+ ret = usb_bulk_msg(ueth->pusb_dev,
+ usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in),
+ ueth->rxbuf, rxsize, &actual_len,
+ USB_BULK_RECV_TIMEOUT);
+ debug("Rx: len = %u, actual = %u, err = %d\n", rxsize, actual_len, ret);
+ if (ret) {
+ printf("Rx: failed to receive: %d\n", ret);
+ return ret;
+ }
+ if (actual_len > rxsize) {
+ debug("Rx: received too many bytes %d\n", actual_len);
+ return -ENOSPC;
+ }
+ ueth->rxlen = actual_len;
+ ueth->rxptr = 0;
+
+ return actual_len ? 0 : -EAGAIN;
+}
+
+void usb_ether_advance_rxbuf(struct ueth_data *ueth, int num_bytes)
+{
+ ueth->rxptr += num_bytes;
+ if (num_bytes < 0 || ueth->rxptr >= ueth->rxlen)
+ ueth->rxlen = 0;
+}
+
+int usb_ether_get_rx_bytes(struct ueth_data *ueth, uint8_t **ptrp)
+{
+ if (!ueth->rxlen)
+ return 0;
+
+ *ptrp = &ueth->rxbuf[ueth->rxptr];
+
+ return ueth->rxlen - ueth->rxptr;
+}
+
+#else
+
typedef void (*usb_eth_before_probe)(void);
typedef int (*usb_eth_probe)(struct usb_device *dev, unsigned int ifnum,
struct ueth_data *ss);
@@ -140,8 +266,8 @@ int usb_host_eth_scan(int mode)
usb_max_eth_dev = 0;
#ifdef CONFIG_DM_USB
/*
- * TODO: We should add USB_DEVICE() declarations to each USB ethernet
- * driver and then most of this file can be removed.
+ * TODO: We should add U_BOOT_USB_DEVICE() declarations to each USB
+ * Ethernet driver and then most of this file can be removed.
*/
struct udevice *bus;
struct uclass *uc;
@@ -197,3 +323,4 @@ int usb_host_eth_scan(int mode)
return 0;
return -1;
}
+#endif
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index bf02221c9f..3a0d32ee2b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -5,20 +5,7 @@
*
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2 of
- * the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <dm.h>
@@ -321,7 +308,7 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
struct udevice *dev = parent;
if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
- printf("ehci: Error cannot find high speed parent of usb-1 device\n");
+ printf("ehci: Error cannot find high-speed parent of usb-1 device\n");
return;
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index b9eabc5593..0cb9fcc166 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -2,29 +2,49 @@
* Copyright (c) 2007-2008, Juniper Networks, Inc.
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2 of
- * the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
+#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <usb.h>
#include "ehci.h"
+/* Information about a USB port */
+struct ehci_pci_priv {
+ struct ehci_ctrl ehci;
+};
+
+static void ehci_pci_common_init(pci_dev_t pdev, struct ehci_hccr **ret_hccr,
+ struct ehci_hcor **ret_hcor)
+{
+ struct ehci_hccr *hccr;
+ struct ehci_hcor *hcor;
+ uint32_t cmd;
+
+ hccr = (struct ehci_hccr *)pci_map_bar(pdev,
+ PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+ hcor = (struct ehci_hcor *)((uint32_t) hccr +
+ HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+ debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
+ (uint32_t)hccr, (uint32_t)hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+ *ret_hccr = hccr;
+ *ret_hcor = hcor;
+
+ /* enable busmaster */
+ pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ pci_write_config_dword(pdev, PCI_COMMAND, cmd);
+}
+
+#ifndef CONFIG_DM_USB
+
#ifdef CONFIG_PCI_EHCI_DEVICE
static struct pci_device_id ehci_pci_ids[] = {
/* Please add supported PCI EHCI controller ids here */
@@ -33,7 +53,6 @@ static struct pci_device_id ehci_pci_ids[] = {
{0x12D8, 0x400F}, /* Pericom */
{0, 0}
};
-#else
#endif
/*
@@ -44,9 +63,6 @@ int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor)
{
pci_dev_t pdev;
- uint32_t cmd;
- struct ehci_hccr *hccr;
- struct ehci_hcor *hcor;
#ifdef CONFIG_PCI_EHCI_DEVICE
pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
@@ -57,23 +73,8 @@ int ehci_hcd_init(int index, enum usb_init_type init,
printf("EHCI host controller not found\n");
return -1;
}
+ ehci_pci_common_init(pdev, ret_hccr, ret_hcor);
- hccr = (struct ehci_hccr *)pci_map_bar(pdev,
- PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
- debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
- *ret_hccr = hccr;
- *ret_hcor = hcor;
-
- /* enable busmaster */
- pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MASTER;
- pci_write_config_dword(pdev, PCI_COMMAND, cmd);
return 0;
}
@@ -85,3 +86,46 @@ int ehci_hcd_stop(int index)
{
return 0;
}
+#endif /* nCONFIG_DM_USB */
+
+#ifdef CONFIG_DM_USB
+static int ehci_pci_probe(struct udevice *dev)
+{
+ struct ehci_hccr *hccr;
+ struct ehci_hcor *hcor;
+
+ ehci_pci_common_init(pci_get_bdf(dev), &hccr, &hcor);
+
+ return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+
+static int ehci_pci_remove(struct udevice *dev)
+{
+ int ret;
+
+ ret = ehci_deregister(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(ehci_pci) = {
+ .name = "ehci_pci",
+ .id = UCLASS_USB,
+ .probe = ehci_pci_probe,
+ .remove = ehci_pci_remove,
+ .ops = &ehci_usb_ops,
+ .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+ .priv_auto_alloc_size = sizeof(struct ehci_pci_priv),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+static struct pci_device_id ehci_pci_supported[] = {
+ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0) },
+ {},
+};
+
+U_BOOT_PCI_DEVICE(ehci_pci, ehci_pci_supported);
+
+#endif /* CONFIG_DM_USB */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 774282d287..3379c293c4 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -3,20 +3,7 @@
* Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2 of
- * the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef USB_EHCI_H
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 6f33456c90..373e04cbe5 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -3,19 +3,7 @@
*
* Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ * SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index ca1b67155e..67dc3c4588 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -3,19 +3,7 @@
*
* Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef __R8A66597_H__
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 6e86f4a24a..c5d1e7feb9 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -128,6 +128,17 @@ int usb_alloc_device(struct usb_device *udev)
return ops->alloc_device(bus, udev);
}
+int usb_reset_root_port(struct usb_device *udev)
+{
+ struct udevice *bus = udev->controller_dev;
+ struct dm_usb_ops *ops = usb_get_ops(bus);
+
+ if (!ops->reset_root_port)
+ return -ENOSYS;
+
+ return ops->reset_root_port(bus, udev);
+}
+
int usb_stop(void)
{
struct udevice *bus;
@@ -146,6 +157,9 @@ int usb_stop(void)
ret = device_remove(bus);
if (ret && !err)
err = ret;
+ ret = device_unbind_children(bus);
+ if (ret && !err)
+ err = ret;
}
#ifdef CONFIG_SANDBOX
@@ -265,11 +279,6 @@ int usb_init(void)
return usb_started ? 0 : -1;
}
-int usb_reset_root_port(void)
-{
- return -ENOSYS;
-}
-
static struct usb_device *find_child_devnum(struct udevice *parent, int devnum)
{
struct usb_device *udev;
@@ -294,14 +303,14 @@ static struct usb_device *find_child_devnum(struct udevice *parent, int devnum)
struct usb_device *usb_get_dev_index(struct udevice *bus, int index)
{
- struct udevice *hub;
+ struct udevice *dev;
int devnum = index + 1; /* Addresses are allocated from 1 on USB */
- device_find_first_child(bus, &hub);
- if (device_get_uclass_id(hub) == UCLASS_USB_HUB)
- return find_child_devnum(hub, devnum);
+ device_find_first_child(bus, &dev);
+ if (!dev)
+ return NULL;
- return NULL;
+ return find_child_devnum(dev, devnum);
}
int usb_post_bind(struct udevice *dev)
@@ -310,35 +319,6 @@ int usb_post_bind(struct udevice *dev)
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
}
-int usb_port_reset(struct usb_device *parent, int portnr)
-{
- unsigned short portstatus;
- int ret;
-
- debug("%s: start\n", __func__);
-
- if (parent) {
- /* reset the port for the second time */
- assert(portnr > 0);
- debug("%s: reset %d\n", __func__, portnr - 1);
- ret = legacy_hub_port_reset(parent, portnr - 1, &portstatus);
- if (ret < 0) {
- printf("\n Couldn't reset port %i\n", portnr);
- return ret;
- }
- } else {
- debug("%s: reset root\n", __func__);
- usb_reset_root_port();
- }
-
- return 0;
-}
-
-int usb_legacy_port_reset(struct usb_device *parent, int portnr)
-{
- return usb_port_reset(parent, portnr);
-}
-
int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp)
{
struct usb_platdata *plat;
@@ -511,15 +491,14 @@ error:
}
/**
- * usb_find_child() - Find an existing device which matches our needs
- *
- *
+ * usb_find_emul_child() - Find an existing device for emulated devices
*/
-static int usb_find_child(struct udevice *parent,
- struct usb_device_descriptor *desc,
- struct usb_interface_descriptor *iface,
- struct udevice **devp)
+static int usb_find_emul_child(struct udevice *parent,
+ struct usb_device_descriptor *desc,
+ struct usb_interface_descriptor *iface,
+ struct udevice **devp)
{
+#ifdef CONFIG_SANDBOX
struct udevice *dev;
*devp = NULL;
@@ -538,7 +517,7 @@ static int usb_find_child(struct udevice *parent,
return 0;
}
}
-
+#endif
return -ENOENT;
}
@@ -594,12 +573,12 @@ int usb_scan_device(struct udevice *parent, int port,
debug("Calling usb_setup_device(), portnr=%d\n", udev->portnr);
parent_udev = device_get_uclass_id(parent) == UCLASS_USB_HUB ?
dev_get_parentdata(parent) : NULL;
- ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev, port);
+ ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev);
debug("read_descriptor for '%s': ret=%d\n", parent->name, ret);
if (ret)
return ret;
- ret = usb_find_child(parent, &udev->descriptor, iface, &dev);
- debug("** usb_find_child returns %d\n", ret);
+ ret = usb_find_emul_child(parent, &udev->descriptor, iface, &dev);
+ debug("** usb_find_emul_child returns %d\n", ret);
if (ret) {
if (ret != -ENOENT)
return ret;
diff --git a/drivers/usb/musb-new/am35x.c b/drivers/usb/musb-new/am35x.c
index 857d7eb0cc..d158454a08 100644
--- a/drivers/usb/musb-new/am35x.c
+++ b/drivers/usb/musb-new/am35x.c
@@ -100,7 +100,11 @@ struct am35x_glue {
/*
* am35x_musb_enable - enable interrupts
*/
+#ifndef __UBOOT__
static void am35x_musb_enable(struct musb *musb)
+#else
+static int am35x_musb_enable(struct musb *musb)
+#endif
{
void __iomem *reg_base = musb->ctrl_base;
u32 epmask;
@@ -116,6 +120,9 @@ static void am35x_musb_enable(struct musb *musb)
if (is_otg_enabled(musb))
musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
+#ifdef __UBOOT__
+ return 0;
+#endif
}
/*
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index 242cc30b1c..f530af4fb7 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -926,10 +926,17 @@ b_host:
/*
* Program the HDRC to start (enable interrupts, dma, etc.).
*/
+#ifndef __UBOOT__
void musb_start(struct musb *musb)
+#else
+int musb_start(struct musb *musb)
+#endif
{
void __iomem *regs = musb->mregs;
u8 devctl = musb_readb(regs, MUSB_DEVCTL);
+#ifdef __UBOOT__
+ int ret;
+#endif
dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
@@ -972,8 +979,21 @@ void musb_start(struct musb *musb)
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
musb->is_active = 1;
}
+
+#ifndef __UBOOT__
musb_platform_enable(musb);
+#else
+ ret = musb_platform_enable(musb);
+ if (ret) {
+ musb->is_active = 0;
+ return ret;
+ }
+#endif
musb_writeb(regs, MUSB_DEVCTL, devctl);
+
+#ifdef __UBOOT__
+ return 0;
+#endif
}
diff --git a/drivers/usb/musb-new/musb_core.h b/drivers/usb/musb-new/musb_core.h
index 2695742098..8727f6415e 100644
--- a/drivers/usb/musb-new/musb_core.h
+++ b/drivers/usb/musb-new/musb_core.h
@@ -231,7 +231,11 @@ struct musb_platform_ops {
int (*init)(struct musb *musb);
int (*exit)(struct musb *musb);
+#ifndef __UBOOT__
void (*enable)(struct musb *musb);
+#else
+ int (*enable)(struct musb *musb);
+#endif
void (*disable)(struct musb *musb);
int (*set_mode)(struct musb *musb, u8 mode);
@@ -546,7 +550,11 @@ static inline void musb_configure_ep0(struct musb *musb)
extern const char musb_driver_name[];
+#ifndef __UBOOT__
extern void musb_start(struct musb *musb);
+#else
+extern int musb_start(struct musb *musb);
+#endif
extern void musb_stop(struct musb *musb);
extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
@@ -564,11 +572,21 @@ static inline void musb_platform_set_vbus(struct musb *musb, int is_on)
musb->ops->set_vbus(musb, is_on);
}
+#ifndef __UBOOT__
static inline void musb_platform_enable(struct musb *musb)
{
if (musb->ops->enable)
musb->ops->enable(musb);
}
+#else
+static inline int musb_platform_enable(struct musb *musb)
+{
+ if (!musb->ops->enable)
+ return 0;
+
+ return musb->ops->enable(musb);
+}
+#endif
static inline void musb_platform_disable(struct musb *musb)
{
diff --git a/drivers/usb/musb-new/musb_dsps.c b/drivers/usb/musb-new/musb_dsps.c
index 17ed224488..895939773a 100644
--- a/drivers/usb/musb-new/musb_dsps.c
+++ b/drivers/usb/musb-new/musb_dsps.c
@@ -156,7 +156,11 @@ struct dsps_glue {
/**
* dsps_musb_enable - enable interrupts
*/
+#ifndef __UBOOT__
static void dsps_musb_enable(struct musb *musb)
+#else
+static int dsps_musb_enable(struct musb *musb)
+#endif
{
#ifndef __UBOOT__
struct device *dev = musb->controller;
@@ -181,6 +185,8 @@ static void dsps_musb_enable(struct musb *musb)
if (is_otg_enabled(musb))
dsps_writel(reg_base, wrp->coreintr_set,
(1 << wrp->drvvbus) << wrp->usb_shift);
+#else
+ return 0;
#endif
}
diff --git a/drivers/usb/musb-new/musb_gadget_ep0.c b/drivers/usb/musb-new/musb_gadget_ep0.c
index 5a715013a2..415a9f21a9 100644
--- a/drivers/usb/musb-new/musb_gadget_ep0.c
+++ b/drivers/usb/musb-new/musb_gadget_ep0.c
@@ -43,6 +43,7 @@
#else
#include <common.h>
#include "linux-compat.h"
+#include <asm/processor.h>
#endif
#include "musb_core.h"
diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
index 437309ceb4..40b9c66af8 100644
--- a/drivers/usb/musb-new/musb_host.c
+++ b/drivers/usb/musb-new/musb_host.c
@@ -2067,7 +2067,11 @@ int musb_urb_enqueue(
/* precompute addressing for external hub/tt ports */
if (musb->is_multipoint) {
+#ifndef __UBOOT__
struct usb_device *parent = urb->dev->parent;
+#else
+ struct usb_device *parent = usb_dev_get_parent(urb->dev);
+#endif
#ifndef __UBOOT__
if (parent != hcd->self.root_hub) {
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index d1ee5f8d06..9b56e904e4 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -13,6 +13,7 @@
#include "musb_core.h"
#include "musb_host.h"
#include "musb_gadget.h"
+#include "musb_uboot.h"
#ifdef CONFIG_MUSB_HOST
struct int_queue {
@@ -20,9 +21,9 @@ struct int_queue {
struct urb urb;
};
-static struct musb *host;
-static struct usb_hcd hcd;
-static enum usb_device_speed host_speed;
+#ifndef CONFIG_DM_USB
+struct musb_host_data musb_host;
+#endif
static void musb_host_complete_urb(struct urb *urb)
{
@@ -30,9 +31,6 @@ static void musb_host_complete_urb(struct urb *urb)
urb->dev->act_len = urb->actual_length;
}
-static struct usb_host_endpoint hep;
-static struct urb urb;
-
static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep,
struct usb_device *dev, int endpoint_type,
unsigned long pipe, void *buffer, int len,
@@ -90,38 +88,40 @@ static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
return urb->status;
}
-int submit_control_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int len, struct devrequest *setup)
+static int _musb_submit_control_msg(struct musb_host_data *host,
+ struct usb_device *dev, unsigned long pipe,
+ void *buffer, int len, struct devrequest *setup)
{
- construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_CONTROL, pipe,
- buffer, len, setup, 0);
+ construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_CONTROL,
+ pipe, buffer, len, setup, 0);
/* Fix speed for non hub-attached devices */
- if (!dev->parent)
- dev->speed = host_speed;
+ if (!usb_dev_get_parent(dev))
+ dev->speed = host->host_speed;
- return submit_urb(&hcd, &urb);
+ return submit_urb(&host->hcd, &host->urb);
}
-
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int len)
+static int _musb_submit_bulk_msg(struct musb_host_data *host,
+ struct usb_device *dev, unsigned long pipe, void *buffer, int len)
{
- construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_BULK, pipe,
- buffer, len, NULL, 0);
- return submit_urb(&hcd, &urb);
+ construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_BULK,
+ pipe, buffer, len, NULL, 0);
+ return submit_urb(&host->hcd, &host->urb);
}
-int submit_int_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int len, int interval)
+static int _musb_submit_int_msg(struct musb_host_data *host,
+ struct usb_device *dev, unsigned long pipe,
+ void *buffer, int len, int interval)
{
- construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_INT, pipe,
+ construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe,
buffer, len, NULL, interval);
- return submit_urb(&hcd, &urb);
+ return submit_urb(&host->hcd, &host->urb);
}
-struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
- int queuesize, int elementsize, void *buffer, int interval)
+static struct int_queue *_musb_create_int_queue(struct musb_host_data *host,
+ struct usb_device *dev, unsigned long pipe, int queuesize,
+ int elementsize, void *buffer, int interval)
{
struct int_queue *queue;
int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe);
@@ -143,7 +143,7 @@ struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT,
pipe, buffer, elementsize, NULL, interval);
- ret = musb_urb_enqueue(&hcd, &queue->urb, 0);
+ ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0);
if (ret < 0) {
printf("Failed to enqueue URB to controller\n");
free(queue);
@@ -154,25 +154,27 @@ struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
return queue;
}
-int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+static int _musb_destroy_int_queue(struct musb_host_data *host,
+ struct usb_device *dev, struct int_queue *queue)
{
int index = usb_pipein(queue->urb.pipe) * 16 +
usb_pipeendpoint(queue->urb.pipe);
if (queue->urb.status == -EINPROGRESS)
- musb_urb_dequeue(&hcd, &queue->urb, -ETIME);
+ musb_urb_dequeue(&host->hcd, &queue->urb, -ETIME);
dev->int_pending &= ~(1 << index);
free(queue);
return 0;
}
-void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+static void *_musb_poll_int_queue(struct musb_host_data *host,
+ struct usb_device *dev, struct int_queue *queue)
{
if (queue->urb.status != -EINPROGRESS)
return NULL; /* URB has already completed in a prev. poll */
- host->isr(0, host);
+ host->host->isr(0, host->host);
if (queue->urb.status != -EINPROGRESS)
return queue->urb.transfer_buffer; /* Done */
@@ -180,9 +182,10 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
return NULL; /* URB still pending */
}
-int usb_reset_root_port(void)
+static int _musb_reset_root_port(struct musb_host_data *host,
+ struct usb_device *dev)
{
- void *mbase = host->mregs;
+ void *mbase = host->host->mregs;
u8 power;
power = musb_readb(mbase, MUSB_POWER);
@@ -202,29 +205,33 @@ int usb_reset_root_port(void)
#ifdef CONFIG_ARCH_SUNXI
sunxi_usb_phy_enable_squelch_detect(0, 1);
#endif
- host->isr(0, host);
- host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
+ host->host->isr(0, host->host);
+ host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
USB_SPEED_HIGH :
(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
USB_SPEED_FULL : USB_SPEED_LOW;
- mdelay((host_speed == USB_SPEED_LOW) ? 200 : 50);
+ mdelay((host->host_speed == USB_SPEED_LOW) ? 200 : 50);
return 0;
}
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+int musb_lowlevel_init(struct musb_host_data *host)
{
void *mbase;
/* USB spec says it may take up to 1 second for a device to connect */
unsigned long timeout = get_timer(0) + 1000;
+ int ret;
- if (!host) {
+ if (!host->host) {
printf("MUSB host is not registered\n");
return -ENODEV;
}
- musb_start(host);
- mbase = host->mregs;
+ ret = musb_start(host->host);
+ if (ret)
+ return ret;
+
+ mbase = host->host->mregs;
do {
if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
break;
@@ -232,23 +239,135 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
if (get_timer(0) >= timeout)
return -ENODEV;
- usb_reset_root_port();
- host->is_active = 1;
- hcd.hcd_priv = host;
+ _musb_reset_root_port(host, NULL);
+ host->host->is_active = 1;
+ host->hcd.hcd_priv = host->host;
return 0;
}
+#ifndef CONFIG_DM_USB
int usb_lowlevel_stop(int index)
{
- if (!host) {
+ if (!musb_host.host) {
printf("MUSB host is not registered\n");
return -ENODEV;
}
- musb_stop(host);
+ musb_stop(musb_host.host);
return 0;
}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int length)
+{
+ return _musb_submit_bulk_msg(&musb_host, dev, pipe, buffer, length);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int length, struct devrequest *setup)
+{
+ return _musb_submit_control_msg(&musb_host, dev, pipe, buffer, length, setup);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int length, int interval)
+{
+ return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval);
+}
+
+struct int_queue *create_int_queue(struct usb_device *dev,
+ unsigned long pipe, int queuesize, int elementsize,
+ void *buffer, int interval)
+{
+ return _musb_create_int_queue(&musb_host, dev, pipe, queuesize, elementsize,
+ buffer, interval);
+}
+
+void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+ return _musb_poll_int_queue(&musb_host, dev, queue);
+}
+
+int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+ return _musb_destroy_int_queue(&musb_host, dev, queue);
+}
+
+int usb_reset_root_port(struct usb_device *dev)
+{
+ return _musb_reset_root_port(&musb_host, dev);
+}
+
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+ return musb_lowlevel_init(&musb_host);
+}
+#endif /* !CONFIG_DM_USB */
+
+#ifdef CONFIG_DM_USB
+static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length,
+ struct devrequest *setup)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_submit_control_msg(host, udev, pipe, buffer, length, setup);
+}
+
+static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_submit_bulk_msg(host, udev, pipe, buffer, length);
+}
+
+static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length,
+ int interval)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval);
+}
+
+static struct int_queue *musb_create_int_queue(struct udevice *dev,
+ struct usb_device *udev, unsigned long pipe, int queuesize,
+ int elementsize, void *buffer, int interval)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_create_int_queue(host, udev, pipe, queuesize, elementsize,
+ buffer, interval);
+}
+
+static void *musb_poll_int_queue(struct udevice *dev, struct usb_device *udev,
+ struct int_queue *queue)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_poll_int_queue(host, udev, queue);
+}
+
+static int musb_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
+ struct int_queue *queue)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_destroy_int_queue(host, udev, queue);
+}
+
+static int musb_reset_root_port(struct udevice *dev, struct usb_device *udev)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+ return _musb_reset_root_port(host, udev);
+}
+
+struct dm_usb_ops musb_usb_ops = {
+ .control = musb_submit_control_msg,
+ .bulk = musb_submit_bulk_msg,
+ .interrupt = musb_submit_int_msg,
+ .create_int_queue = musb_create_int_queue,
+ .poll_int_queue = musb_poll_int_queue,
+ .destroy_int_queue = musb_destroy_int_queue,
+ .reset_root_port = musb_reset_root_port,
+};
+#endif /* CONFIG_DM_USB */
#endif /* CONFIG_MUSB_HOST */
#ifdef CONFIG_MUSB_GADGET
@@ -309,9 +428,9 @@ int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
struct musb **musbp;
switch (plat->mode) {
-#ifdef CONFIG_MUSB_HOST
+#if defined(CONFIG_MUSB_HOST) && !defined(CONFIG_DM_USB)
case MUSB_HOST:
- musbp = &host;
+ musbp = &musb_host.host;
break;
#endif
#ifdef CONFIG_MUSB_GADGET
diff --git a/drivers/usb/musb-new/musb_uboot.h b/drivers/usb/musb-new/musb_uboot.h
new file mode 100644
index 0000000000..6312cd2148
--- /dev/null
+++ b/drivers/usb/musb-new/musb_uboot.h
@@ -0,0 +1,28 @@
+/*
+ * MUSB OTG driver u-boot specific functions
+ *
+ * Copyright © 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef __MUSB_UBOOT_H__
+#define __MUSB_UBOOT_H__
+
+#include <usb.h>
+#include "linux-compat.h"
+#include "usb-compat.h"
+#include "musb_core.h"
+
+struct musb_host_data {
+ struct musb *host;
+ struct usb_hcd hcd;
+ enum usb_device_speed host_speed;
+ struct usb_host_endpoint hep;
+ struct urb urb;
+};
+
+extern struct dm_usb_ops musb_usb_ops;
+
+int musb_lowlevel_init(struct musb_host_data *host);
+
+#endif
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 31a280edba..77273a49a3 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -400,7 +400,11 @@ err1:
return status;
}
+#ifndef __UBOOT__
static void omap2430_musb_enable(struct musb *musb)
+#else
+static int omap2430_musb_enable(struct musb *musb)
+#endif
{
#ifndef __UBOOT__
u8 devctl;
@@ -445,6 +449,7 @@ static void omap2430_musb_enable(struct musb *musb)
__PRETTY_FUNCTION__);
}
#endif
+ return 0;
#endif
}
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 052e0657d0..c123d61af2 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -199,12 +199,12 @@ 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 void sunxi_musb_enable(struct musb *musb)
+static int sunxi_musb_enable(struct musb *musb)
{
pr_debug("%s():\n", __func__);
if (enabled)
- return;
+ return 0;
/* select PIO mode */
musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
@@ -215,6 +215,7 @@ static void sunxi_musb_enable(struct musb *musb)
USBC_ForceVbusValidToHigh(musb->mregs);
enabled = true;
+ return 0;
}
static void sunxi_musb_disable(struct musb *musb)
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 50bad378c5..53fe4ff3c4 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -1,6 +1,7 @@
#ifndef __USB_COMPAT_H__
#define __USB_COMPAT_H__
+#include <dm.h>
#include "usb.h"
struct usb_hcd {
@@ -66,6 +67,68 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
return 0;
}
+#ifdef CONFIG_DM_USB
+static inline u16 find_tt(struct usb_device *udev)
+{
+ struct udevice *parent;
+ struct usb_device *uparent, *ttdev;
+
+ /*
+ * When called from usb-uclass.c: usb_scan_device() udev->dev points
+ * to the parent udevice, not the actual udevice belonging to the
+ * udev as the device is not instantiated yet. So when searching
+ * for the first usb-2 parent start with udev->dev not
+ * udev->dev->parent .
+ */
+ ttdev = udev;
+ parent = udev->dev;
+ uparent = dev_get_parentdata(parent);
+
+ while (uparent->speed != USB_SPEED_HIGH) {
+ struct udevice *dev = parent;
+
+ if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
+ printf("musb: Error cannot find high speed parent of usb-1 device\n");
+ return 0;
+ }
+
+ ttdev = dev_get_parentdata(dev);
+ parent = dev->parent;
+ uparent = dev_get_parentdata(parent);
+ }
+
+ return (uparent->devnum << 8) | (ttdev->portnr - 1);
+}
+
+static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
+{
+ struct udevice *parent = udev->dev->parent;
+
+ /*
+ * When called from usb-uclass.c: usb_scan_device() udev->dev points
+ * to the parent udevice, not the actual udevice belonging to the
+ * udev as the device is not instantiated yet.
+ *
+ * If dev is an usb-bus, then we are called from usb_scan_device() for
+ * an usb-device plugged directly into the root port, return NULL.
+ */
+ if (device_get_uclass_id(udev->dev) == UCLASS_USB)
+ return NULL;
+
+ /*
+ * If these 2 are not the same we are being called from
+ * usb_scan_device() and udev itself is the parent.
+ */
+ if (dev_get_parentdata(udev->dev) != udev)
+ return udev;
+
+ /* We are being called normally, use the parent pointer */
+ if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
+ return dev_get_parentdata(parent);
+
+ return NULL;
+}
+#else
static inline u16 find_tt(struct usb_device *dev)
{
u8 chid;
@@ -86,4 +149,11 @@ static inline u16 find_tt(struct usb_device *dev)
return (hub << 8) | chid;
}
+
+static inline struct usb_device *usb_dev_get_parent(struct usb_device *dev)
+{
+ return dev->parent;
+}
+#endif
+
#endif /* __USB_COMPAT_H__ */
OpenPOWER on IntegriCloud