Discussion:
[U-Boot] [PATCH v4 01/10] usb: gadget: Do not call board_usb_xxx() directly in USB gadget drivers
Jean-Jacques Hiblot
2018-11-29 09:52:41 UTC
Permalink
Add 2 functions to wrap the calls to board_usb_init() and
board_usb_cleanup().
This is a preparatory work for DM support for UDC drivers (DM_USB_GADGET).

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
Reviewed-by: Lukasz Majewski <***@denx.de>

---

Changes in v4: None
Changes in v3: None
Changes in v2:
- Updated commit log
- Fixed typo in thordown.c

cmd/fastboot.c | 4 ++--
cmd/rockusb.c | 4 ++--
cmd/thordown.c | 4 ++--
cmd/usb_gadget_sdp.c | 4 ++--
cmd/usb_mass_storage.c | 4 ++--
common/dfu.c | 6 +++---
drivers/usb/gadget/ether.c | 38 +++++---------------------------------
include/linux/usb/gadget.h | 10 ++++++++++
8 files changed, 28 insertions(+), 46 deletions(-)

diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index ae3a5f6..0be83b7 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -51,7 +51,7 @@ static int do_fastboot_usb(int argc, char *const argv[],
return CMD_RET_FAILURE;
}

- ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+ ret = usb_gadget_initialize(controller_index);
if (ret) {
pr_err("USB init failed: %d\n", ret);
return CMD_RET_FAILURE;
@@ -82,7 +82,7 @@ static int do_fastboot_usb(int argc, char *const argv[],
exit:
g_dnl_unregister();
g_dnl_clear_detach();
- board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+ usb_gadget_release(controller_index);

return ret;
#else
diff --git a/cmd/rockusb.c b/cmd/rockusb.c
index 8206643..e0c1480 100644
--- a/cmd/rockusb.c
+++ b/cmd/rockusb.c
@@ -33,7 +33,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
dev_index = simple_strtoul(devnum, NULL, 0);
rockusb_dev_init(devtype, dev_index);

- ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+ ret = usb_gadget_initialize(controller_index);
if (ret) {
printf("USB init failed: %d\n", ret);
return CMD_RET_FAILURE;
@@ -62,7 +62,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
exit:
g_dnl_unregister();
g_dnl_clear_detach();
- board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+ usb_gadget_release(controller_index);

return ret;
}
diff --git a/cmd/thordown.c b/cmd/thordown.c
index 2615ada..ce3660d 100644
--- a/cmd/thordown.c
+++ b/cmd/thordown.c
@@ -30,7 +30,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
goto done;

int controller_index = simple_strtoul(usb_controller, NULL, 0);
- ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+ ret = usb_gadget_initialize(controller_index);
if (ret) {
pr_err("USB init failed: %d\n", ret);
ret = CMD_RET_FAILURE;
@@ -55,7 +55,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

exit:
g_dnl_unregister();
- board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+ usb_gadget_release(controller_index);
done:
dfu_free_entities();

diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c
index ba1f66a..808ed97 100644
--- a/cmd/usb_gadget_sdp.c
+++ b/cmd/usb_gadget_sdp.c
@@ -20,7 +20,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

char *usb_controller = argv[1];
int controller_index = simple_strtoul(usb_controller, NULL, 0);
- board_usb_init(controller_index, USB_INIT_DEVICE);
+ usb_gadget_initialize(controller_index);

g_dnl_clear_detach();
g_dnl_register("usb_dnl_sdp");
@@ -37,7 +37,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

exit:
g_dnl_unregister();
- board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+ usb_gadget_release(controller_index);

return ret;
}
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
index 0d55114..753ae4f 100644
--- a/cmd/usb_mass_storage.c
+++ b/cmd/usb_mass_storage.c
@@ -160,7 +160,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,

controller_index = (unsigned int)(simple_strtoul(
usb_controller, NULL, 0));
- if (board_usb_init(controller_index, USB_INIT_DEVICE)) {
+ if (usb_gadget_initialize(controller_index)) {
pr_err("Couldn't init USB controller.\n");
rc = CMD_RET_FAILURE;
goto cleanup_ums_init;
@@ -231,7 +231,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
cleanup_register:
g_dnl_unregister();
cleanup_board:
- board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+ usb_gadget_release(controller_index);
cleanup_ums_init:
ums_fini();

diff --git a/common/dfu.c b/common/dfu.c
index 2620d32..44d1484 100644
--- a/common/dfu.c
+++ b/common/dfu.c
@@ -23,9 +23,9 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
bool dfu_reset = false;
int ret, i = 0;

- ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
+ ret = usb_gadget_initialize(usbctrl_index);
if (ret) {
- pr_err("board usb init failed\n");
+ pr_err("usb_gadget_initialize failed\n");
return CMD_RET_FAILURE;
}
g_dnl_clear_detach();
@@ -84,7 +84,7 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
}
exit:
g_dnl_unregister();
- board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
+ usb_gadget_release(usbctrl_index);

if (dfu_reset)
do_reset(NULL, 0, 0, NULL);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 193583b..5a9ffd7 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -100,9 +100,6 @@ struct eth_dev {
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
struct usb_request *stat_req; /* for cdc & rndis status */
-#if CONFIG_IS_ENABLED(DM_USB)
- struct udevice *usb_udev;
-#endif

u8 config;
struct usb_ep *in_ep, *out_ep, *status_ep;
@@ -2336,40 +2333,17 @@ fail:
}

/*-------------------------------------------------------------------------*/
-
-#if CONFIG_IS_ENABLED(DM_USB)
-int dm_usb_init(struct eth_dev *e_dev)
-{
- struct udevice *dev = NULL;
- int ret;
-
- ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
- if (!dev || ret) {
- pr_err("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;
+ int ret;
unsigned long timeout = USB_CONNECT_TIMEOUT;

-#if CONFIG_IS_ENABLED(DM_USB)
- if (dm_usb_init(dev)) {
- pr_err("USB ether not found\n");
- return -ENODEV;
- }
-#else
- board_usb_init(0, USB_INIT_DEVICE);
-#endif
+ ret = usb_gadget_initialize(0);
+ if (ret)
+ return ret;

/* Configure default mac-addresses for the USB ethernet device */
#ifdef CONFIG_USBNET_DEV_ADDR
@@ -2541,9 +2515,7 @@ void _usb_eth_halt(struct ether_priv *priv)
}

usb_gadget_unregister_driver(&priv->eth_driver);
-#if !CONFIG_IS_ENABLED(DM_USB)
- board_usb_cleanup(0, USB_INIT_DEVICE);
-#endif
+ usb_gadget_release(0);
}

#ifndef CONFIG_DM_ETH
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index b824f13..40ca2d3 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -19,6 +19,7 @@
#define __LINUX_USB_GADGET_H

#include <errno.h>
+#include <usb.h>
#include <linux/compat.h>
#include <linux/list.h>

@@ -926,4 +927,13 @@ extern void usb_ep_autoconfig_reset(struct usb_gadget *);

extern int usb_gadget_handle_interrupts(int index);

+static inline int usb_gadget_initialize(int index)
+{
+ return board_usb_init(index, USB_INIT_DEVICE);
+}
+
+static inline int usb_gadget_release(int index)
+{
+ return board_usb_cleanup(index, USB_INIT_DEVICE);
+}
#endif /* __LINUX_USB_GADGET_H */
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:42 UTC
Permalink
Using CONFIG_DM_USB for this purpose prevents using DM_USB for host and not
for device.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
Reviewed-by: Lukasz Majewski <***@denx.de>

---

Changes in v4:
- renamed DM_USB_DEV as DM_USB_GADGET

Changes in v3: None
Changes in v2:
- select DM_USB_DEV by default for zynqmp platforms

arch/arm/Kconfig | 2 ++
drivers/usb/Kconfig | 14 ++++++++++++++
drivers/usb/dwc3/core.c | 3 +--
drivers/usb/dwc3/dwc3-generic.c | 4 ++--
4 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f5d4d39..05b6ebf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -917,6 +917,7 @@ config ARCH_ZYNQMP_R5
select DM_SERIAL
select OF_CONTROL
imply CMD_DM
+ imply DM_USB_GADGET

config ARCH_ZYNQMP
bool "Xilinx ZynqMP based platform"
@@ -933,6 +934,7 @@ config ARCH_ZYNQMP
imply CMD_DM
imply FAT_WRITE
imply MP
+ imply DM_USB_GADGET

config TEGRA
bool "NVIDIA Tegra"
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 03746dd..631fcce 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -52,6 +52,20 @@ config SPL_DM_USB
depends on DM_USB
default y

+config DM_USB_GADGET
+ bool "Enable driver model for USB Gadget"
+ depends on DM_USB
+ help
+ Enable driver model for USB Gadget (Peripheral
+ mode)
+
+config SPL_DM_USB_GADGET
+ bool "Enable driver model for USB Gadget in sPL"
+ depends on SPL_DM_USB
+ help
+ Enable driver model for USB Gadget in SPL
+ (Peripheral mode)
+
source "drivers/usb/host/Kconfig"

source "drivers/usb/dwc3/Kconfig"
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f1ca619..f9d8465 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -789,8 +789,7 @@ MODULE_AUTHOR("Felipe Balbi <***@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");

-#if CONFIG_IS_ENABLED(DM_USB)
-
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
int dwc3_init(struct dwc3 *dwc)
{
int ret;
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 56c9fd6..ad3a116 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -21,8 +21,7 @@
#include "gadget.h"
#include "linux-compat.h"

-DECLARE_GLOBAL_DATA_PTR;
-
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
int usb_gadget_handle_interrupts(int index)
{
struct dwc3 *priv;
@@ -97,6 +96,7 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.priv_auto_alloc_size = sizeof(struct dwc3),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+#endif

static int dwc3_generic_bind(struct udevice *parent)
{
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:44 UTC
Permalink
The driver will be probed when usb_gadget_initialize() is called.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/usb/dwc3/dwc3-generic.c | 7 -------
1 file changed, 7 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 47cc140..681b5c7 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -70,21 +70,14 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
return 0;
}

-static int dwc3_generic_peripheral_bind(struct udevice *dev)
-{
- return device_probe(dev);
-}
-
U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.name = "dwc3-generic-peripheral",
.id = UCLASS_USB_DEV_GENERIC,
.ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
.probe = dwc3_generic_peripheral_probe,
.remove = dwc3_generic_peripheral_remove,
- .bind = dwc3_generic_peripheral_bind,
.platdata_auto_alloc_size = sizeof(struct usb_platdata),
.priv_auto_alloc_size = sizeof(struct dwc3),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
#endif
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:43 UTC
Permalink
When DM_USB_GADGET the platform code for the USB device must be replaced by
calls to a USB device driver.

usb_gadget_initialize() probes the USB device driver.
usb_gadget_release() removes the USB device driver.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
Reviewed-by: Lukasz Majewski <***@denx.de>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/usb/dwc3/dwc3-generic.c | 14 ++-----------
drivers/usb/gadget/udc/udc-core.c | 44 ++++++++++++++++++++++++++++++++++++++-
include/linux/usb/gadget.h | 8 +++++++
3 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index ad3a116..47cc140 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -22,19 +22,9 @@
#include "linux-compat.h"

#if CONFIG_IS_ENABLED(DM_USB_GADGET)
-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
{
- struct dwc3 *priv;
- struct udevice *dev;
- int ret;
-
- ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
- if (!dev || ret) {
- pr_err("No USB device found\n");
- return -ENODEV;
- }
-
- priv = dev_get_priv(dev);
+ struct dwc3 *priv = dev_get_priv(dev);

dwc3_gadget_uboot_handle_interrupt(priv);

diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index f5c30dd..34bea27 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -18,7 +18,8 @@
#include <asm/cache.h>
#include <asm/dma-mapping.h>
#include <common.h>
-
+#include <dm.h>
+#include <dm/device-internal.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>

@@ -351,3 +352,44 @@ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
MODULE_DESCRIPTION("UDC Framework");
MODULE_AUTHOR("Felipe Balbi <***@ti.com>");
MODULE_LICENSE("GPL v2");
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+#define MAX_UDC_DEVICES 4
+static struct udevice *dev_array[MAX_UDC_DEVICES];
+int usb_gadget_initialize(int index)
+{
+ int ret;
+ struct udevice *dev = NULL;
+
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ if (dev_array[index])
+ return 0;
+ ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, index, &dev);
+ if (!dev || ret) {
+ pr_err("No USB device found\n");
+ return -ENODEV;
+ }
+ dev_array[index] = dev;
+ return 0;
+}
+
+int usb_gadget_release(int index)
+{
+ int ret;
+
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
+ if (!ret)
+ dev_array[index] = NULL;
+ return ret;
+}
+
+int usb_gadget_handle_interrupts(int index)
+{
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ return dm_usb_gadget_handle_interrupts(dev_array[index]);
+}
+#endif
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 40ca2d3..497798a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -927,6 +927,12 @@ extern void usb_ep_autoconfig_reset(struct usb_gadget *);

extern int usb_gadget_handle_interrupts(int index);

+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+int usb_gadget_initialize(int index);
+int usb_gadget_release(int index);
+int dm_usb_gadget_handle_interrupts(struct udevice *dev);
+#else
+#include <usb.h>
static inline int usb_gadget_initialize(int index)
{
return board_usb_init(index, USB_INIT_DEVICE);
@@ -936,4 +942,6 @@ static inline int usb_gadget_release(int index)
{
return board_usb_cleanup(index, USB_INIT_DEVICE);
}
+#endif
+
#endif /* __LINUX_USB_GADGET_H */
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:48 UTC
Permalink
This make the driver more generic. At this point this driver can replace
the dwc3-of-simple implementation.
Make the description in the Kconfig more generic too.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/usb/dwc3/Kconfig | 7 +-
drivers/usb/dwc3/dwc3-generic.c | 159 +++++++++++++++++++++++++++++++++-------
2 files changed, 137 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 943b763..bbd8105 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -38,10 +38,11 @@ config USB_DWC3_OMAP
Say 'Y' here if you have one such device

config USB_DWC3_GENERIC
- bool "Xilinx ZynqMP and similar Platforms"
- depends on DM_USB && USB_DWC3
+ bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)"
+ depends on DM_USB && USB_DWC3 && MISC
help
- Some platforms can reuse this DWC3 generic implementation.
+ Select this for Xilinx ZynqMP and similar Platforms.
+ This wrapper supports Host and Peripheral operation modes.

config USB_DWC3_UNIPHIER
bool "DesignWare USB3 Host Support on UniPhier Platforms"
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 7375660..7be0187 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -11,58 +11,85 @@
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
-#include <linux/usb/otg.h>
-#include <linux/compat.h>
+#include <dwc3-uboot.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <malloc.h>
#include <usb.h>
#include "core.h"
#include "gadget.h"
-#include "linux-compat.h"
+#include <reset.h>
+#include <clk.h>

#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+struct dwc3_generic_peripheral {
+ struct dwc3 dwc3;
+ struct phy *phys;
+ int num_phys;
+ fdt_addr_t base;
+};
+
int dm_usb_gadget_handle_interrupts(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;

- dwc3_gadget_uboot_handle_interrupt(priv);
+ dwc3_gadget_uboot_handle_interrupt(dwc3);

return 0;
}

static int dwc3_generic_peripheral_probe(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ int rc;
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
+
+ rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
+ if (rc)
+ return rc;
+
+ dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+ dwc3->regs += DWC3_GLOBALS_REGS_START;
+ dwc3->dev = dev;
+
+ rc = dwc3_init(dwc3);
+ if (rc) {
+ unmap_physmem(dwc3->regs, MAP_NOCACHE);
+ return rc;
+ }

- return dwc3_init(priv);
+ return 0;
}

static int dwc3_generic_peripheral_remove(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;

- dwc3_remove(priv);
+ dwc3_remove(dwc3);
+ dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+ unmap_physmem(dwc3->regs, MAP_NOCACHE);

return 0;
}

static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
int node = dev_of_offset(dev);

- priv->regs = (void *)devfdt_get_addr(dev);
- priv->regs += DWC3_GLOBALS_REGS_START;
+ priv->base = devfdt_get_addr(dev);

- priv->maximum_speed = usb_get_maximum_speed(node);
- if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
+ dwc3->maximum_speed = usb_get_maximum_speed(node);
+ if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) {
pr_err("Invalid usb maximum speed\n");
return -ENODEV;
}

- priv->dr_mode = usb_get_dr_mode(node);
- if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+ dwc3->dr_mode = usb_get_dr_mode(node);
+ if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) {
pr_err("Invalid usb mode setup\n");
return -ENODEV;
}
@@ -76,12 +103,16 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
.probe = dwc3_generic_peripheral_probe,
.remove = dwc3_generic_peripheral_remove,
- .platdata_auto_alloc_size = sizeof(struct usb_platdata),
- .priv_auto_alloc_size = sizeof(struct dwc3),
+ .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral),
};
#endif

-static int dwc3_generic_bind(struct udevice *parent)
+struct dwc3_glue_data {
+ struct clk_bulk clks;
+ struct reset_ctl_bulk resets;
+};
+
+static int dwc3_glue_bind(struct udevice *parent)
{
const void *fdt = gd->fdt_blob;
int node;
@@ -92,29 +123,32 @@ static int dwc3_generic_bind(struct udevice *parent)
const char *name = fdt_get_name(fdt, node, NULL);
enum usb_dr_mode dr_mode;
struct udevice *dev;
- const char *driver;
+ const char *driver = NULL;

debug("%s: subnode name: %s\n", __func__, name);
- if (strncmp(name, "dwc3@", 4))
- continue;

dr_mode = usb_get_dr_mode(node);

switch (dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
debug("%s: dr_mode: OTG or Peripheral\n", __func__);
driver = "dwc3-generic-peripheral";
+#endif
break;
case USB_DR_MODE_HOST:
debug("%s: dr_mode: HOST\n", __func__);
- driver = "dwc3-generic-host";
+ driver = "xhci-dwc3";
break;
default:
debug("%s: unsupported dr_mode\n", __func__);
return -ENODEV;
};

+ if (!driver)
+ continue;
+
ret = device_bind_driver_to_node(parent, driver, name,
offset_to_ofnode(node), &dev);
if (ret) {
@@ -127,7 +161,76 @@ static int dwc3_generic_bind(struct udevice *parent)
return 0;
}

-static const struct udevice_id dwc3_generic_ids[] = {
+static int dwc3_glue_reset_init(struct udevice *dev,
+ struct dwc3_glue_data *glue)
+{
+ int ret;
+
+ ret = reset_get_bulk(dev, &glue->resets);
+ if (ret == -ENOTSUPP)
+ return 0;
+ else if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&glue->resets);
+ if (ret) {
+ reset_release_bulk(&glue->resets);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc3_glue_clk_init(struct udevice *dev,
+ struct dwc3_glue_data *glue)
+{
+ int ret;
+
+ ret = clk_get_bulk(dev, &glue->clks);
+ if (ret == -ENOSYS)
+ return 0;
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable_bulk(&glue->clks);
+ if (ret) {
+ clk_release_bulk(&glue->clks);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int dwc3_glue_probe(struct udevice *dev)
+{
+ struct dwc3_glue_data *glue = dev_get_platdata(dev);
+ int ret;
+
+ ret = dwc3_glue_clk_init(dev, glue);
+ if (ret)
+ return ret;
+
+ ret = dwc3_glue_reset_init(dev, glue);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int dwc3_glue_remove(struct udevice *dev)
+{
+ struct dwc3_glue_data *glue = dev_get_platdata(dev);
+
+ reset_release_bulk(&glue->resets);
+
+ clk_release_bulk(&glue->clks);
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_glue_ids[] = {
{ .compatible = "xlnx,zynqmp-dwc3" },
{ }
};
@@ -135,6 +238,10 @@ static const struct udevice_id dwc3_generic_ids[] = {
U_BOOT_DRIVER(dwc3_generic_wrapper) = {
.name = "dwc3-generic-wrapper",
.id = UCLASS_MISC,
- .of_match = dwc3_generic_ids,
- .bind = dwc3_generic_bind,
+ .of_match = dwc3_glue_ids,
+ .bind = dwc3_glue_bind,
+ .probe = dwc3_glue_probe,
+ .remove = dwc3_glue_remove,
+ .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data),
+
};
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:45 UTC
Permalink
Those operations can be used for peripheral operation as well as host
operation.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>

# Conflicts:
# drivers/usb/dwc3/core.c
# drivers/usb/host/xhci-dwc3.c

---

Changes in v4: None
Changes in v3:
- fixes bug dwc3_setup_phy(): the phy arrays wasn't returned. This was
visible only when the device is removed.
- Stub the DWC3 PHY operations if CONFIG_IS_ENABLED(PHY) is false.
This fixes all build issues but one (evb-rk3328).

Changes in v2: None

drivers/usb/dwc3/core.c | 88 +++++++++++++++++++++++++++++++++++++++-
drivers/usb/host/xhci-dwc3.c | 95 ++++----------------------------------------
include/dwc3-uboot.h | 19 +++++++++
3 files changed, 112 insertions(+), 90 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f9d8465..56e2a04 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -19,7 +19,7 @@
#include <asm/dma-mapping.h>
#include <linux/ioport.h>
#include <dm.h>
-
+#include <generic-phy.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>

@@ -789,6 +789,91 @@ MODULE_AUTHOR("Felipe Balbi <***@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");

+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
+{
+ int i, ret, count;
+ struct phy *usb_phys;
+
+ /* Return if no phy declared */
+ if (!dev_read_prop(dev, "phys", NULL))
+ return 0;
+ count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+ if (count <= 0)
+ return count;
+
+ usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
+ GFP_KERNEL);
+ if (!usb_phys)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_get_by_index(dev, i, &usb_phys[i]);
+ if (ret && ret != -ENOENT) {
+ pr_err("Failed to get USB PHY%d for %s\n",
+ i, dev->name);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_init(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't init USB PHY%d for %s\n",
+ i, dev->name);
+ goto phys_init_err;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_power_on(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't power USB PHY%d for %s\n",
+ i, dev->name);
+ goto phys_poweron_err;
+ }
+ }
+
+ *array = usb_phys;
+ *num_phys = count;
+ return 0;
+
+phys_poweron_err:
+ for (i = count - 1; i >= 0; i--)
+ generic_phy_power_off(&usb_phys[i]);
+
+ for (i = 0; i < count; i++)
+ generic_phy_exit(&usb_phys[i]);
+
+ return ret;
+
+phys_init_err:
+ for (; i >= 0; i--)
+ generic_phy_exit(&usb_phys[i]);
+
+ return ret;
+}
+
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
+{
+ int i, ret;
+
+ for (i = 0; i < num_phys; i++) {
+ if (!generic_phy_valid(&usb_phys[i]))
+ continue;
+
+ ret = generic_phy_power_off(&usb_phys[i]);
+ ret |= generic_phy_exit(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't shutdown USB PHY%d for %s\n",
+ i, dev->name);
+ }
+ }
+
+ return 0;
+}
+#endif
+
#if CONFIG_IS_ENABLED(DM_USB_GADGET)
int dwc3_init(struct dwc3 *dwc)
{
@@ -840,5 +925,4 @@ void dwc3_remove(struct dwc3 *dwc)
dwc3_core_exit(dwc);
kfree(dwc->mem);
}
-
#endif
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index dd0d156..83b9f11 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -12,6 +12,7 @@
#include <fdtdec.h>
#include <generic-phy.h>
#include <usb.h>
+#include <dwc3-uboot.h>

#include "xhci.h"
#include <asm/io.h>
@@ -110,105 +111,21 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val)
}

#if CONFIG_IS_ENABLED(DM_USB)
-static int xhci_dwc3_setup_phy(struct udevice *dev)
-{
- struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
- int i, ret, count;
-
- /* Return if no phy declared */
- if (!dev_read_prop(dev, "phys", NULL))
- return 0;
-
- count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
- if (count <= 0)
- return count;
-
- plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
- GFP_KERNEL);
- if (!plat->usb_phys)
- return -ENOMEM;
-
- for (i = 0; i < count; i++) {
- ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]);
- if (ret && ret != -ENOENT) {
- pr_err("Failed to get USB PHY%d for %s\n",
- i, dev->name);
- return ret;
- }
-
- ++plat->num_phys;
- }
-
- for (i = 0; i < plat->num_phys; i++) {
- ret = generic_phy_init(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't init USB PHY%d for %s\n",
- i, dev->name);
- goto phys_init_err;
- }
- }
-
- for (i = 0; i < plat->num_phys; i++) {
- ret = generic_phy_power_on(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't power USB PHY%d for %s\n",
- i, dev->name);
- goto phys_poweron_err;
- }
- }
-
- return 0;
-
-phys_poweron_err:
- for (; i >= 0; i--)
- generic_phy_power_off(&plat->usb_phys[i]);
-
- for (i = 0; i < plat->num_phys; i++)
- generic_phy_exit(&plat->usb_phys[i]);
-
- return ret;
-
-phys_init_err:
- for (; i >= 0; i--)
- generic_phy_exit(&plat->usb_phys[i]);
-
- return ret;
-}
-
-static int xhci_dwc3_shutdown_phy(struct udevice *dev)
-{
- struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
- int i, ret;
-
- for (i = 0; i < plat->num_phys; i++) {
- if (!generic_phy_valid(&plat->usb_phys[i]))
- continue;
-
- ret = generic_phy_power_off(&plat->usb_phys[i]);
- ret |= generic_phy_exit(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't shutdown USB PHY%d for %s\n",
- i, dev->name);
- }
- }
-
- return 0;
-}
-
static int xhci_dwc3_probe(struct udevice *dev)
{
struct xhci_hcor *hcor;
struct xhci_hccr *hccr;
struct dwc3 *dwc3_reg;
enum usb_dr_mode dr_mode;
+ struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
int ret;

hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev));
hcor = (struct xhci_hcor *)((uintptr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));

