summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/cdns3/Kconfig7
-rw-r--r--drivers/usb/cdns3/Makefile1
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c182
-rw-r--r--drivers/usb/cdns3/core.c3
-rw-r--r--drivers/usb/cdns3/drd.c14
-rw-r--r--drivers/usb/emul/sandbox_keyb.c8
-rw-r--r--drivers/usb/gadget/Makefile4
-rw-r--r--drivers/usb/gadget/core.c621
-rw-r--r--drivers/usb/gadget/ep0.c619
-rw-r--r--drivers/usb/musb-new/Kconfig7
-rw-r--r--drivers/usb/musb-new/Makefile1
-rw-r--r--drivers/usb/musb-new/sc5xx.c202
12 files changed, 421 insertions, 1248 deletions
diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig
index 35b61497d9c..1d5e4afac6c 100644
--- a/drivers/usb/cdns3/Kconfig
+++ b/drivers/usb/cdns3/Kconfig
@@ -49,6 +49,13 @@ config SPL_USB_CDNS3_HOST
Host controller is compliant with XHCI so it will use
standard XHCI driver.
+config USB_CDNS3_STARFIVE
+ tristate "Cadence USB3 support on Starfive platforms"
+ default y if STARFIVE_JH7110
+ help
+ Say 'Y' here if you are building for Starfive platforms
+ that contain Cadence USB3 controller core. E.g.: JH7110.
+
config USB_CDNS3_TI
tristate "Cadence USB3 support on TI platforms"
default USB_CDNS3
diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile
index d6047856091..1f00f23f704 100644
--- a/drivers/usb/cdns3/Makefile
+++ b/drivers/usb/cdns3/Makefile
@@ -8,4 +8,5 @@ cdns3-$(CONFIG_$(XPL_)USB_CDNS3_GADGET) += gadget.o ep0.o
cdns3-$(CONFIG_$(XPL_)USB_CDNS3_HOST) += host.o
+obj-$(CONFIG_USB_CDNS3_STARFIVE) += cdns3-starfive.o
obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o
diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c
new file mode 100644
index 00000000000..78ceb831b19
--- /dev/null
+++ b/drivers/usb/cdns3/cdns3-starfive.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * cdns3-starfive.c - StarFive specific Glue layer for Cadence USB Controller
+ *
+ * Copyright (C) 2024 StarFive Technology Co., Ltd.
+ *
+ * Author: Minda Chen <minda.chen@starfivetech.com>
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/usb/otg.h>
+#include <malloc.h>
+#include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "core.h"
+
+#define USB_STRAP_HOST BIT(17)
+#define USB_STRAP_DEVICE BIT(18)
+#define USB_STRAP_MASK GENMASK(18, 16)
+
+#define USB_SUSPENDM_HOST BIT(19)
+#define USB_SUSPENDM_MASK BIT(19)
+
+#define USB_MISC_CFG_MASK GENMASK(23, 20)
+#define USB_SUSPENDM_BYPS BIT(20)
+#define USB_PLL_EN BIT(22)
+#define USB_REFCLK_MODE BIT(23)
+
+struct cdns_starfive {
+ struct udevice *dev;
+ struct regmap *stg_syscon;
+ struct reset_ctl_bulk resets;
+ struct clk_bulk clks;
+ u32 stg_usb_mode;
+ enum usb_dr_mode mode;
+};
+
+static void cdns_mode_init(struct cdns_starfive *data, enum usb_dr_mode mode)
+{
+ unsigned int strap, suspendm;
+
+ regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
+ USB_MISC_CFG_MASK,
+ USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE);
+
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ strap = USB_STRAP_HOST;
+ suspendm = USB_SUSPENDM_HOST;
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ strap = USB_STRAP_DEVICE;
+ suspendm = 0;
+ break;
+ default:
+ return;
+ }
+
+ regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
+ USB_SUSPENDM_MASK | USB_STRAP_MASK,
+ strap | suspendm);
+}
+
+static void cdns_clk_rst_deinit(struct cdns_starfive *data)
+{
+ reset_assert_bulk(&data->resets);
+ clk_disable_bulk(&data->clks);
+}
+
+static int cdns_clk_rst_init(struct cdns_starfive *data)
+{
+ int ret;
+
+ ret = clk_get_bulk(data->dev, &data->clks);
+ if (ret)
+ return ret;
+
+ ret = reset_get_bulk(data->dev, &data->resets);
+ if (ret)
+ goto err_clk;
+
+ ret = clk_enable_bulk(&data->clks);
+ if (ret) {
+ dev_err(data->dev, "clk enable failed: %d\n", ret);
+ goto err_en_clk;
+ }
+
+ ret = reset_deassert_bulk(&data->resets);
+ if (ret) {
+ dev_err(data->dev, "reset deassert failed: %d\n", ret);
+ goto err_reset;
+ }
+
+ return 0;
+
+err_reset:
+ clk_disable_bulk(&data->clks);
+err_en_clk:
+ reset_release_bulk(&data->resets);
+err_clk:
+ clk_release_bulk(&data->clks);
+
+ return ret;
+}
+
+static int cdns_starfive_get_syscon(struct cdns_starfive *data)
+{
+ struct ofnode_phandle_args phandle;
+ int ret;
+
+ ret = dev_read_phandle_with_args(data->dev, "starfive,stg-syscon", NULL, 1, 0,
+ &phandle);
+ if (ret < 0) {
+ dev_err(data->dev, "Can't get stg cfg phandle: %d\n", ret);
+ return ret;
+ }
+
+ data->stg_syscon = syscon_node_to_regmap(phandle.node);
+ if (IS_ERR(data->stg_syscon)) {
+ dev_err(data->dev, "fail to get regmap: %d\n", (int)PTR_ERR(data->stg_syscon));
+ return PTR_ERR(data->stg_syscon);
+ }
+
+ data->stg_usb_mode = phandle.args[0];
+
+ return 0;
+}
+
+static int cdns_starfive_probe(struct udevice *dev)
+{
+ struct cdns_starfive *data = dev_get_plat(dev);
+ enum usb_dr_mode dr_mode;
+ int ret;
+
+ data->dev = dev;
+
+ ret = cdns_starfive_get_syscon(data);
+ if (ret)
+ return ret;
+
+ dr_mode = usb_get_dr_mode(dev_ofnode(dev));
+
+ data->mode = dr_mode;
+ ret = cdns_clk_rst_init(data);
+ if (ret) {
+ dev_err(data->dev, "clk reset failed: %d\n", ret);
+ return ret;
+ }
+ cdns_mode_init(data, dr_mode);
+
+ return 0;
+}
+
+static int cdns_starfive_remove(struct udevice *dev)
+{
+ struct cdns_starfive *data = dev_get_plat(dev);
+
+ cdns_clk_rst_deinit(data);
+ return 0;
+}
+
+static const struct udevice_id cdns_starfive_of_match[] = {
+ { .compatible = "starfive,jh7110-usb", },
+ {},
+};
+
+U_BOOT_DRIVER(cdns_starfive) = {
+ .name = "cdns-starfive",
+ .id = UCLASS_NOP,
+ .of_match = cdns_starfive_of_match,
+ .bind = cdns3_bind,
+ .probe = cdns_starfive_probe,
+ .remove = cdns_starfive_remove,
+ .plat_auto = sizeof(struct cdns_starfive),
+ .flags = DM_FLAG_OS_PREPARE,
+};
diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c
index 4cfd38ec245..4434dc15bec 100644
--- a/drivers/usb/cdns3/core.c
+++ b/drivers/usb/cdns3/core.c
@@ -410,6 +410,9 @@ int cdns3_bind(struct udevice *parent)
name = ofnode_get_name(node);
dr_mode = usb_get_dr_mode(node);
+ if (dr_mode == USB_DR_MODE_UNKNOWN)
+ dr_mode = usb_get_dr_mode(dev_ofnode(parent));
+
switch (dr_mode) {
#if defined(CONFIG_SPL_USB_HOST) || \
(!defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_HOST))
diff --git a/drivers/usb/cdns3/drd.c b/drivers/usb/cdns3/drd.c
index 47874fec29e..cbb13342343 100644
--- a/drivers/usb/cdns3/drd.c
+++ b/drivers/usb/cdns3/drd.c
@@ -217,15 +217,19 @@ static int cdns3_init_otg_mode(struct cdns3 *cdns)
int cdns3_drd_update_mode(struct cdns3 *cdns)
{
int ret = 0;
+ int mode;
switch (cdns->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+ mode = PHY_MODE_USB_DEVICE;
ret = cdns3_set_mode(cdns, USB_DR_MODE_PERIPHERAL);
break;
case USB_DR_MODE_HOST:
+ mode = PHY_MODE_USB_HOST;
ret = cdns3_set_mode(cdns, USB_DR_MODE_HOST);
break;
case USB_DR_MODE_OTG:
+ mode = PHY_MODE_USB_OTG;
ret = cdns3_init_otg_mode(cdns);
break;
default:
@@ -234,6 +238,16 @@ int cdns3_drd_update_mode(struct cdns3 *cdns)
return -EINVAL;
}
+ ret = generic_phy_set_mode(&cdns->usb2_phy, mode, 0);
+ if (ret) {
+ dev_err(cdns->dev, "Set usb 2.0 PHY mode failed %d\n", ret);
+ return ret;
+ }
+
+ ret = generic_phy_set_mode(&cdns->usb3_phy, mode, 0);
+ if (ret)
+ dev_err(cdns->dev, "Set usb 3.0 PHY mode failed %d\n", ret);
+
return ret;
}
diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c
index db769883ba3..5ed8c2c799a 100644
--- a/drivers/usb/emul/sandbox_keyb.c
+++ b/drivers/usb/emul/sandbox_keyb.c
@@ -38,7 +38,7 @@ enum {
*
*/
struct sandbox_keyb_priv {
- struct membuff in;
+ struct membuf in;
};
struct sandbox_keyb_plat {
@@ -167,7 +167,7 @@ int sandbox_usb_keyb_add_string(struct udevice *dev,
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
int ret;
- ret = membuff_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE);
+ ret = membuf_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE);
if (ret != USB_KBD_BOOT_REPORT_SIZE)
return -ENOSPC;
@@ -194,7 +194,7 @@ static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev,
if (length < USB_KBD_BOOT_REPORT_SIZE)
return 0;
- membuff_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE);
+ membuf_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE);
return 0;
}
@@ -220,7 +220,7 @@ static int sandbox_keyb_probe(struct udevice *dev)
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
/* Provide an 80 character keyboard buffer */
- return membuff_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE);
+ return membuf_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE);
}
static const struct dm_usb_ops sandbox_usb_keyb_ops = {
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 4bda224ff1a..db5f8895a33 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -35,7 +35,3 @@ endif
endif
obj-$(CONFIG_CI_UDC) += ci_udc.o
-
-# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
-# This is really only N900 and USBTTY now.
-obj-$(CONFIG_USB_DEVICE) += core.o ep0.o
diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c
deleted file mode 100644
index bcb1ad3082c..00000000000
--- a/drivers/usb/gadget/core.c
+++ /dev/null
@@ -1,621 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2003
- * Gerry Hamel, geh@ti.com, Texas Instruments
- *
- * Based on
- * linux/drivers/usbd/usbd.c.c - USB Device Core Layer
- *
- * Copyright (c) 2000, 2001, 2002 Lineo
- * Copyright (c) 2001 Hewlett Packard
- *
- * By:
- * Stuart Lynne <sl@lineo.com>,
- * Tom Rushworth <tbr@lineo.com>,
- * Bruce Balden <balden@lineo.com>
- */
-
-#include <log.h>
-#include <malloc.h>
-#include <serial.h>
-#include <usbdevice.h>
-
-#define MAX_INTERFACES 2
-
-int maxstrings = 20;
-
-/* Global variables ************************************************************************** */
-
-struct usb_string_descriptor **usb_strings;
-
-int usb_devices;
-
-extern struct usb_function_driver ep0_driver;
-
-int registered_functions;
-int registered_devices;
-
-__maybe_unused static char *usbd_device_events[] = {
- "DEVICE_UNKNOWN",
- "DEVICE_INIT",
- "DEVICE_CREATE",
- "DEVICE_HUB_CONFIGURED",
- "DEVICE_RESET",
- "DEVICE_ADDRESS_ASSIGNED",
- "DEVICE_CONFIGURED",
- "DEVICE_SET_INTERFACE",
- "DEVICE_SET_FEATURE",
- "DEVICE_CLEAR_FEATURE",
- "DEVICE_DE_CONFIGURED",
- "DEVICE_BUS_INACTIVE",
- "DEVICE_BUS_ACTIVITY",
- "DEVICE_POWER_INTERRUPTION",
- "DEVICE_HUB_RESET",
- "DEVICE_DESTROY",
- "DEVICE_FUNCTION_PRIVATE",
-};
-
-__maybe_unused static char *usbd_device_status[] = {
- "USBD_OPENING",
- "USBD_OK",
- "USBD_SUSPENDED",
- "USBD_CLOSING",
-};
-
-#define USBD_DEVICE_STATUS(x) (((unsigned int)x <= USBD_CLOSING) ? usbd_device_status[x] : "UNKNOWN")
-
-/* Descriptor support functions ************************************************************** */
-
-/**
- * usbd_get_string - find and return a string descriptor
- * @index: string index to return
- *
- * Find an indexed string and return a pointer to a it.
- */
-struct usb_string_descriptor *usbd_get_string (__u8 index)
-{
- if (index >= maxstrings) {
- return NULL;
- }
- return usb_strings[index];
-}
-
-/* Access to device descriptor functions ***************************************************** */
-
-/* *
- * usbd_device_configuration_instance - find a configuration instance for this device
- * @device:
- * @configuration: index to configuration, 0 - N-1
- *
- * Get specifed device configuration. Index should be bConfigurationValue-1.
- */
-static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device,
- unsigned int port, unsigned int configuration)
-{
- if (configuration >= device->configurations)
- return NULL;
-
- return device->configuration_instance_array + configuration;
-}
-
-/* *
- * usbd_device_interface_instance
- * @device:
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- *
- * Return the specified interface descriptor for the specified device.
- */
-struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *device, int port, int configuration, int interface)
-{
- struct usb_configuration_instance *configuration_instance;
-
- if ((configuration_instance = usbd_device_configuration_instance (device, port, configuration)) == NULL) {
- return NULL;
- }
- if (interface >= configuration_instance->interfaces) {
- return NULL;
- }
- return configuration_instance->interface_instance_array + interface;
-}
-
-/* *
- * usbd_device_alternate_descriptor_list
- * @device:
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- * @alternate: alternate setting
- *
- * Return the specified alternate descriptor for the specified device.
- */
-struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *device, int port, int configuration, int interface, int alternate)
-{
- struct usb_interface_instance *interface_instance;
-
- if ((interface_instance = usbd_device_interface_instance (device, port, configuration, interface)) == NULL) {
- return NULL;
- }
-
- if (alternate >= interface_instance->alternates) {
- return NULL;
- }
-
- return interface_instance->alternates_instance_array + alternate;
-}
-
-/* *
- * usbd_device_device_descriptor
- * @device: which device
- * @configuration: index to configuration, 0 - N-1
- * @port: which port
- *
- * Return the specified configuration descriptor for the specified device.
- */
-struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port)
-{
- return (device->device_descriptor);
-}
-
-/**
- * usbd_device_configuration_descriptor
- * @device: which device
- * @port: which port
- * @configuration: index to configuration, 0 - N-1
- *
- * Return the specified configuration descriptor for the specified device.
- */
-struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct
- usb_device_instance
- *device, int port, int configuration)
-{
- struct usb_configuration_instance *configuration_instance;
- if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) {
- return NULL;
- }
- return (configuration_instance->configuration_descriptor);
-}
-
-/**
- * usbd_device_interface_descriptor
- * @device: which device
- * @port: which port
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- * @alternate: alternate setting
- *
- * Return the specified interface descriptor for the specified device.
- */
-struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance
- *device, int port, int configuration, int interface, int alternate)
-{
- struct usb_interface_instance *interface_instance;
- if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) {
- return NULL;
- }
- if ((alternate < 0) || (alternate >= interface_instance->alternates)) {
- return NULL;
- }
- return (interface_instance->alternates_instance_array[alternate].interface_descriptor);
-}
-
-/**
- * usbd_device_endpoint_descriptor_index
- * @device: which device
- * @port: which port
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- * @alternate: index setting
- * @index: which index
- *
- * Return the specified endpoint descriptor for the specified device.
- */
-struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance
- *device, int port, int configuration, int interface, int alternate, int index)
-{
- struct usb_alternate_instance *alternate_instance;
-
- if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) {
- return NULL;
- }
- if (index >= alternate_instance->endpoints) {
- return NULL;
- }
- return *(alternate_instance->endpoints_descriptor_array + index);
-}
-
-/**
- * usbd_device_endpoint_transfersize
- * @device: which device
- * @port: which port
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- * @index: which index
- *
- * Return the specified endpoint transfer size;
- */
-int usbd_device_endpoint_transfersize (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int index)
-{
- struct usb_alternate_instance *alternate_instance;
-
- if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) {
- return 0;
- }
- if (index >= alternate_instance->endpoints) {
- return 0;
- }
- return *(alternate_instance->endpoint_transfersize_array + index);
-}
-
-/**
- * usbd_device_endpoint_descriptor
- * @device: which device
- * @port: which port
- * @configuration: index to configuration, 0 - N-1
- * @interface: index to interface
- * @alternate: alternate setting
- * @endpoint: which endpoint
- *
- * Return the specified endpoint descriptor for the specified device.
- */
-struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int endpoint)
-{
- struct usb_endpoint_descriptor *endpoint_descriptor;
- int i;
-
- for (i = 0; !(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, configuration, interface, alternate, i)); i++) {
- if (endpoint_descriptor->bEndpointAddress == endpoint) {
- return endpoint_descriptor;
- }
- }
- return NULL;
-}
-
-/**
- * usbd_endpoint_halted
- * @device: point to struct usb_device_instance
- * @endpoint: endpoint to check
- *
- * Return non-zero if endpoint is halted.
- */
-int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint)
-{
- return (device->status == USB_STATUS_HALT);
-}
-
-/**
- * usbd_rcv_complete - complete a receive
- * @endpoint:
- * @len:
- * @urb_bad:
- *
- * Called from rcv interrupt to complete.
- */
-void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad)
-{
- if (endpoint) {
- struct urb *rcv_urb;
-
- /*usbdbg("len: %d urb: %p\n", len, endpoint->rcv_urb); */
-
- /* if we had an urb then update actual_length, dispatch if neccessary */
- if ((rcv_urb = endpoint->rcv_urb)) {
-
- /*usbdbg("actual: %d buffer: %d\n", */
- /*rcv_urb->actual_length, rcv_urb->buffer_length); */
-
- /* check the urb is ok, are we adding data less than the packetsize */
- if (!urb_bad && (len <= endpoint->rcv_packetSize)) {
- /*usbdbg("updating actual_length by %d\n",len); */
-
- /* increment the received data size */
- rcv_urb->actual_length += len;
-
- } else {
- usberr(" RECV_ERROR actual: %d buffer: %d urb_bad: %d\n",
- rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad);
-
- rcv_urb->actual_length = 0;
- rcv_urb->status = RECV_ERROR;
- }
- } else {
- usberr("no rcv_urb!");
- }
- } else {
- usberr("no endpoint!");
- }
-
-}
-
-/**
- * usbd_tx_complete - complete a transmit
- * @endpoint:
- * @resetart:
- *
- * Called from tx interrupt to complete.
- */
-void usbd_tx_complete (struct usb_endpoint_instance *endpoint)
-{
- if (endpoint) {
- struct urb *tx_urb;
-
- /* if we have a tx_urb advance or reset, finish if complete */
- if ((tx_urb = endpoint->tx_urb)) {
- int sent = endpoint->last;
- endpoint->sent += sent;
- endpoint->last -= sent;
-
- if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) {
- tx_urb->actual_length = 0;
- endpoint->sent = 0;
- endpoint->last = 0;
-
- /* Remove from active, save for re-use */
- urb_detach(tx_urb);
- urb_append(&endpoint->done, tx_urb);
- /*usbdbg("done->next %p, tx_urb %p, done %p", */
- /* endpoint->done.next, tx_urb, &endpoint->done); */
-
- endpoint->tx_urb = first_urb_detached(&endpoint->tx);
- if( endpoint->tx_urb ) {
- endpoint->tx_queue--;
- usbdbg("got urb from tx list");
- }
- if( !endpoint->tx_urb ) {
- /*usbdbg("taking urb from done list"); */
- endpoint->tx_urb = first_urb_detached(&endpoint->done);
- }
- if( !endpoint->tx_urb ) {
- usbdbg("allocating new urb for tx_urb");
- endpoint->tx_urb = usbd_alloc_urb(tx_urb->device, endpoint);
- }
- }
- }
- }
-}
-
-/* URB linked list functions ***************************************************** */
-
-/*
- * Initialize an urb_link to be a single element list.
- * If the urb_link is being used as a distinguished list head
- * the list is empty when the head is the only link in the list.
- */
-void urb_link_init (urb_link * ul)
-{
- if (ul) {
- ul->prev = ul->next = ul;
- }
-}
-
-/*
- * Detach an urb_link from a list, and set it
- * up as a single element list, so no dangling
- * pointers can be followed, and so it can be
- * joined to another list if so desired.
- */
-void urb_detach (struct urb *urb)
-{
- if (urb) {
- urb_link *ul = &urb->link;
- ul->next->prev = ul->prev;
- ul->prev->next = ul->next;
- urb_link_init (ul);
- }
-}
-
-/*
- * Return the first urb_link in a list with a distinguished
- * head "hd", or NULL if the list is empty. This will also
- * work as a predicate, returning NULL if empty, and non-NULL
- * otherwise.
- */
-urb_link *first_urb_link (urb_link * hd)
-{
- urb_link *nx;
- if (NULL != hd && NULL != (nx = hd->next) && nx != hd) {
- /* There is at least one element in the list */
- /* (besides the distinguished head). */
- return (nx);
- }
- /* The list is empty */
- return (NULL);
-}
-
-/*
- * Return the first urb in a list with a distinguished
- * head "hd", or NULL if the list is empty.
- */
-struct urb *first_urb (urb_link * hd)
-{
- urb_link *nx;
- if (NULL == (nx = first_urb_link (hd))) {
- /* The list is empty */
- return (NULL);
- }
- return (p2surround (struct urb, link, nx));
-}
-
-/*
- * Detach and return the first urb in a list with a distinguished
- * head "hd", or NULL if the list is empty.
- *
- */
-struct urb *first_urb_detached (urb_link * hd)
-{
- struct urb *urb;
- if ((urb = first_urb (hd))) {
- urb_detach (urb);
- }
- return urb;
-}
-
-/*
- * Append an urb_link (or a whole list of
- * urb_links) to the tail of another list
- * of urb_links.
- */
-void urb_append (urb_link * hd, struct urb *urb)
-{
- if (hd && urb) {
- urb_link *new = &urb->link;
-
- /* This allows the new urb to be a list of urbs, */
- /* with new pointing at the first, but the link */
- /* must be initialized. */
- /* Order is important here... */
- urb_link *pul = hd->prev;
- new->prev->next = hd;
- hd->prev = new->prev;
- new->prev = pul;
- pul->next = new;
- }
-}
-
-/* URB create/destroy functions ***************************************************** */
-
-/**
- * usbd_alloc_urb - allocate an URB appropriate for specified endpoint
- * @device: device instance
- * @endpoint: endpoint
- *
- * Allocate an urb structure. The usb device urb structure is used to
- * contain all data associated with a transfer, including a setup packet for
- * control transfers.
- *
- * NOTE: endpoint_address MUST contain a direction flag.
- */
-struct urb *usbd_alloc_urb (struct usb_device_instance *device,
- struct usb_endpoint_instance *endpoint)
-{
- struct urb *urb;
-
- if (!(urb = (struct urb *) malloc (sizeof (struct urb)))) {
- usberr (" F A T A L: malloc(%zu) FAILED!!!!",
- sizeof (struct urb));
- return NULL;
- }
-
- /* Fill in known fields */
- memset (urb, 0, sizeof (struct urb));
- urb->endpoint = endpoint;
- urb->device = device;
- urb->buffer = (u8 *) urb->buffer_data;
- urb->buffer_length = sizeof (urb->buffer_data);
-
- urb_link_init (&urb->link);
-
- return urb;
-}
-
-/**
- * usbd_dealloc_urb - deallocate an URB and associated buffer
- * @urb: pointer to an urb structure
- *
- * Deallocate an urb structure and associated data.
- */
-void usbd_dealloc_urb (struct urb *urb)
-{
- if (urb) {
- free (urb);
- }
-}
-
-/* Event signaling functions ***************************************************** */
-
-/**
- * usbd_device_event - called to respond to various usb events
- * @device: pointer to struct device
- * @event: event to respond to
- *
- * Used by a Bus driver to indicate an event.
- */
-void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data)
-{
- usb_device_state_t state;
-
- if (!device || !device->bus) {
- usberr("(%p,%d) NULL device or device->bus", device, event);
- return;
- }
-
- state = device->device_state;
-
- usbinfo("%s", usbd_device_events[event]);
-
- switch (event) {
- case DEVICE_UNKNOWN:
- break;
- case DEVICE_INIT:
- device->device_state = STATE_INIT;
- break;
-
- case DEVICE_CREATE:
- device->device_state = STATE_ATTACHED;
- break;
-
- case DEVICE_HUB_CONFIGURED:
- device->device_state = STATE_POWERED;
- break;
-
- case DEVICE_RESET:
- device->device_state = STATE_DEFAULT;
- device->address = 0;
- break;
-
- case DEVICE_ADDRESS_ASSIGNED:
- device->device_state = STATE_ADDRESSED;
- break;
-
- case DEVICE_CONFIGURED:
- device->device_state = STATE_CONFIGURED;
- break;
-
- case DEVICE_DE_CONFIGURED:
- device->device_state = STATE_ADDRESSED;
- break;
-
- case DEVICE_BUS_INACTIVE:
- if (device->status != USBD_CLOSING) {
- device->status = USBD_SUSPENDED;
- }
- break;
- case DEVICE_BUS_ACTIVITY:
- if (device->status != USBD_CLOSING) {
- device->status = USBD_OK;
- }
- break;
-
- case DEVICE_SET_INTERFACE:
- break;
- case DEVICE_SET_FEATURE:
- break;
- case DEVICE_CLEAR_FEATURE:
- break;
-
- case DEVICE_POWER_INTERRUPTION:
- device->device_state = STATE_POWERED;
- break;
- case DEVICE_HUB_RESET:
- device->device_state = STATE_ATTACHED;
- break;
- case DEVICE_DESTROY:
- device->device_state = STATE_UNKNOWN;
- break;
-
- case DEVICE_FUNCTION_PRIVATE:
- break;
-
- default:
- usbdbg("event %d - not handled",event);
- break;
- }
- debug("%s event: %d oldstate: %d newstate: %d status: %d address: %d",
- device->name, event, state,
- device->device_state, device->status, device->address);
-
- /* tell the bus interface driver */
- if( device->event ) {
- /* usbdbg("calling device->event"); */
- device->event(device, event, data);
- }
-}
diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c
deleted file mode 100644
index 8c7fc17c2ea..00000000000
--- a/drivers/usb/gadget/ep0.c
+++ /dev/null
@@ -1,619 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2003
- * Gerry Hamel, geh@ti.com, Texas Instruments
- *
- * (C) Copyright 2006
- * Bryan O'Donoghue, deckard@CodeHermit.ie
- *
- * Based on
- * linux/drivers/usbd/ep0.c
- *
- * Copyright (c) 2000, 2001, 2002 Lineo
- * Copyright (c) 2001 Hewlett Packard
- *
- * By:
- * Stuart Lynne <sl@lineo.com>,
- * Tom Rushworth <tbr@lineo.com>,
- * Bruce Balden <balden@lineo.com>
- */
-
-/*
- * This is the builtin ep0 control function. It implements all required functionality
- * for responding to control requests (SETUP packets).
- *
- * XXX
- *
- * Currently we do not pass any SETUP packets (or other) to the configured
- * function driver. This may need to change.
- *
- * XXX
- *
- * As alluded to above, a simple callback cdc_recv_setup has been implemented
- * in the usb_device data structure to facilicate passing
- * Common Device Class packets to a function driver.
- *
- * XXX
- */
-
-#include <serial.h>
-#include <usbdevice.h>
-
-#if 0
-#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args)
-#else
-#define dbg_ep0(lvl,fmt,args...)
-#endif
-
-__maybe_unused static char *usbd_device_descriptors[] = {
- "UNKNOWN", /* 0 */
- "DEVICE", /* 1 */
- "CONFIG", /* 2 */
- "STRING", /* 3 */
- "INTERFACE", /* 4 */
- "ENDPOINT", /* 5 */
- "DEVICE QUALIFIER", /* 6 */
- "OTHER SPEED", /* 7 */
- "INTERFACE POWER", /* 8 */
-};
-
-#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \
- usbd_device_descriptors[x] : "UNKNOWN")
-
-__maybe_unused static char *usbd_device_states[] = {
- "STATE_INIT",
- "STATE_CREATED",
- "STATE_ATTACHED",
- "STATE_POWERED",
- "STATE_DEFAULT",
- "STATE_ADDRESSED",
- "STATE_CONFIGURED",
- "STATE_UNKNOWN",
-};
-
-#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN")
-
-__maybe_unused static char *usbd_device_requests[] = {
- "GET STATUS", /* 0 */
- "CLEAR FEATURE", /* 1 */
- "RESERVED", /* 2 */
- "SET FEATURE", /* 3 */
- "RESERVED", /* 4 */
- "SET ADDRESS", /* 5 */
- "GET DESCRIPTOR", /* 6 */
- "SET DESCRIPTOR", /* 7 */
- "GET CONFIGURATION", /* 8 */
- "SET CONFIGURATION", /* 9 */
- "GET INTERFACE", /* 10 */
- "SET INTERFACE", /* 11 */
- "SYNC FRAME", /* 12 */
-};
-
-#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN")
-
-/* EP0 Configuration Set ********************************************************************* */
-
-/**
- * ep0_get_status - fill in URB data with appropriate status
- * @device:
- * @urb:
- * @index:
- * @requesttype:
- *
- */
-static int ep0_get_status (struct usb_device_instance *device,
- struct urb *urb, int index, int requesttype)
-{
- char *cp;
-
- urb->actual_length = 2;
- cp = (char*)urb->buffer;
- cp[0] = cp[1] = 0;
-
- switch (requesttype) {
- case USB_REQ_RECIPIENT_DEVICE:
- cp[0] = USB_STATUS_SELFPOWERED;
- break;
- case USB_REQ_RECIPIENT_INTERFACE:
- break;
- case USB_REQ_RECIPIENT_ENDPOINT:
- cp[0] = usbd_endpoint_halted (device, index);
- break;
- case USB_REQ_RECIPIENT_OTHER:
- urb->actual_length = 0;
- default:
- break;
- }
- dbg_ep0 (2, "%02x %02x", cp[0], cp[1]);
- return 0;
-}
-
-/**
- * ep0_get_one
- * @device:
- * @urb:
- * @result:
- *
- * Set a single byte value in the urb send buffer. Return non-zero to signal
- * a request error.
- */
-static int ep0_get_one (struct usb_device_instance *device, struct urb *urb,
- __u8 result)
-{
- urb->actual_length = 1; /* XXX 2? */
- ((char *) urb->buffer)[0] = result;
- return 0;
-}
-
-/**
- * copy_config
- * @urb: pointer to urb
- * @data: pointer to configuration data
- * @length: length of data
- *
- * Copy configuration data to urb transfer buffer if there is room for it.
- */
-void copy_config (struct urb *urb, void *data, int max_length,
- int max_buf)
-{
- int available;
- int length;
-
- /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */
- /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */
-
- if (!data) {
- dbg_ep0 (1, "data is NULL");
- return;
- }
- length = max_length;
-
- if (length > max_length) {
- dbg_ep0 (1, "length: %d >= max_length: %d", length,
- max_length);
- return;
- }
- /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */
- /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */
-
- if ((available =
- /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) {
- return;
- }
- /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
- /* urb->actual_length, urb->buffer_length, max_buf, length, available); */
-
- if (length > available) {
- length = available;
- }
- /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
- /* urb->actual_length, urb->buffer_length, max_buf, length, available); */
-
- memcpy (urb->buffer + urb->actual_length, data, length);
- urb->actual_length += length;
-
- dbg_ep0 (3,
- "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d",
- urb->actual_length, urb->buffer_length, max_buf, max_length,
- available);
-}
-
-/**
- * ep0_get_descriptor
- * @device:
- * @urb:
- * @max:
- * @descriptor_type:
- * @index:
- *
- * Called by ep0_rx_process for a get descriptor device command. Determine what
- * descriptor is being requested, copy to send buffer. Return zero if ok to send,
- * return non-zero to signal a request error.
- */
-static int ep0_get_descriptor (struct usb_device_instance *device,
- struct urb *urb, int max, int descriptor_type,
- int index)
-{
- int port = 0; /* XXX compound device */
-
- /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */
-
- if (!urb || !urb->buffer || !urb->buffer_length
- || (urb->buffer_length < 255)) {
- dbg_ep0 (2, "invalid urb %p", urb);
- return -1L;
- }
-
- /* setup tx urb */
- urb->actual_length = 0;
-
- dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type));
-
- switch (descriptor_type) {
- case USB_DESCRIPTOR_TYPE_DEVICE:
- {
- struct usb_device_descriptor *device_descriptor;
- if (!
- (device_descriptor =
- usbd_device_device_descriptor (device, port))) {
- return -1;
- }
- /* copy descriptor for this device */
- copy_config (urb, device_descriptor,
- sizeof (struct usb_device_descriptor),
- max);
-
- /* correct the correct control endpoint 0 max packet size into the descriptor */
- device_descriptor =
- (struct usb_device_descriptor *) urb->buffer;
-
- }
- dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);
- break;
-
- case USB_DESCRIPTOR_TYPE_CONFIGURATION:
- {
- struct usb_configuration_descriptor
- *configuration_descriptor;
- struct usb_device_descriptor *device_descriptor;
- if (!
- (device_descriptor =
- usbd_device_device_descriptor (device, port))) {
- return -1;
- }
- /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */
- if (index >= device_descriptor->bNumConfigurations) {
- dbg_ep0 (0, "index too large: %d >= %d", index,
- device_descriptor->
- bNumConfigurations);
- return -1;
- }
-
- if (!
- (configuration_descriptor =
- usbd_device_configuration_descriptor (device,
- port,
- index))) {
- dbg_ep0 (0,
- "usbd_device_configuration_descriptor failed: %d",
- index);
- return -1;
- }
- dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));
- copy_config (urb, configuration_descriptor,
-
- cpu_to_le16(configuration_descriptor->wTotalLength),
- max);
- }
-
- break;
-
- case USB_DESCRIPTOR_TYPE_STRING:
- {
- struct usb_string_descriptor *string_descriptor;
- if (!(string_descriptor = usbd_get_string (index))) {
- dbg_ep0(0, "Invalid string index %d\n", index);
- return -1;
- }
- dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);
- copy_config (urb, string_descriptor, string_descriptor->bLength, max);
- }
- break;
- case USB_DESCRIPTOR_TYPE_INTERFACE:
- dbg_ep0(2, "USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");
- return -1;
- case USB_DESCRIPTOR_TYPE_ENDPOINT:
- dbg_ep0(2, "USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");
- return -1;
- case USB_DESCRIPTOR_TYPE_HID:
- {
- dbg_ep0(2, "USB_DESCRIPTOR_TYPE_HID - error not implemented\n");
- return -1; /* unsupported at this time */
-#if 0
- int bNumInterface =
- le16_to_cpu (urb->device_request.wIndex);
- int bAlternateSetting = 0;
- int class = 0;
- struct usb_class_descriptor *class_descriptor;
-
- if (!(class_descriptor =
- usbd_device_class_descriptor_index (device,
- port, 0,
- bNumInterface,
- bAlternateSetting,
- class))
- || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) {
- dbg_ep0 (3, "[%d] interface is not HID",
- bNumInterface);
- return -1;
- }
- /* copy descriptor for this class */
- copy_config (urb, class_descriptor,
- class_descriptor->descriptor.hid.bLength,
- max);
-#endif
- }
- break;
- case USB_DESCRIPTOR_TYPE_REPORT:
- {
- dbg_ep0(2, "USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");
- return -1; /* unsupported at this time */
-#if 0
- int bNumInterface =
- le16_to_cpu (urb->device_request.wIndex);
- int bAlternateSetting = 0;
- int class = 0;
- struct usb_class_report_descriptor *report_descriptor;
-
- if (!(report_descriptor =
- usbd_device_class_report_descriptor_index
- (device, port, 0, bNumInterface,
- bAlternateSetting, class))
- || report_descriptor->bDescriptorType !=
- USB_DT_REPORT) {
- dbg_ep0 (3, "[%d] descriptor is not REPORT",
- bNumInterface);
- return -1;
- }
- /* copy report descriptor for this class */
- /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */
- if (max - urb->actual_length > 0) {
- int length =
- min(report_descriptor->wLength,
- max - urb->actual_length);
- memcpy (urb->buffer + urb->actual_length,
- &report_descriptor->bData[0], length);
- urb->actual_length += length;
- }
-#endif
- }
- break;
- case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
- return -1;
-
- default:
- return -1;
- }
-
- dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d",
- urb->buffer, urb->buffer_length, urb->actual_length,
- device->bus->endpoint_array[0].tx_packetSize);
-/*
- if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) {
- dbg_ep0(0, "adding null byte");
- urb->buffer[urb->actual_length++] = 0;
- dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d",
- urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize);
- }
-*/
- return 0;
-
-}
-
-/**
- * ep0_recv_setup - called to indicate URB has been received
- * @urb: pointer to struct urb
- *
- * Check if this is a setup packet, process the device request, put results
- * back into the urb and return zero or non-zero to indicate success (DATA)
- * or failure (STALL).
- *
- */
-int ep0_recv_setup (struct urb *urb)
-{
- /*struct usb_device_request *request = urb->buffer; */
- /*struct usb_device_instance *device = urb->device; */
-
- struct usb_device_request *request;
- struct usb_device_instance *device;
- int address;
-
- dbg_ep0 (0, "entering ep0_recv_setup()");
- if (!urb || !urb->device) {
- dbg_ep0 (3, "invalid URB %p", urb);
- return -1;
- }
-
- request = &urb->device_request;
- device = urb->device;
-
- dbg_ep0 (3, "urb: %p device: %p", urb, urb->device);
-
- /*dbg_ep0(2, "- - - - - - - - - -"); */
-
- dbg_ep0 (2,
- "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s",
- request->bmRequestType, request->bRequest,
- le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex),
- le16_to_cpu (request->wLength),
- USBD_DEVICE_REQUESTS (request->bRequest));
-
- /* handle USB Standard Request (c.f. USB Spec table 9-2) */
- if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) {
- if(device->device_state <= STATE_CONFIGURED){
- /* Attempt to handle a CDC specific request if we are
- * in the configured state.
- */
- return device->cdc_recv_setup(request,urb);
- }
- dbg_ep0 (1, "non standard request: %x",
- request->bmRequestType & USB_REQ_TYPE_MASK);
- return -1; /* Stall here */
- }
-
- switch (device->device_state) {
- case STATE_CREATED:
- case STATE_ATTACHED:
- case STATE_POWERED:
- /* It actually is important to allow requests in these states,
- * Windows will request descriptors before assigning an
- * address to the client.
- */
-
- /*dbg_ep0 (1, "request %s not allowed in this state: %s", */
- /* USBD_DEVICE_REQUESTS(request->bRequest), */
- /* usbd_device_states[device->device_state]); */
- /*return -1; */
- break;
-
- case STATE_INIT:
- case STATE_DEFAULT:
- switch (request->bRequest) {
- case USB_REQ_GET_STATUS:
- case USB_REQ_GET_INTERFACE:
- case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- case USB_REQ_SET_DESCRIPTOR:
- /* case USB_REQ_SET_CONFIGURATION: */
- case USB_REQ_SET_INTERFACE:
- dbg_ep0 (1,
- "request %s not allowed in DEFAULT state: %s",
- USBD_DEVICE_REQUESTS (request->bRequest),
- usbd_device_states[device->device_state]);
- return -1;
-
- case USB_REQ_SET_CONFIGURATION:
- case USB_REQ_SET_ADDRESS:
- case USB_REQ_GET_DESCRIPTOR:
- case USB_REQ_GET_CONFIGURATION:
- break;
- }
- case STATE_ADDRESSED:
- case STATE_CONFIGURED:
- break;
- case STATE_UNKNOWN:
- dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s",
- USBD_DEVICE_REQUESTS (request->bRequest),
- usbd_device_states[device->device_state]);
- return -1;
- }
-
- /* handle all requests that return data (direction bit set on bm RequestType) */
- if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) {
-
- dbg_ep0 (3, "Device-to-Host");
-
- switch (request->bRequest) {
-
- case USB_REQ_GET_STATUS:
- return ep0_get_status (device, urb, request->wIndex,
- request->bmRequestType &
- USB_REQ_RECIPIENT_MASK);
-
- case USB_REQ_GET_DESCRIPTOR:
- return ep0_get_descriptor (device, urb,
- le16_to_cpu (request->wLength),
- le16_to_cpu (request->wValue) >> 8,
- le16_to_cpu (request->wValue) & 0xff);
-
- case USB_REQ_GET_CONFIGURATION:
- dbg_ep0(2, "get config %d\n", device->configuration);
- return ep0_get_one (device, urb,
- device->configuration);
-
- case USB_REQ_GET_INTERFACE:
- return ep0_get_one (device, urb, device->alternate);
-
- case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
- return -1;
-
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- case USB_REQ_SET_ADDRESS:
- case USB_REQ_SET_DESCRIPTOR:
- case USB_REQ_SET_CONFIGURATION:
- case USB_REQ_SET_INTERFACE:
- return -1;
- }
- }
- /* handle the requests that do not return data */
- else {
-
- /*dbg_ep0(3, "Host-to-Device"); */
- switch (request->bRequest) {
-
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- dbg_ep0 (0, "Host-to-Device");
- switch (request->
- bmRequestType & USB_REQ_RECIPIENT_MASK) {
- case USB_REQ_RECIPIENT_DEVICE:
- /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */
- /* XXX fall through for now as we do not support either */
- case USB_REQ_RECIPIENT_INTERFACE:
- case USB_REQ_RECIPIENT_OTHER:
- dbg_ep0 (0, "request %s not",
- USBD_DEVICE_REQUESTS (request->bRequest));
- default:
- return -1;
-
- case USB_REQ_RECIPIENT_ENDPOINT:
- dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue));
- if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) {
- /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */
- /* request->bRequest == USB_REQ_SET_FEATURE); */
- /* NEED TO IMPLEMENT THIS!!! */
- return -1;
- } else {
- dbg_ep0 (1, "request %s bad wValue: %04x",
- USBD_DEVICE_REQUESTS
- (request->bRequest),
- le16_to_cpu (request->wValue));
- return -1;
- }
- }
-
- case USB_REQ_SET_ADDRESS:
- /* check if this is a re-address, reset first if it is (this shouldn't be possible) */
- if (device->device_state != STATE_DEFAULT) {
- dbg_ep0 (1, "set_address: %02x state: %s",
- le16_to_cpu (request->wValue),
- usbd_device_states[device->device_state]);
- return -1;
- }
- address = le16_to_cpu (request->wValue);
- if ((address & 0x7f) != address) {
- dbg_ep0 (1, "invalid address %04x %04x",
- address, address & 0x7f);
- return -1;
- }
- device->address = address;
-
- /*dbg_ep0(2, "address: %d %d %d", */
- /* request->wValue, le16_to_cpu(request->wValue), device->address); */
-
- return 0;
-
- case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */
- dbg_ep0 (0, "set descriptor: NOT SUPPORTED");
- return -1;
-
- case USB_REQ_SET_CONFIGURATION:
- /* c.f. 9.4.7 - the top half of wValue is reserved */
- device->configuration = le16_to_cpu(request->wValue) & 0xff;
-
- /* reset interface and alternate settings */
- device->interface = device->alternate = 0;
-
- /*dbg_ep0(2, "set configuration: %d", device->configuration); */
- /*dbg_ep0(2, "DEVICE_CONFIGURED.. event?\n"); */
- return 0;
-
- case USB_REQ_SET_INTERFACE:
- device->interface = le16_to_cpu (request->wIndex);
- device->alternate = le16_to_cpu (request->wValue);
- /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */
- dbg_ep0(2, "DEVICE_SET_INTERFACE.. event?\n");
- return 0;
-
- case USB_REQ_GET_STATUS:
- case USB_REQ_GET_DESCRIPTOR:
- case USB_REQ_GET_CONFIGURATION:
- case USB_REQ_GET_INTERFACE:
- case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
- return -1;
- }
- }
- return -1;
-}
diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig
index c52afd41a75..ad9072a5327 100644
--- a/drivers/usb/musb-new/Kconfig
+++ b/drivers/usb/musb-new/Kconfig
@@ -22,6 +22,13 @@ config USB_MUSB_GADGET
Enables the MUSB USB dual-role controller in gadget mode.
if USB_MUSB_HOST || USB_MUSB_GADGET
+config USB_MUSB_SC5XX
+ bool "Analog Devices MUSB support"
+ depends on (SC57X || SC58X)
+ help
+ Say y here to enable support for the USB controller on
+ ADI SC57X/SC58X processors.
+
config USB_MUSB_DA8XX
bool "Enable DA8xx MUSB Controller"
depends on ARCH_DAVINCI
diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile
index 396ff02654b..6638772daca 100644
--- a/drivers/usb/musb-new/Makefile
+++ b/drivers/usb/musb-new/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o
obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
+obj-$(CONFIG_USB_MUSB_SC5XX) += sc5xx.o
ccflags-y := $(call cc-option,-Wno-unused-variable) \
$(call cc-option,-Wno-unused-but-set-variable) \
diff --git a/drivers/usb/musb-new/sc5xx.c b/drivers/usb/musb-new/sc5xx.c
new file mode 100644
index 00000000000..16201480b43
--- /dev/null
+++ b/drivers/usb/musb-new/sc5xx.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (C) Copyright 2022 - Analog Devices, Inc.
+ *
+ * ADI SC5XX MUSB "glue layer"
+ *
+ * Written and/or maintained by Timesys Corporation
+ *
+ * Loosely ported from Linux driver:
+ * Author: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
+ *
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/usb/musb.h>
+#include "linux-compat.h"
+#include "musb_core.h"
+#include "musb_uboot.h"
+
+#define MUSB_SOFTRST 0x7f
+#define MUSB_SOFTRST_NRST BIT(0)
+#define MUSB_SOFTRST_NRSTX BIT(1)
+
+#define REG_USB_VBUS_CTL 0x380
+#define REG_USB_ID_CTL 0x382
+#define REG_USB_PHY_CTL 0x394
+#define REG_USB_PLL_OSC 0x398
+#define REG_USB_UTMI_CTL 0x39c
+
+/* controller data */
+struct sc5xx_musb_data {
+ struct musb_host_data mdata;
+ struct device dev;
+};
+
+#define to_sc5xx_musb_data(d) \
+ container_of(d, struct sc5xx_musb_data, dev)
+
+static void sc5xx_musb_disable(struct musb *musb)
+{
+ /* no way to shut the controller */
+}
+
+static int sc5xx_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 sc5xx_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ irqreturn_t ret = IRQ_NONE;
+ u8 devctl;
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ if (musb->int_usb & MUSB_INTR_VBUSERROR) {
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+ devctl = musb_readw(musb->mregs, MUSB_DEVCTL);
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+ }
+ if (musb->int_usb || musb->int_tx || musb->int_rx) {
+ musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
+ musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
+ musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);
+ ret = musb_interrupt(musb);
+ }
+
+ if (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))
+ musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0);
+
+ return ret;
+}
+
+static int sc5xx_musb_set_mode(struct musb *musb, u8 mode)
+{
+ struct device *dev = musb->controller;
+ struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(dev);
+
+ switch (mode) {
+ case MUSB_HOST:
+ musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x1);
+ break;
+ case MUSB_PERIPHERAL:
+ musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x3);
+ break;
+ case MUSB_OTG:
+ musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x0);
+ break;
+ default:
+ dev_err(dev, "unsupported mode %d\n", mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sc5xx_musb_init(struct musb *musb)
+{
+ struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(musb->controller);
+
+ musb->isr = sc5xx_interrupt;
+
+ musb_writel(musb->mregs, REG_USB_PLL_OSC, 20 << 1);
+ musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0);
+ musb_writeb(musb->mregs, REG_USB_PHY_CTL, 0x80);
+ musb_writel(musb->mregs, REG_USB_UTMI_CTL,
+ 0x40 | musb_readl(musb->mregs, REG_USB_UTMI_CTL));
+
+ return 0;
+}
+
+const struct musb_platform_ops sc5xx_musb_ops = {
+ .init = sc5xx_musb_init,
+ .set_mode = sc5xx_musb_set_mode,
+ .disable = sc5xx_musb_disable,
+ .enable = sc5xx_musb_enable,
+};
+
+static struct musb_hdrc_config sc5xx_musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 16,
+ .ram_bits = 12,
+};
+
+/* has one MUSB controller which can be host or gadget */
+static struct musb_hdrc_platform_data sc5xx_musb_plat = {
+ .mode = MUSB_HOST,
+ .config = &sc5xx_musb_config,
+ .power = 100,
+ .platform_ops = &sc5xx_musb_ops,
+};
+
+static int musb_usb_probe(struct udevice *dev)
+{
+ struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+ struct sc5xx_musb_data *pdata = dev_get_priv(dev);
+ struct musb_host_data *mdata = &pdata->mdata;
+ void __iomem *mregs;
+ int ret;
+
+ priv->desc_before_addr = true;
+
+ mregs = dev_remap_addr(dev);
+ if (!mregs)
+ return -EINVAL;
+
+ /* init controller */
+ if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) {
+ mdata->host = musb_init_controller(&sc5xx_musb_plat,
+ &pdata->dev, mregs);
+ if (!mdata->host)
+ return -EIO;
+
+ ret = musb_lowlevel_init(mdata);
+ } else {
+ sc5xx_musb_plat.mode = MUSB_PERIPHERAL;
+ mdata->host = musb_register(&sc5xx_musb_plat, &pdata->dev, mregs);
+ if (!mdata->host)
+ return -EIO;
+ }
+ return ret;
+}
+
+static int musb_usb_remove(struct udevice *dev)
+{
+ struct sc5xx_musb_data *pdata = dev_get_priv(dev);
+
+ musb_stop(pdata->mdata.host);
+
+ return 0;
+}
+
+static const struct udevice_id sc5xx_musb_ids[] = {
+ { .compatible = "adi,sc5xx-musb" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_musb) = {
+ .name = "sc5xx-musb",
+ .id = UCLASS_USB,
+ .of_match = sc5xx_musb_ids,
+ .probe = musb_usb_probe,
+ .remove = musb_usb_remove,
+#ifdef CONFIG_USB_MUSB_HOST
+ .ops = &musb_usb_ops,
+#endif
+ .plat_auto = sizeof(struct usb_plat),
+ .priv_auto = sizeof(struct sc5xx_musb_data),
+};