diff options
author | Tom Rini | 2016-12-03 19:43:51 -0500 |
---|---|---|
committer | Tom Rini | 2016-12-03 19:43:51 -0500 |
commit | 73eed452b9c9827474c0789c30729dca6fcf061d (patch) | |
tree | b33a39a41b7b2891b0171f79ea9b5599658884c3 /drivers/usb | |
parent | bfb380b30ad2d678c09037560abb6f09a5e9c9b6 (diff) | |
parent | a2558e8729831e0bcef634ea2440e60425ef0ff6 (diff) |
Merge branch 'master' of git://www.denx.de/git/u-boot-dm
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/ether.c | 168 | ||||
-rw-r--r-- | drivers/usb/musb-new/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/musb-new/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/musb-new/am35x.c | 14 | ||||
-rw-r--r-- | drivers/usb/musb-new/musb_dsps.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb-new/ti-musb.c | 255 |
6 files changed, 391 insertions, 64 deletions
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 497b981129b..046ad8ca2bf 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -24,6 +24,10 @@ #include "gadget_chips.h" #include "rndis.h" +#include <dm.h> +#include <dm/uclass-internal.h> +#include <dm/device-internal.h> + #define USB_NET_NAME "usb_ether" #define atomic_read @@ -101,6 +105,9 @@ struct eth_dev { struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ struct usb_request *stat_req; /* for cdc & rndis status */ +#ifdef CONFIG_DM_USB + struct udevice *usb_udev; +#endif u8 config; struct usb_ep *in_ep, *out_ep, *status_ep; @@ -134,9 +141,14 @@ struct eth_dev { */ /*-------------------------------------------------------------------------*/ -static struct eth_dev l_ethdev; -static struct eth_device l_netdev; -static struct usb_gadget_driver eth_driver; +struct ether_priv { + struct eth_dev ethdev; + struct eth_device netdev; + struct usb_gadget_driver eth_driver; +}; + +struct ether_priv eth_priv; +struct ether_priv *l_priv = ð_priv; /*-------------------------------------------------------------------------*/ @@ -1135,7 +1147,7 @@ static void eth_status_complete(struct usb_ep *ep, struct usb_request *req) event->bNotificationType, value); if (event->bNotificationType == USB_CDC_NOTIFY_SPEED_CHANGE) { - l_ethdev.network_started = 1; + dev->network_started = 1; printf("USB network up!\n"); } } @@ -1323,7 +1335,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) * that network is working. So we signalize it * here. */ - l_ethdev.network_started = 1; + dev->network_started = 1; debug("USB network up!\n"); goto done_set_intf; } @@ -1823,10 +1835,10 @@ static void rndis_control_ack_complete(struct usb_ep *ep, debug("rndis control ack complete --> %d, %d/%d\n", req->status, req->actual, req->length); - if (!l_ethdev.network_started) { + if (!dev->network_started) { if (rndis_get_state(dev->rndis_config) == RNDIS_DATA_INITIALIZED) { - l_ethdev.network_started = 1; + dev->network_started = 1; printf("USB RNDIS network up!\n"); } } @@ -1841,7 +1853,8 @@ static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32)))); static int rndis_control_ack(struct eth_device *net) { - struct eth_dev *dev = &l_ethdev; + struct ether_priv *priv = (struct ether_priv *)net->priv; + struct eth_dev *dev = &priv->ethdev; int length; struct usb_request *resp = dev->stat_req; @@ -1982,7 +1995,7 @@ static int get_ether_addr(const char *str, u8 *dev_addr) static int eth_bind(struct usb_gadget *gadget) { - struct eth_dev *dev = &l_ethdev; + struct eth_dev *dev = &l_priv->ethdev; u8 cdc = 1, zlp = 1, rndis = 1; struct usb_ep *in_ep, *out_ep, *status_ep = NULL; int status = -ENOMEM; @@ -2175,7 +2188,7 @@ autoconf_fail: /* network device setup */ - dev->net = &l_netdev; + dev->net = &l_priv->netdev; dev->cdc = cdc; dev->zlp = zlp; @@ -2303,19 +2316,39 @@ fail: /*-------------------------------------------------------------------------*/ -static int usb_eth_init(struct eth_device *netdev, bd_t *bd) +#ifdef CONFIG_DM_USB +int dm_usb_init(struct eth_dev *e_dev) { - struct eth_dev *dev = &l_ethdev; + struct udevice *dev = NULL; + int ret; + + ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); + if (!dev || ret) { + error("No USB device found\n"); + return -ENODEV; + } + + e_dev->usb_udev = dev; + + return ret; +} +#endif + +static int _usb_eth_init(struct ether_priv *priv) +{ + struct eth_dev *dev = &priv->ethdev; struct usb_gadget *gadget; unsigned long ts; unsigned long timeout = USB_CONNECT_TIMEOUT; - if (!netdev) { - error("received NULL ptr"); - goto fail; +#ifdef CONFIG_DM_USB + if (dm_usb_init(dev)) { + error("USB ether not found\n"); + return -ENODEV; } - +#else board_usb_init(0, USB_INIT_DEVICE); +#endif /* Configure default mac-addresses for the USB ethernet device */ #ifdef CONFIG_USBNET_DEV_ADDR @@ -2342,7 +2375,15 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd) goto fail; } - if (usb_gadget_register_driver(ð_driver) < 0) + priv->eth_driver.speed = DEVSPEED; + priv->eth_driver.bind = eth_bind; + priv->eth_driver.unbind = eth_unbind; + priv->eth_driver.setup = eth_setup; + priv->eth_driver.reset = eth_disconnect; + priv->eth_driver.disconnect = eth_disconnect; + priv->eth_driver.suspend = eth_suspend; + priv->eth_driver.resume = eth_resume; + if (usb_gadget_register_driver(&priv->eth_driver) < 0) goto fail; dev->network_started = 0; @@ -2357,7 +2398,7 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd) timeout = simple_strtoul(getenv("cdc_connect_timeout"), NULL, 10) * CONFIG_SYS_HZ; ts = get_timer(0); - while (!l_ethdev.network_started) { + while (!dev->network_started) { /* Handle control-c and timeouts */ if (ctrlc() || (get_timer(ts) > timeout)) { error("The remote end did not respond in time."); @@ -2373,11 +2414,11 @@ fail: return -1; } -static int usb_eth_send(struct eth_device *netdev, void *packet, int length) +static int _usb_eth_send(struct ether_priv *priv, void *packet, int length) { int retval; void *rndis_pkt = NULL; - struct eth_dev *dev = &l_ethdev; + struct eth_dev *dev = &priv->ethdev; struct usb_request *req = dev->tx_req; unsigned long ts; unsigned long timeout = USB_CONNECT_TIMEOUT; @@ -2442,34 +2483,16 @@ drop: return -ENOMEM; } -static int usb_eth_recv(struct eth_device *netdev) +static int _usb_eth_recv(struct ether_priv *priv) { - struct eth_dev *dev = &l_ethdev; - usb_gadget_handle_interrupts(0); - if (packet_received) { - debug("%s: packet received\n", __func__); - if (dev->rx_req) { - net_process_received_packet(net_rx_packets[0], - dev->rx_req->length); - packet_received = 0; - - rx_submit(dev, dev->rx_req, 0); - } else - error("dev->rx_req invalid"); - } return 0; } -void usb_eth_halt(struct eth_device *netdev) +void _usb_eth_halt(struct ether_priv *priv) { - struct eth_dev *dev = &l_ethdev; - - if (!netdev) { - error("received NULL ptr"); - return; - } + struct eth_dev *dev = &priv->ethdev; /* If the gadget not registered, simple return */ if (!dev->gadget) @@ -2496,27 +2519,65 @@ void usb_eth_halt(struct eth_device *netdev) dev->network_started = 0; } - usb_gadget_unregister_driver(ð_driver); + usb_gadget_unregister_driver(&priv->eth_driver); +#ifdef CONFIG_DM_USB + device_remove(dev->usb_udev); +#else board_usb_cleanup(0, USB_INIT_DEVICE); +#endif +} + +static int usb_eth_init(struct eth_device *netdev, bd_t *bd) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + + return _usb_eth_init(priv); } -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, +static int usb_eth_send(struct eth_device *netdev, void *packet, int length) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; - .bind = eth_bind, - .unbind = eth_unbind, + return _usb_eth_send(priv, packet, length); +} - .setup = eth_setup, - .reset = eth_disconnect, - .disconnect = eth_disconnect, +static int usb_eth_recv(struct eth_device *netdev) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + struct eth_dev *dev = &priv->ethdev; + int ret; + + ret = _usb_eth_recv(priv); + if (ret) { + error("error packet receive\n"); + return ret; + } - .suspend = eth_suspend, - .resume = eth_resume, -}; + if (!packet_received) + return 0; + + if (dev->rx_req) { + net_process_received_packet(net_rx_packets[0], + dev->rx_req->length); + } else { + error("dev->rx_req invalid"); + } + packet_received = 0; + rx_submit(dev, dev->rx_req, 0); + + return 0; +} + +void usb_eth_halt(struct eth_device *netdev) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + + _usb_eth_halt(priv); +} int usb_eth_initialize(bd_t *bi) { - struct eth_device *netdev = &l_netdev; + struct eth_device *netdev = &l_priv->netdev; strlcpy(netdev->name, USB_NET_NAME, sizeof(netdev->name)); @@ -2524,6 +2585,7 @@ int usb_eth_initialize(bd_t *bi) netdev->send = usb_eth_send; netdev->recv = usb_eth_recv; netdev->halt = usb_eth_halt; + netdev->priv = l_priv; #ifdef CONFIG_MCAST_TFTP #error not supported diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index c264859b6c0..caba42c26fc 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -14,6 +14,15 @@ config USB_MUSB_GADGET help Enables the MUSB USB dual-role controller in gadget mode. +config USB_MUSB_TI + bool "Enable TI OTG USB controller" + depends on DM_USB + default n + help + Say y here to enable support for the dual role high + speed USB controller based on the Mentor Graphics + silicon IP. + if USB_MUSB_HOST || USB_MUSB_GADGET config USB_MUSB_PIC32 diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index df1c3c8a45b..296f230fbf3 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -12,6 +12,7 @@ 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 +obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o ccflags-y := $(call cc-option,-Wno-unused-variable) \ $(call cc-option,-Wno-unused-but-set-variable) \ diff --git a/drivers/usb/musb-new/am35x.c b/drivers/usb/musb-new/am35x.c index b8791ddd5c1..0167ea77970 100644 --- a/drivers/usb/musb-new/am35x.c +++ b/drivers/usb/musb-new/am35x.c @@ -336,7 +336,7 @@ eoi: if (ret == IRQ_HANDLED || epintr || usbintr) { /* clear level interrupt */ if (data->clear_irq) - data->clear_irq(); + data->clear_irq(data->dev); /* write EOI */ musb_writel(reg_base, USB_END_OF_INTR_REG, 0); } @@ -401,14 +401,14 @@ static int am35x_musb_init(struct musb *musb) /* Reset the musb */ if (data->reset) - data->reset(); + data->reset(data->dev); /* Reset the controller */ musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(1); + data->set_phy_power(data->dev, 1); msleep(5); @@ -416,7 +416,7 @@ static int am35x_musb_init(struct musb *musb) /* clear level interrupt */ if (data->clear_irq) - data->clear_irq(); + data->clear_irq(data->dev); return 0; } @@ -439,7 +439,7 @@ static int am35x_musb_exit(struct musb *musb) /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(0); + data->set_phy_power(data->dev, 0); #ifndef __UBOOT__ usb_put_phy(musb->xceiv); @@ -630,7 +630,7 @@ static int am35x_suspend(struct device *dev) /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(0); + data->set_phy_power(data->dev, 0); clk_disable(glue->phy_clk); clk_disable(glue->clk); @@ -647,7 +647,7 @@ static int am35x_resume(struct device *dev) /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(1); + data->set_phy_power(data->dev, 1); ret = clk_enable(glue->phy_clk); if (ret) { diff --git a/drivers/usb/musb-new/musb_dsps.c b/drivers/usb/musb-new/musb_dsps.c index a71db76d7c7..399b85bbce8 100644 --- a/drivers/usb/musb-new/musb_dsps.c +++ b/drivers/usb/musb-new/musb_dsps.c @@ -452,7 +452,7 @@ static int dsps_musb_init(struct musb *musb) /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(1); + data->set_phy_power(data->dev, 1); musb->isr = dsps_interrupt; @@ -493,7 +493,7 @@ static int dsps_musb_exit(struct musb *musb) /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(0); + data->set_phy_power(data->dev, 0); #ifndef __UBOOT__ /* NOP driver needs change if supporting dual instance */ @@ -693,7 +693,7 @@ static int dsps_suspend(struct device *dev) /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(0); + data->set_phy_power(data->dev, 0); return 0; } @@ -705,7 +705,7 @@ static int dsps_resume(struct device *dev) /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) - data->set_phy_power(1); + data->set_phy_power(data->dev, 1); return 0; } diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c new file mode 100644 index 00000000000..1c15aa2a427 --- /dev/null +++ b/drivers/usb/musb-new/ti-musb.c @@ -0,0 +1,255 @@ +/* + * MISC driver for TI MUSB Glue. + * + * (C) Copyright 2016 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <command.h> +#include <console.h> +#include <dm.h> +#include <linux/usb/otg.h> +#include <dm/device-internal.h> +#include <dm/lists.h> + +#include <asm/io.h> +#include <asm/omap_musb.h> +#include "musb_uboot.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_DM_USB + +/* USB 2.0 PHY Control */ +#define CM_PHY_PWRDN (1 << 0) +#define CM_PHY_OTG_PWRDN (1 << 1) +#define OTGVDET_EN (1 << 19) +#define OTGSESSENDEN (1 << 20) + +#define AM335X_USB1_CTRL 0x8 + +struct ti_musb_platdata { + void *base; + void *ctrl_mod_base; + struct musb_hdrc_platform_data plat; + struct musb_hdrc_config musb_config; + struct omap_musb_board_data otg_board_data; +}; + +static int ti_musb_get_usb_index(int node) +{ + const void *fdt = gd->fdt_blob; + int i = 0; + char path[64]; + const char *alias_path; + char alias[16]; + + fdt_get_path(fdt, node, path, sizeof(path)); + + do { + snprintf(alias, sizeof(alias), "usb%d", i); + alias_path = fdt_get_alias(fdt, alias); + if (alias_path == NULL) { + debug("USB index not found\n"); + return -ENOENT; + } + + if (!strcmp(path, alias_path)) + return i; + + i++; + } while (alias_path); + + return -ENOENT; +} + +static void ti_musb_set_phy_power(struct udevice *dev, u8 on) +{ + struct ti_musb_platdata *platdata = dev_get_platdata(dev); + + if (on) { + clrsetbits_le32(platdata->ctrl_mod_base, + CM_PHY_PWRDN | CM_PHY_OTG_PWRDN, + OTGVDET_EN | OTGSESSENDEN); + } else { + clrsetbits_le32(platdata->ctrl_mod_base, 0, + CM_PHY_PWRDN | CM_PHY_OTG_PWRDN); + } +} + +static int ti_musb_ofdata_to_platdata(struct udevice *dev) +{ + struct ti_musb_platdata *platdata = dev_get_platdata(dev); + const void *fdt = gd->fdt_blob; + int node = dev->of_offset; + int phys; + int ctrl_mod; + int usb_index; + + platdata->base = (void *)dev_get_addr_index(dev, 1); + + phys = fdtdec_lookup_phandle(fdt, node, "phys"); + ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod"); + platdata->ctrl_mod_base = (void *)fdtdec_get_addr(fdt, ctrl_mod, "reg"); + usb_index = ti_musb_get_usb_index(node); + switch (usb_index) { + case 1: + platdata->ctrl_mod_base += AM335X_USB1_CTRL; + case 0: + default: + break; + } + + platdata->musb_config.multipoint = fdtdec_get_int(fdt, node, + "mentor,multipoint", + -1); + if (platdata->musb_config.multipoint < 0) { + error("MUSB multipoint DT entry missing\n"); + return -ENOENT; + } + + platdata->musb_config.dyn_fifo = 1; + + platdata->musb_config.num_eps = fdtdec_get_int(fdt, node, + "mentor,num-eps", -1); + if (platdata->musb_config.num_eps < 0) { + error("MUSB num-eps DT entry missing\n"); + return -ENOENT; + } + + platdata->musb_config.ram_bits = fdtdec_get_int(fdt, node, + "mentor,ram-bits", -1); + if (platdata->musb_config.ram_bits < 0) { + error("MUSB ram-bits DT entry missing\n"); + return -ENOENT; + } + + platdata->otg_board_data.set_phy_power = ti_musb_set_phy_power; + platdata->otg_board_data.dev = dev; + platdata->plat.config = &platdata->musb_config; + + platdata->plat.power = fdtdec_get_int(fdt, node, "mentor,power", -1); + if (platdata->plat.power < 0) { + error("MUSB mentor,power DT entry missing\n"); + return -ENOENT; + } + + platdata->plat.platform_ops = &musb_dsps_ops; + platdata->plat.board_data = &platdata->otg_board_data; + + return 0; +} + +static int ti_musb_host_probe(struct udevice *dev) +{ + struct musb_host_data *host = dev_get_priv(dev); + struct ti_musb_platdata *platdata = dev_get_platdata(dev); + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + struct omap_musb_board_data *otg_board_data; + int ret; + + priv->desc_before_addr = true; + + otg_board_data = &platdata->otg_board_data; + + host->host = musb_init_controller(&platdata->plat, + (struct device *)otg_board_data, + platdata->base); + if (!host->host) + return -EIO; + + ret = musb_lowlevel_init(host); + + return ret; +} + +static int ti_musb_host_remove(struct udevice *dev) +{ + struct musb_host_data *host = dev_get_priv(dev); + + musb_stop(host->host); + + return 0; +} + +static int ti_musb_host_ofdata_to_platdata(struct udevice *dev) +{ + struct ti_musb_platdata *platdata = dev_get_platdata(dev); + const void *fdt = gd->fdt_blob; + int node = dev->of_offset; + int ret; + + ret = ti_musb_ofdata_to_platdata(dev); + if (ret) { + error("platdata dt parse error\n"); + return ret; + } + + platdata->plat.mode = MUSB_HOST; + + return 0; +} + +U_BOOT_DRIVER(ti_musb_host) = { + .name = "ti-musb-host", + .id = UCLASS_USB, + .ofdata_to_platdata = ti_musb_host_ofdata_to_platdata, + .probe = ti_musb_host_probe, + .remove = ti_musb_host_remove, + .ops = &musb_usb_ops, + .platdata_auto_alloc_size = sizeof(struct ti_musb_platdata), + .priv_auto_alloc_size = sizeof(struct musb_host_data), +}; + +static int ti_musb_wrapper_bind(struct udevice *parent) +{ + const void *fdt = gd->fdt_blob; + int node; + int ret; + + for (node = fdt_first_subnode(fdt, parent->of_offset); node > 0; + node = fdt_next_subnode(fdt, node)) { + struct udevice *dev; + const char *name = fdt_get_name(fdt, node, NULL); + enum usb_dr_mode dr_mode; + struct driver *drv; + + if (strncmp(name, "usb@", 4)) + continue; + + dr_mode = usb_get_dr_mode(node); + switch (dr_mode) { + case USB_DR_MODE_PERIPHERAL: + /* Bind MUSB device */ + break; + case USB_DR_MODE_HOST: + /* Bind MUSB host */ + ret = device_bind_driver_to_node(parent, "ti-musb-host", + name, node, &dev); + if (ret) { + error("musb - not able to bind usb host node\n"); + return ret; + } + break; + default: + break; + }; + } + return 0; +} + +static const struct udevice_id ti_musb_ids[] = { + { .compatible = "ti,am33xx-usb" }, + { } +}; + +U_BOOT_DRIVER(ti_musb_wrapper) = { + .name = "ti-musb-wrapper", + .id = UCLASS_MISC, + .of_match = ti_musb_ids, + .bind = ti_musb_wrapper_bind, +}; + +#endif /* CONFIG_DM_USB */ |