- ret = xhci_dwc3_setup_phy(dev);
- if (ret)
+ ret = dwc3_setup_phy(dev, &plat->usb_phys, &plat->num_phys);
+ if (ret && (ret != -ENOTSUPP))
return ret;

dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
@@ -227,7 +144,9 @@ static int xhci_dwc3_probe(struct udevice *dev)

static int xhci_dwc3_remove(struct udevice *dev)
{
- xhci_dwc3_shutdown_phy(dev);
+ struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
+
+ dwc3_shutdown_phy(dev, plat->usb_phys, plat->num_phys);

return xhci_deregister(dev);
}
diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h
index 228ab3b..9941cc3 100644
--- a/include/dwc3-uboot.h
+++ b/include/dwc3-uboot.h
@@ -38,4 +38,23 @@ struct dwc3_device {
int dwc3_uboot_init(struct dwc3_device *dev);
void dwc3_uboot_exit(int index);
void dwc3_uboot_handle_interrupt(int index);
+
+struct phy;
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys);
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys);
+#else
+static inline int dwc3_setup_phy(struct udevice *dev, struct phy **array,
+ int *num_phys)
+{
+ return -ENOTSUPP;
+}
+
+static inline int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys,
+ int num_phys)
+{
+ return -ENOTSUPP;
+}
+#endif
+
#endif /* __DWC3_UBOOT_H_ */
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:47 UTC
Permalink
This is now required because the PHY operations used by xhci-dwc3 are part
of the dwc3 core.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>

