summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/Kconfig8
-rw-r--r--drivers/usb/dwc3/Makefile1
-rw-r--r--drivers/usb/dwc3/dwc3-generic-sti.c134
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c20
-rw-r--r--drivers/usb/gadget/f_mass_storage.c1
-rw-r--r--drivers/usb/gadget/g_dnl.c3
-rw-r--r--drivers/usb/host/Kconfig9
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/dwc3-sti-glue.c253
9 files changed, 150 insertions, 280 deletions
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 0100723a68b..682a6910655 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -87,6 +87,14 @@ config USB_DWC3_LAYERSCAPE
Host and Peripheral operation modes are supported. OTG is not
supported.
+config USB_DWC3_STI
+ bool "STi USB wrapper"
+ depends on DM_USB && USB_DWC3_GENERIC && SYSCON
+ help
+ Enables support for the on-chip xHCI controller on STMicroelectronics
+ STiH407 family SoCs. This is a driver for the dwc3 to provide the
+ glue logic to configure the controller.
+
menu "PHY Subsystem"
config USB_DWC3_PHY_OMAP
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index a085c9d4628..985206eafe4 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_USB_DWC3_UNIPHIER) += dwc3-uniphier.o
obj-$(CONFIG_USB_DWC3_LAYERSCAPE) += dwc3-layerscape.o
obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o
obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG) += samsung_usb_phy.o
+obj-$(CONFIG_USB_DWC3_STI) += dwc3-generic-sti.o
diff --git a/drivers/usb/dwc3/dwc3-generic-sti.c b/drivers/usb/dwc3/dwc3-generic-sti.c
new file mode 100644
index 00000000000..b34f5ceceac
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-generic-sti.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * STi specific glue layer for DWC3
+ *
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY UCLASS_NOP
+
+#include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/read.h>
+#include <linux/usb/otg.h>
+#include "dwc3-generic.h"
+
+/* glue registers */
+#define CLKRST_CTRL 0x00
+#define AUX_CLK_EN BIT(0)
+#define SW_PIPEW_RESET_N BIT(4)
+#define EXT_CFG_RESET_N BIT(8)
+
+#define XHCI_REVISION BIT(12)
+
+#define USB2_VBUS_MNGMNT_SEL1 0x2C
+#define USB2_VBUS_UTMIOTG 0x1
+
+#define SEL_OVERRIDE_VBUSVALID(n) ((n) << 0)
+#define SEL_OVERRIDE_POWERPRESENT(n) ((n) << 4)
+#define SEL_OVERRIDE_BVALID(n) ((n) << 8)
+
+/* Static DRD configuration */
+#define USB3_CONTROL_MASK 0xf77
+
+#define USB3_DEVICE_NOT_HOST BIT(0)
+#define USB3_FORCE_VBUSVALID BIT(1)
+#define USB3_DELAY_VBUSVALID BIT(2)
+#define USB3_SEL_FORCE_OPMODE BIT(4)
+#define USB3_FORCE_OPMODE(n) ((n) << 5)
+#define USB3_SEL_FORCE_DPPULLDOWN2 BIT(8)
+#define USB3_FORCE_DPPULLDOWN2 BIT(9)
+#define USB3_SEL_FORCE_DMPULLDOWN2 BIT(10)
+#define USB3_FORCE_DMPULLDOWN2 BIT(11)
+
+static void dwc3_stih407_glue_configure(struct udevice *dev, int index,
+ enum usb_dr_mode mode)
+{
+ struct dwc3_glue_data *glue = dev_get_plat(dev);
+ struct regmap *regmap;
+ ulong syscfg_base;
+ ulong syscfg_offset;
+ ulong glue_base;
+ int ret;
+
+ /* deassert both powerdown and softreset */
+ ret = reset_deassert_bulk(&glue->resets);
+ if (ret) {
+ dev_err(dev, "reset_deassert_bulk error: %d\n", ret);
+ return;
+ }
+
+ regmap = syscon_regmap_lookup_by_phandle(dev, "st,syscfg");
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "unable to get st,syscfg, dev %s\n", dev->name);
+ return;
+ }
+
+ syscfg_base = regmap->ranges[0].start;
+ glue_base = dev_read_addr_index(dev, 0);
+ syscfg_offset = dev_read_addr_index(dev, 1);
+
+ clrbits_le32(syscfg_base + syscfg_offset, USB3_CONTROL_MASK);
+
+ /* glue drd init */
+ switch (mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ clrbits_le32(syscfg_base + syscfg_offset,
+ USB3_DELAY_VBUSVALID | USB3_SEL_FORCE_OPMODE |
+ USB3_FORCE_OPMODE(0x3) | USB3_SEL_FORCE_DPPULLDOWN2 |
+ USB3_FORCE_DPPULLDOWN2 | USB3_SEL_FORCE_DMPULLDOWN2 |
+ USB3_FORCE_DMPULLDOWN2);
+
+ setbits_le32(syscfg_base + syscfg_offset,
+ USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID);
+ break;
+
+ case USB_DR_MODE_HOST:
+ clrbits_le32(syscfg_base + syscfg_offset,
+ USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID |
+ USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3) |
+ USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2 |
+ USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
+
+ setbits_le32(syscfg_base + syscfg_offset, USB3_DELAY_VBUSVALID);
+ break;
+
+ default:
+ dev_err(dev, "Unsupported mode of operation %d\n", mode);
+ return;
+ }
+
+ /* glue init */
+ setbits_le32(glue_base + CLKRST_CTRL, AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION);
+ clrbits_le32(glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
+
+ /* configure mux for vbus, powerpresent and bvalid signals */
+ setbits_le32(glue_base + USB2_VBUS_MNGMNT_SEL1,
+ SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
+ SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
+ SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG));
+ setbits_le32(glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
+};
+
+struct dwc3_glue_ops stih407_ops = {
+ .glue_configure = dwc3_stih407_glue_configure,
+};
+
+static const struct udevice_id dwc3_sti_match[] = {
+ { .compatible = "st,stih407-dwc3", .data = (ulong)&stih407_ops},
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(dwc3_sti_wrapper) = {
+ .name = "dwc3-sti",
+ .id = UCLASS_NOP,
+ .of_match = dwc3_sti_match,
+ .bind = dwc3_glue_bind,
+ .probe = dwc3_glue_probe,
+ .remove = dwc3_glue_remove,
+ .plat_auto = sizeof(struct dwc3_glue_data),
+};
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 55e62b35c61..21452ad1569 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -7,29 +7,17 @@
* Based on dwc3-omap.c.
*/
-#include <cpu_func.h>
-#include <log.h>
#include <dm.h>
-#include <dm/device-internal.h>
+#include <reset.h>
+#include <asm/gpio.h>
#include <dm/lists.h>
-#include <dwc3-uboot.h>
-#include <generic-phy.h>
-#include <linux/bitops.h>
#include <linux/delay.h>
-#include <linux/printk.h>
-#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <malloc.h>
#include <power/regulator.h>
-#include <usb.h>
-#include "core.h"
-#include "gadget.h"
-#include <reset.h>
-#include <clk.h>
#include <usb/xhci.h>
-#include <asm/gpio.h>
-
+#include "core.h"
#include "dwc3-generic.h"
+#include "gadget.h"
struct dwc3_generic_plat {
fdt_addr_t base;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index ffe1ae6eb73..d3fc4acb401 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -682,6 +682,7 @@ static int sleep_thread(struct fsg_common *common)
k = 0;
}
+ schedule();
dm_usb_gadget_handle_interrupts(udcdev);
}
common->thread_wakeup_needed = 0;
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 631969b3405..f2540eb6ded 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -207,7 +207,8 @@ void g_dnl_clear_detach(void)
static int on_serialno(const char *name, const char *value, enum env_op op,
int flags)
{
- g_dnl_set_serialnumber((char *)value);
+ if (value)
+ g_dnl_set_serialnumber((char *)value);
return 0;
}
U_BOOT_ENV_CALLBACK(serialno, on_serialno);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index a656265890e..3dc79770eeb 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -110,15 +110,6 @@ config USB_XHCI_RCAR
Choose this option to add support for USB 3.0 driver on Renesas
R-Car Gen3 SoCs.
-config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
- Enables support for the on-chip xHCI controller on STMicroelectronics
- STiH407 family SoCs. This is a driver for the dwc3 to provide the glue logic
- to configure the controller.
-
config USB_XHCI_DRA7XX_INDEX
int "DRA7XX xHCI USB index"
range 0 1
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 301bb9fdee1..902d68d0378 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_USB_XHCI_GENERIC) += xhci-generic.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
-obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o
obj-$(CONFIG_USB_XHCI_OCTEON) += dwc3-octeon-glue.o
# designware
diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c
deleted file mode 100644
index 3e6834e38e3..00000000000
--- a/drivers/usb/host/dwc3-sti-glue.c
+++ /dev/null
@@ -1,253 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * STiH407 family DWC3 specific Glue layer
- *
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
- */
-
-#include <log.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <dm.h>
-#include <errno.h>
-#include <dm/lists.h>
-#include <regmap.h>
-#include <reset-uclass.h>
-#include <syscon.h>
-#include <usb.h>
-#include <linux/printk.h>
-
-#include <linux/usb/dwc3.h>
-#include <linux/usb/otg.h>
-#include <dwc3-sti-glue.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * struct sti_dwc3_glue_plat - dwc3 STi glue driver private structure
- * @syscfg_base: addr for the glue syscfg
- * @glue_base: addr for the glue registers
- * @syscfg_offset: usb syscfg control offset
- * @powerdown_ctl: rest controller for powerdown signal
- * @softreset_ctl: reset controller for softreset signal
- * @mode: drd static host/device config
- */
-struct sti_dwc3_glue_plat {
- phys_addr_t syscfg_base;
- phys_addr_t glue_base;
- phys_addr_t syscfg_offset;
- struct reset_ctl powerdown_ctl;
- struct reset_ctl softreset_ctl;
- enum usb_dr_mode mode;
-};
-
-static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_plat *plat)
-{
- unsigned long val;
-
- val = readl(plat->syscfg_base + plat->syscfg_offset);
-
- val &= USB3_CONTROL_MASK;
-
- switch (plat->mode) {
- case USB_DR_MODE_PERIPHERAL:
- val &= ~(USB3_DELAY_VBUSVALID
- | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
- | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
- | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
-
- val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
- break;
-
- case USB_DR_MODE_HOST:
- val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID
- | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
- | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
- | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
-
- val |= USB3_DELAY_VBUSVALID;
- break;
-
- default:
- pr_err("Unsupported mode of operation %d\n", plat->mode);
- return -EINVAL;
- }
- writel(val, plat->syscfg_base + plat->syscfg_offset);
-
- return 0;
-}
-
-static void sti_dwc3_glue_init(struct sti_dwc3_glue_plat *plat)
-{
- unsigned long reg;
-
- reg = readl(plat->glue_base + CLKRST_CTRL);
-
- reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION;
- reg &= ~SW_PIPEW_RESET_N;
-
- writel(reg, plat->glue_base + CLKRST_CTRL);
-
- /* configure mux for vbus, powerpresent and bvalid signals */
- reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
-
- reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
- SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
- SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG);
-
- writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
-
- setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
-}
-
-static int sti_dwc3_glue_of_to_plat(struct udevice *dev)
-{
- struct sti_dwc3_glue_plat *plat = dev_get_plat(dev);
- struct udevice *syscon;
- struct regmap *regmap;
- int ret;
- u32 reg[4];
-
- ret = ofnode_read_u32_array(dev_ofnode(dev), "reg", reg,
- ARRAY_SIZE(reg));
- if (ret) {
- pr_err("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
- return ret;
- }
-
- plat->glue_base = reg[0];
- plat->syscfg_offset = reg[2];
-
- /* get corresponding syscon phandle */
- ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "st,syscfg",
- &syscon);
- if (ret) {
- pr_err("unable to find syscon device (%d)\n", ret);
- return ret;
- }
-
- /* get syscfg-reg base address */
- regmap = syscon_get_regmap(syscon);
- if (!regmap) {
- pr_err("unable to find regmap\n");
- return -ENODEV;
- }
- plat->syscfg_base = regmap->ranges[0].start;
-
- /* get powerdown reset */
- ret = reset_get_by_name(dev, "powerdown", &plat->powerdown_ctl);
- if (ret) {
- pr_err("can't get powerdown reset for %s (%d)", dev->name, ret);
- return ret;
- }
-
- /* get softreset reset */
- ret = reset_get_by_name(dev, "softreset", &plat->softreset_ctl);
- if (ret)
- pr_err("can't get soft reset for %s (%d)", dev->name, ret);
-
- return ret;
-};
-
-static int sti_dwc3_glue_bind(struct udevice *dev)
-{
- struct sti_dwc3_glue_plat *plat = dev_get_plat(dev);
- ofnode node, dwc3_node;
-
- /* Find snps,dwc3 node from subnode */
- ofnode_for_each_subnode(node, dev_ofnode(dev)) {
- if (ofnode_device_is_compatible(node, "snps,dwc3"))
- dwc3_node = node;
- }
-
- if (!ofnode_valid(dwc3_node)) {
- pr_err("Can't find dwc3 subnode for %s\n", dev->name);
- return -ENODEV;
- }
-
- /* retrieve the DWC3 dual role mode */
- plat->mode = usb_get_dr_mode(dwc3_node);
- if (plat->mode == USB_DR_MODE_UNKNOWN)
- /* by default set dual role mode to HOST */
- plat->mode = USB_DR_MODE_HOST;
-
- return dm_scan_fdt_dev(dev);
-}
-
-static int sti_dwc3_glue_probe(struct udevice *dev)
-{
- struct sti_dwc3_glue_plat *plat = dev_get_plat(dev);
- int ret;
-
- /* deassert both powerdown and softreset */
- ret = reset_deassert(&plat->powerdown_ctl);
- if (ret < 0) {
- pr_err("DWC3 powerdown reset deassert failed: %d", ret);
- return ret;
- }
-
- ret = reset_deassert(&plat->softreset_ctl);
- if (ret < 0) {
- pr_err("DWC3 soft reset deassert failed: %d", ret);
- goto softreset_err;
- }
-
- ret = sti_dwc3_glue_drd_init(plat);
- if (ret)
- goto init_err;
-
- sti_dwc3_glue_init(plat);
-
- return 0;
-
-init_err:
- ret = reset_assert(&plat->softreset_ctl);
- if (ret < 0) {
- pr_err("DWC3 soft reset deassert failed: %d", ret);
- return ret;
- }
-
-softreset_err:
- ret = reset_assert(&plat->powerdown_ctl);
- if (ret < 0)
- pr_err("DWC3 powerdown reset deassert failed: %d", ret);
-
- return ret;
-}
-
-static int sti_dwc3_glue_remove(struct udevice *dev)
-{
- struct sti_dwc3_glue_plat *plat = dev_get_plat(dev);
- int ret;
-
- /* assert both powerdown and softreset */
- ret = reset_assert(&plat->powerdown_ctl);
- if (ret < 0) {
- pr_err("DWC3 powerdown reset deassert failed: %d", ret);
- return ret;
- }
-
- ret = reset_assert(&plat->softreset_ctl);
- if (ret < 0)
- pr_err("DWC3 soft reset deassert failed: %d", ret);
-
- return ret;
-}
-
-static const struct udevice_id sti_dwc3_glue_ids[] = {
- { .compatible = "st,stih407-dwc3" },
- { }
-};
-
-U_BOOT_DRIVER(dwc3_sti_glue) = {
- .name = "dwc3_sti_glue",
- .id = UCLASS_NOP,
- .of_match = sti_dwc3_glue_ids,
- .of_to_plat = sti_dwc3_glue_of_to_plat,
- .probe = sti_dwc3_glue_probe,
- .remove = sti_dwc3_glue_remove,
- .bind = sti_dwc3_glue_bind,
- .plat_auto = sizeof(struct sti_dwc3_glue_plat),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
-};