---

Changes in v4: None
Changes in v3:
- Fix build issue with evb-rk3328 by enabling CONFIG_USB_DWC3. This has
little impact on the footprint and should not break the runtime as the
xhci-rockchip driver has its own probe function.
Nevertheless this was !!! NOT TESTED !!! by lack of hw

Changes in v2: None

configs/evb-rk3328_defconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index 5b3bb8e..f022163 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -49,6 +49,7 @@ CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYSRESET=y
CONFIG_USB=y
+CONFIG_USB_DWC3=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_EHCI_HCD=y
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:49 UTC
Permalink
The select_dr_mode operation is executed when the glue driver is probed.
The role of this optional function is to configure the operating mode
of the controller at the glue level.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/usb/dwc3/dwc3-generic.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 7be0187..6d9be9b 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -8,6 +8,7 @@
*/

#include <common.h>
+#include <asm-generic/io.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
@@ -110,6 +111,12 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = {
struct dwc3_glue_data {
struct clk_bulk clks;
struct reset_ctl_bulk resets;
+ fdt_addr_t regs;
+};
+
+struct dwc3_glue_ops {
+ void (*select_dr_mode)(struct udevice *dev, int index,
+ enum usb_dr_mode mode);
};

static int dwc3_glue_bind(struct udevice *parent)
@@ -205,9 +212,14 @@ static int dwc3_glue_clk_init(struct udevice *dev,

static int dwc3_glue_probe(struct udevice *dev)
{
+ struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
struct dwc3_glue_data *glue = dev_get_platdata(dev);
+ struct udevice *child = NULL;
+ int index = 0;
int ret;

+ glue->regs = dev_read_addr(dev);
+
ret = dwc3_glue_clk_init(dev, glue);
if (ret)
return ret;
@@ -216,6 +228,20 @@ static int dwc3_glue_probe(struct udevice *dev)
if (ret)
return ret;

+ ret = device_find_first_child(dev, &child);
+ if (ret)
+ return ret;
+
+ while (child) {
+ enum usb_dr_mode dr_mode;
+
+ dr_mode = usb_get_dr_mode(dev_of_offset(child));
+ device_find_next_child(&child);
+ if (ops && ops->select_dr_mode)
+ ops->select_dr_mode(dev, index, dr_mode);
+ index++;
+ }
+
return 0;
}
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:50 UTC
Permalink
The error is:
In file included from include/part.h:10:0,
from include/usb.h:18,
from include/linux/usb/gadget.h:22,
from drivers/usb/dwc3/ep0.c:20:
include/ide.h:62:14: error: unknown type name ‘uchar’
void ide_led(uchar led, uchar status);

Fixing it by including common.h that defines the uchar type.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

drivers/usb/dwc3/ep0.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4f68887..818efb3 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -12,7 +12,7 @@
*
* commit c00552ebaf : Merge 3.18-rc7 into usb-next
*/
-
+#include <common.h>
#include <linux/kernel.h>
#include <linux/list.h>
--
2.7.4
Jean-Jacques Hiblot
2018-11-29 09:52:46 UTC
Permalink
UCLASS_USB_DEV_GENERIC was meant for USB devices connected to host
controllers, not gadget devices.
Adding a new UCLASS for gadget devices alone.

Also move the generic DM code for USB gadgets in a separate file for
clarity.

Signed-off-by: Jean-Jacques Hiblot <***@ti.com>

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

board/sunxi/board.c | 2 +-
drivers/usb/dwc3/dwc3-generic.c | 2 +-
drivers/usb/gadget/ether.c | 2 +-
drivers/usb/gadget/udc/Makefile | 4 +++
drivers/usb/gadget/udc/udc-core.c | 41 --------------------------
drivers/usb/gadget/udc/udc-uclass.c | 58 +++++++++++++++++++++++++++++++++++++
drivers/usb/musb-new/omap2430.c | 2 +-
drivers/usb/musb-new/sunxi.c | 2 +-
include/dm/uclass-id.h | 1 +
9 files changed, 68 insertions(+), 46 deletions(-)
create mode 100644 drivers/usb/gadget/udc/udc-uclass.c

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 64ccbc7..9b36cc7 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -663,7 +663,7 @@ int g_dnl_board_usb_cable_connected(void)
struct phy phy;
int ret;

- ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, 0, &dev);
+ ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
if (ret) {
pr_err("%s: Cannot find USB device\n", __func__);
return ret;
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 681b5c7..7375660 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -72,7 +72,7 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)

U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.name = "dwc3-generic-peripheral",
- .id = UCLASS_USB_DEV_GENERIC,
+ .id = UCLASS_USB_GADGET_GENERIC,
.ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
.probe = dwc3_generic_peripheral_probe,
.remove = dwc3_generic_peripheral_remove,
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 5a9ffd7..3b3d9af 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2671,7 +2671,7 @@ int usb_ether_init(void)
struct udevice *usb_dev;
int ret;

- ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
+ ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev);
if (!usb_dev || ret) {
pr_err("No USB device found\n");
return ret;
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 449339f..38ac2dd 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,4 +2,8 @@
#
# USB peripheral controller drivers

+ifndef CONFIG_$(SPL_)DM_USB_GADGET
obj-$(CONFIG_USB_DWC3_GADGET) += udc-core.o
+endif
+
+obj-$(CONFIG_$(SPL_)DM_USB_GADGET) += udc-uclass.o udc-core.o
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index 34bea27..62b4778 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -352,44 +352,3 @@ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
MODULE_DESCRIPTION("UDC Framework");
MODULE_AUTHOR("Felipe Balbi <***@ti.com>");
MODULE_LICENSE("GPL v2");
-
-#if CONFIG_IS_ENABLED(DM_USB_GADGET)
-#define MAX_UDC_DEVICES 4
-static struct udevice *dev_array[MAX_UDC_DEVICES];
-int usb_gadget_initialize(int index)
-{
- int ret;
- struct udevice *dev = NULL;
-
- if (index < 0 || index >= ARRAY_SIZE(dev_array))
- return -EINVAL;
- if (dev_array[index])
- return 0;
- ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, index, &dev);
- if (!dev || ret) {
- pr_err("No USB device found\n");
- return -ENODEV;
- }
- dev_array[index] = dev;
- return 0;
-}
-
-int usb_gadget_release(int index)
-{
- int ret;
-
- if (index < 0 || index >= ARRAY_SIZE(dev_array))
- return -EINVAL;
- ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
- if (!ret)
- dev_array[index] = NULL;
- return ret;
-}
-
-int usb_gadget_handle_interrupts(int index)
-{
- if (index < 0 || index >= ARRAY_SIZE(dev_array))
- return -EINVAL;
- return dm_usb_gadget_handle_interrupts(dev_array[index]);
-}
-#endif
diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c
new file mode 100644
index 0000000..0620518
--- /dev/null
+++ b/drivers/usb/gadget/udc/udc-uclass.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <***@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/usb/gadget.h>
+
+#define MAX_UDC_DEVICES 4
+static struct udevice *dev_array[MAX_UDC_DEVICES];
+int usb_gadget_initialize(int index)
+{
+ int ret;
+ struct udevice *dev = NULL;
+
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ if (dev_array[index])
+ return 0;
+ ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev);
+ if (!dev || ret) {
+ pr_err("No USB device found\n");
+ return -ENODEV;
+ }
+ dev_array[index] = dev;
+ return 0;
+}
+
+int usb_gadget_release(int index)
+{
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+ int ret;
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+
+ ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
+ if (!ret)
+ dev_array[index] = NULL;
+ return ret;
+#else
+ return -ENOTSUPP;
+#endif
+}
+
+int usb_gadget_handle_interrupts(int index)
+{
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ return dm_usb_gadget_handle_interrupts(dev_array[index]);
+}
+
+UCLASS_DRIVER(usb_gadget_generic) = {
+ .id = UCLASS_USB_GADGET_GENERIC,
+ .name = "usb_gadget_generic",
+};
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 58aed72..32743aa 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -263,7 +263,7 @@ U_BOOT_DRIVER(omap2430_musb) = {
#ifdef CONFIG_USB_MUSB_HOST
.id = UCLASS_USB,
#else
- .id = UCLASS_USB_DEV_GENERIC,
+ .id = UCLASS_USB_GADGET_GENERIC,
#endif
.of_match = omap2430_musb_ids,
.ofdata_to_platdata = omap2430_musb_ofdata_to_platdata,
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 6cf9826..d7170a3 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -535,7 +535,7 @@ U_BOOT_DRIVER(usb_musb) = {
#ifdef CONFIG_USB_MUSB_HOST
.id = UCLASS_USB,
#else
- .id = UCLASS_USB_DEV_GENERIC,
+ .id = UCLASS_USB_GADGET_GENERIC,
#endif
.of_match = sunxi_musb_ids,
.probe = musb_usb_probe,
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index c91dca1..1601100 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -92,6 +92,7 @@ enum uclass_id {
UCLASS_USB, /* USB bus */
UCLASS_USB_DEV_GENERIC, /* USB generic device */
UCLASS_USB_HUB, /* USB hub */
+ UCLASS_USB_GADGET_GENERIC, /* USB generic device */
UCLASS_VIDEO, /* Video or LCD device */
UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */
UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */
--
2.7.4
Simon Glass
2018-12-11 01:03:59 UTC
Permalink
Hi Jean-Jacques,
Post by Jean-Jacques Hiblot
UCLASS_USB_DEV_GENERIC was meant for USB devices connected to host
controllers, not gadget devices.
Adding a new UCLASS for gadget devices alone.
Also move the generic DM code for USB gadgets in a separate file for
clarity.
---
Changes in v4: None
Changes in v3: None
Changes in v2: None
board/sunxi/board.c | 2 +-
drivers/usb/dwc3/dwc3-generic.c | 2 +-
drivers/usb/gadget/ether.c | 2 +-
drivers/usb/gadget/udc/Makefile | 4 +++
drivers/usb/gadget/udc/udc-core.c | 41 --------------------------
drivers/usb/gadget/udc/udc-uclass.c | 58 +++++++++++++++++++++++++++++++++++++
drivers/usb/musb-new/omap2430.c | 2 +-
drivers/usb/musb-new/sunxi.c | 2 +-
include/dm/uclass-id.h | 1 +
9 files changed, 68 insertions(+), 46 deletions(-)
create mode 100644 drivers/usb/gadget/udc/udc-uclass.c
We should have a test for this, with a sandbox driver for this uclass,
as we have done for UCLASS_USB.

Regards,
Simon

Loic Devulder
2018-12-06 20:56:59 UTC
Permalink
Hi,

I re-tested this series on Khadas VIM1 and it still fix the USB issue I
had with 'usb reset' (I already tested v2 patches).

I just have a message and I'm not sure that I had it last time:
"Error disabling PHY supply
Can't shutdown USB PHY1 for ***@c9000000"

But USB stack looks ok, I can plug/unplug USB key and do the reset, all
works as expected.

Since my last test lot of changes has been done in Amlogic SoCs, maybe
it's because of this?

So if you want you can add my tested-by flag.
This series aims at bringing improvements to the dwc3_generic driver so
that it can be used by most of the platforms using the dwc3 controller.
I tested this on with DRA7 and AM57x platforms for both Peripheral and Host
operations. The code to enable DM USB host & dev support for those
platforms will be submitted in a separate series.
" I have tested it on zcu100 with usb stick, usb to ethernet converter and
also dfu.
- use separate Kconfig option for DM USB Periphal and DM USB Host. This
allow platforms to keep their non-DM USB peripheral code and use the DM
USB host.
- fixes the bind/probe confusion in dwc3_generic. The probe is done when
the USB device is first needed.
- handles PHYs when in the peripheral mode. The code to handle the PHYs is
shared with the host side
- handles clock and reset
- bind host controller to the more generic driver 'xhci-dwc3'
- rebased on latest U-Boot
- renamed DM_USB_DEV as DM_USB_GADGET
- Add a new commit to create a new UCLASS for USB gadget drivers
- fixes bug dwc3_setup_phy(): the phy arrays wasn't returned. This was
visible only when the device is removed.
- Stub the DWC3 PHY operations if CONFIG_IS_ENABLED(PHY) is false.
This fixes all build issues but one (evb-rk3328).
- Fix build issue with evb-rk3328 by enabling CONFIG_USB_DWC3. This has
little impact on the footprint and should not break the runtime as the
xhci-rockchip driver has its own probe function.
Nevertheless this was !!! NOT TESTED !!! by lack of hw
- Updated commit log
- Fixed typo in thordown.c
- select DM_USB_DEV by default for zynqmp platforms
usb: gadget: Do not call board_usb_xxx() directly in USB gadget
drivers
usb: introduce a separate config option for DM USB device
usb: udc: implement DM versions of
usb_gadget_initialize()/_release()/_handle_interrupt()
dwc3_generic: do not probe the USB device driver when it's bound
dwc3: move phy operation to core.c
dm: usb: create a new UCLASS ID for USB gadget devices
configs: evb-rk3328: Enable CONFIG_USB_DWC3
dwc3-generic: Handle the PHYs, the clocks and the reset lines
dwc3-generic: Add select_dr_mode operation
usb: dwc3: Fix a compilation error with the edison defconfig
arch/arm/Kconfig | 2 +
board/sunxi/board.c | 2 +-
cmd/fastboot.c | 4 +-
cmd/rockusb.c | 4 +-
cmd/thordown.c | 4 +-
cmd/usb_gadget_sdp.c | 4 +-
cmd/usb_mass_storage.c | 4 +-
common/dfu.c | 6 +-
configs/evb-rk3328_defconfig | 1 +
drivers/usb/Kconfig | 14 +++
drivers/usb/dwc3/Kconfig | 7 +-
drivers/usb/dwc3/core.c | 89 ++++++++++++++-
drivers/usb/dwc3/dwc3-generic.c | 208 ++++++++++++++++++++++++++++--------
drivers/usb/dwc3/ep0.c | 2 +-
drivers/usb/gadget/ether.c | 40 ++-----
drivers/usb/gadget/udc/Makefile | 4 +
drivers/usb/gadget/udc/udc-core.c | 3 +-
drivers/usb/gadget/udc/udc-uclass.c | 58 ++++++++++
drivers/usb/host/xhci-dwc3.c | 95 ++--------------
drivers/usb/musb-new/omap2430.c | 2 +-
drivers/usb/musb-new/sunxi.c | 2 +-
include/dm/uclass-id.h | 1 +
include/dwc3-uboot.h | 19 ++++
include/linux/usb/gadget.h | 18 ++++
24 files changed, 401 insertions(+), 192 deletions(-)
create mode 100644 drivers/usb/gadget/udc/udc-uclass.c
--
Loic Devulder <***@suse.com> | ***@irc
0x175A963893C85F55 | D220 DEF5 56A3 DE00 9DAA 78BA 175A 9638 93C8 5F55
Senior QA Engineer | Container & Storage Solutions Quality Assurance
team (qa-css)
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nuernberg, Germany
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB,
21284 (AG Nuernberg)
Jean-Jacques Hiblot
2018-12-07 07:46:14 UTC
Permalink
Post by Loic Devulder
Hi,
I re-tested this series on Khadas VIM1 and it still fix the USB issue I
had with 'usb reset' (I already tested v2 patches).
"Error disabling PHY supply
But USB stack looks ok, I can plug/unplug USB key and do the reset, all
works as expected.
Since my last test lot of changes has been done in Amlogic SoCs, maybe
it's because of this?
So if you want you can add my tested-by flag.
Thank you for testing
Post by Loic Devulder
This series aims at bringing improvements to the dwc3_generic driver so
that it can be used by most of the platforms using the dwc3 controller.
I tested this on with DRA7 and AM57x platforms for both Peripheral and Host
operations. The code to enable DM USB host & dev support for those
platforms will be submitted in a separate series.
" I have tested it on zcu100 with usb stick, usb to ethernet converter and
also dfu.
- use separate Kconfig option for DM USB Periphal and DM USB Host. This
allow platforms to keep their non-DM USB peripheral code and use the DM
USB host.
- fixes the bind/probe confusion in dwc3_generic. The probe is done when
the USB device is first needed.
- handles PHYs when in the peripheral mode. The code to handle the PHYs is
shared with the host side
- handles clock and reset
- bind host controller to the more generic driver 'xhci-dwc3'
- rebased on latest U-Boot
- renamed DM_USB_DEV as DM_USB_GADGET
- Add a new commit to create a new UCLASS for USB gadget drivers
- fixes bug dwc3_setup_phy(): the phy arrays wasn't returned. This was
visible only when the device is removed.
- Stub the DWC3 PHY operations if CONFIG_IS_ENABLED(PHY) is false.
This fixes all build issues but one (evb-rk3328).
- Fix build issue with evb-rk3328 by enabling CONFIG_USB_DWC3. This has
little impact on the footprint and should not break the runtime as the
xhci-rockchip driver has its own probe function.
Nevertheless this was !!! NOT TESTED !!! by lack of hw
- Updated commit log
- Fixed typo in thordown.c
- select DM_USB_DEV by default for zynqmp platforms
usb: gadget: Do not call board_usb_xxx() directly in USB gadget
drivers
usb: introduce a separate config option for DM USB device
usb: udc: implement DM versions of
usb_gadget_initialize()/_release()/_handle_interrupt()
dwc3_generic: do not probe the USB device driver when it's bound
dwc3: move phy operation to core.c
dm: usb: create a new UCLASS ID for USB gadget devices
configs: evb-rk3328: Enable CONFIG_USB_DWC3
dwc3-generic: Handle the PHYs, the clocks and the reset lines
dwc3-generic: Add select_dr_mode operation
usb: dwc3: Fix a compilation error with the edison defconfig
arch/arm/Kconfig | 2 +
board/sunxi/board.c | 2 +-
cmd/fastboot.c | 4 +-
cmd/rockusb.c | 4 +-
cmd/thordown.c | 4 +-
cmd/usb_gadget_sdp.c | 4 +-
cmd/usb_mass_storage.c | 4 +-
common/dfu.c | 6 +-
configs/evb-rk3328_defconfig | 1 +
drivers/usb/Kconfig | 14 +++
drivers/usb/dwc3/Kconfig | 7 +-
drivers/usb/dwc3/core.c | 89 ++++++++++++++-
drivers/usb/dwc3/dwc3-generic.c | 208 ++++++++++++++++++++++++++++--------
drivers/usb/dwc3/ep0.c | 2 +-
drivers/usb/gadget/ether.c | 40 ++-----
drivers/usb/gadget/udc/Makefile | 4 +
drivers/usb/gadget/udc/udc-core.c | 3 +-
drivers/usb/gadget/udc/udc-uclass.c | 58 ++++++++++
drivers/usb/host/xhci-dwc3.c | 95 ++--------------
drivers/usb/musb-new/omap2430.c | 2 +-
drivers/usb/musb-new/sunxi.c | 2 +-
include/dm/uclass-id.h | 1 +
include/dwc3-uboot.h | 19 ++++
include/linux/usb/gadget.h | 18 ++++
24 files changed, 401 insertions(+), 192 deletions(-)
create mode 100644 drivers/usb/gadget/udc/udc-uclass.c
Loading...